6933331: (d3d/ogl) java.lang.IllegalStateException: Buffers have not been created
authorserb
Sat, 18 May 2019 23:35:40 -0700
changeset 55172 1a80806e7d15
parent 55171 9ee0b8733ee4
child 55173 f36cee599800
6933331: (d3d/ogl) java.lang.IllegalStateException: Buffers have not been created Reviewed-by: prr
src/java.desktop/share/classes/java/awt/Component.java
test/jdk/java/awt/image/BufferStrategy/ExceptionAfterComponentDispose.java
--- a/src/java.desktop/share/classes/java/awt/Component.java	Fri May 17 22:48:03 2019 -0700
+++ b/src/java.desktop/share/classes/java/awt/Component.java	Sat May 18 23:35:40 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -352,7 +352,7 @@
      * @see java.awt.image.BufferStrategy
      * @see #getBufferStrategy()
      */
-    transient BufferStrategy bufferStrategy = null;
+    private transient BufferStrategy bufferStrategy = null;
 
     /**
      * True when the object should ignore all repaint events.
@@ -4038,12 +4038,12 @@
          /**
           * The width of the back buffers
           */
-        int width;
+        private int width;
 
         /**
          * The height of the back buffers
          */
-        int height;
+        private int height;
 
         /**
          * Creates a new flipping buffer strategy for this component.
@@ -4116,9 +4116,7 @@
 
             if (drawBuffer != null) {
                 // dispose the existing backbuffers
-                drawBuffer = null;
-                drawVBuffer = null;
-                destroyBuffers();
+                invalidate();
                 // ... then recreate the backbuffers
             }
 
@@ -4206,6 +4204,15 @@
         }
 
         /**
+         * Destroys the buffers and invalidates the state of FlipBufferStrategy.
+         */
+        private void invalidate() {
+            drawBuffer = null;
+            drawVBuffer = null;
+            destroyBuffers();
+        }
+
+        /**
          * Destroys the buffers created through this object
          */
         protected void destroyBuffers() {
@@ -4244,14 +4251,11 @@
          * Restore the drawing buffer if it has been lost
          */
         protected void revalidate() {
-            revalidate(true);
-        }
-
-        void revalidate(boolean checkSize) {
             validatedContents = false;
-
-            if (checkSize && (getWidth() != width || getHeight() != height)) {
-                // component has been resized; recreate the backbuffers
+            if (getWidth() != width || getHeight() != height
+                    || drawBuffer == null) {
+                // component has been resized or the peer was recreated;
+                // recreate the backbuffers
                 try {
                     createBuffers(numBuffers, caps);
                 } catch (AWTException e) {
@@ -4329,7 +4333,7 @@
             if (Component.this.bufferStrategy == this) {
                 Component.this.bufferStrategy = null;
                 if (peer != null) {
-                    destroyBuffers();
+                    invalidate();
                 }
             }
         }
@@ -7156,7 +7160,7 @@
                 boolean isLightweight = isLightweight();
 
                 if (bufferStrategy instanceof FlipBufferStrategy) {
-                    ((FlipBufferStrategy)bufferStrategy).destroyBuffers();
+                    ((FlipBufferStrategy)bufferStrategy).invalidate();
                 }
 
                 if (dropTarget != null) dropTarget.removeNotify();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/image/BufferStrategy/ExceptionAfterComponentDispose.java	Sat May 18 23:35:40 2019 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Canvas;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.image.BufferStrategy;
+import java.util.List;
+
+import javax.swing.JFrame;
+
+/**
+ * @test
+ * @bug 6933331
+ * @key headful
+ * @summary Tests that BufferStrategy works after the peer is recreated
+ */
+public final class ExceptionAfterComponentDispose {
+
+    public static void main(final String[] args) throws Exception {
+        // Will check Canvas on the main thread
+        for (int size = -3; size < 3; ++size) {
+            for (int numBuffers = 1; numBuffers < 3; ++numBuffers) {
+                testCanvas(size, numBuffers);
+            }
+        }
+        // Will check JFrame on EDT
+        EventQueue.invokeAndWait(() -> {
+            for (int size = -3; size < 3; ++size) {
+                for (int numBuffers = 1; numBuffers < 3; ++numBuffers) {
+                    testJFrame(size, numBuffers);
+                }
+            }
+        });
+    }
+
+    private static void testCanvas(final int size, final int numBuffers) {
+        final Frame frame = new Frame();
+        try {
+            final Canvas canvas = new Canvas();
+            frame.setLayout(null); // we would like to control the size
+            frame.add(canvas);
+            frame.pack(); // creates a peer
+            canvas.setSize(size, size);
+
+            // BufferStrategy works when the peer just created
+            canvas.createBufferStrategy(numBuffers);
+            final BufferStrategy bs = canvas.getBufferStrategy();
+            if (bs.getDrawGraphics() == null) {
+                throw new RuntimeException("DrawGraphics is null");
+            }
+
+            // BufferStrategy should work when the peer is recreated
+            frame.dispose();
+            frame.pack();
+            if (canvas.getBufferStrategy() != bs) {
+                throw new RuntimeException("BS was changed");
+            }
+            if (bs.getDrawGraphics() == null) {
+                throw new RuntimeException("DrawGraphics is null");
+            }
+        } finally {
+            frame.dispose();
+        }
+    }
+
+    private static void testJFrame(final int size, final int numBuffers) {
+        for (final boolean undecorated : List.of(true, false)) {
+            final JFrame frame = new JFrame();
+            try {
+                frame.setUndecorated(undecorated);
+                frame.pack(); // creates a peer
+                frame.setSize(size, size);
+
+                // BufferStrategy works when the peer just created
+                frame.createBufferStrategy(numBuffers);
+                final BufferStrategy bs = frame.getBufferStrategy();
+                if (bs.getDrawGraphics() == null) {
+                    throw new RuntimeException("DrawGraphics is null");
+                }
+
+                // BufferStrategy should work when the peer is recreated
+                frame.dispose();
+                frame.pack();
+                if (frame.getBufferStrategy() != bs) {
+                    throw new RuntimeException("BS was changed");
+                }
+                if (bs.getDrawGraphics() == null) {
+                    throw new RuntimeException("DrawGraphics is null");
+                }
+            } finally {
+                frame.dispose();
+            }
+        }
+    }
+}