1 /*
   2  * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 6366359
  27  * @summary Test that we don't crash when changing from 8 to 16/32 bit modes
  28  * @author Dmitri.Trembovetski@Sun.COM area=FullScreen
  29  * @run main/othervm/timeout=200 DisplayChangeVITest
  30  * @run main/othervm/timeout=200 -Dsun.java2d.d3d=false DisplayChangeVITest
  31  * @run main/othervm/timeout=200 -Dsun.java2d.opengl=true DisplayChangeVITest
  32  * @key randomness
  33  */
  34 
  35 import java.awt.Color;
  36 import java.awt.DisplayMode;
  37 import java.awt.Graphics;
  38 import java.awt.GraphicsDevice;
  39 import java.awt.GraphicsEnvironment;
  40 import java.awt.event.KeyAdapter;
  41 import java.awt.event.KeyEvent;
  42 import java.awt.image.BufferedImage;
  43 import java.awt.image.VolatileImage;
  44 import java.lang.Exception;
  45 import java.lang.Thread;
  46 import java.util.ArrayList;
  47 import java.util.Random;
  48 import javax.swing.JFrame;
  49 
  50 /**
  51  * The test enters fullscreen mode (if it's supported) and then tries
  52  * to switch between display moes with different depths and dimensions
  53  * while doing both rendering to the screen (via a VolatileImage)
  54  * and Swing repainting just to make things more chaotic.
  55  *
  56  * The procedure is repeated TEST_REPS times (3 by default).
  57  *
  58  * Don't pay attention to what happens on the screen, it won't be pretty.
  59  * If the test doesn't crash or throw exceptions, it passes, otherwise
  60  * it fails.
  61  */
  62 public class DisplayChangeVITest extends JFrame implements Runnable {
  63 
  64     private final Random rnd = new Random();
  65     private VolatileImage bb;
  66     private BufferedImage sprite;
  67     private VolatileImage volSprite;
  68 
  69     private static boolean done = false;
  70     private static final Object lock = new Object();
  71     private static final int TEST_REPS = 3;
  72 
  73     private ArrayList<DisplayMode> dms;
  74 
  75     DisplayChangeVITest() {
  76         selectDisplayModes();
  77         addKeyListener(new KeyAdapter() {
  78             public void keyPressed(KeyEvent e) {
  79                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
  80                     synchronized (lock) {
  81                         done = true;
  82                     }
  83                 }
  84             }
  85         });
  86         sprite = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  87         sprite.getRaster().getDataBuffer();
  88         Graphics g = sprite.getGraphics();
  89         g.setColor(Color.yellow);
  90         g.fillRect(0, 0, sprite.getWidth(), sprite.getHeight());
  91     }
  92 
  93     void render(Graphics g) {
  94         do {
  95             // volatile images validated here
  96             initBackbuffer();
  97 
  98             g.setColor(Color.black);
  99             g.fillRect(0, 0, getWidth(), getHeight());
 100 
 101             Graphics gg = bb.getGraphics();
 102             gg.setColor(new Color(rnd.nextInt(0x00ffffff)));
 103             gg.fillRect(0, 0, bb.getWidth(), bb.getHeight());
 104             for (int x = 0; x < 10; x++) {
 105                 gg.drawImage(sprite, x*200, 0, null);
 106                 gg.drawImage(volSprite, x*200, 500, null);
 107             }
 108 
 109             g.drawImage(bb, 0, 0, null);
 110         } while (bb.contentsLost());
 111     }
 112 
 113     private static void sleep(long msec) {
 114         try { Thread.sleep(msec); } catch (InterruptedException e) {}
 115     }
 116 
 117     private int reps = 0;
 118     public void run() {
 119         GraphicsDevice gd = getGraphicsConfiguration().getDevice();
 120         if (gd.isDisplayChangeSupported() && dms.size() > 0) {
 121             while (!done && reps++ < TEST_REPS) {
 122                 for (DisplayMode dm : dms) {
 123                     System.err.printf("Entering DisplayMode[%dx%dx%d]\n",
 124                         dm.getWidth(), dm.getHeight(), dm.getBitDepth());
 125                     gd.setDisplayMode(dm);
 126 
 127                     initBackbuffer();
 128                     for (int i = 0; i < 10; i++) {
 129                         // render to the screen
 130                         render(getGraphics());
 131                         // ask Swing to repaint
 132                         repaint();
 133                         sleep(100);
 134                     }
 135                     sleep(1500);
 136                 }
 137             }
 138         } else {
 139             System.err.println("Display mode change " +
 140                                "not supported. Test passed.");
 141         }
 142         dispose();
 143         synchronized (lock) {
 144             done = true;
 145             lock.notify();
 146         }
 147     }
 148 
 149     private void createBackbuffer() {
 150         if (bb == null ||
 151             bb.getWidth() != getWidth() || bb.getHeight() != getHeight())
 152         {
 153             bb = createVolatileImage(getWidth(), getHeight());
 154         }
 155     }
 156 
 157     private void initBackbuffer() {
 158         createBackbuffer();
 159 
 160         int res = bb.validate(getGraphicsConfiguration());
 161         if (res == VolatileImage.IMAGE_INCOMPATIBLE) {
 162             bb = null;
 163             createBackbuffer();
 164             bb.validate(getGraphicsConfiguration());
 165             res = VolatileImage.IMAGE_RESTORED;
 166         }
 167         if (res == VolatileImage.IMAGE_RESTORED) {
 168             Graphics g = bb.getGraphics();
 169             g.setColor(new Color(rnd.nextInt(0x00ffffff)));
 170             g.fillRect(0, 0, bb.getWidth(), bb.getHeight());
 171 
 172             volSprite = createVolatileImage(100, 100);
 173         }
 174         volSprite.validate(getGraphicsConfiguration());
 175     }
 176 
 177     private void selectDisplayModes() {
 178         GraphicsDevice gd =
 179             GraphicsEnvironment.getLocalGraphicsEnvironment().
 180                 getDefaultScreenDevice();
 181         dms = new ArrayList<DisplayMode>();
 182         DisplayMode dmArray[] = gd.getDisplayModes();
 183         boolean found8 = false, found16 = false,
 184                 found24 = false, found32 = false;
 185         for (DisplayMode dm : dmArray) {
 186             if (!found8 &&
 187                 (dm.getBitDepth() == 8 ||
 188                  dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI)  &&
 189                 (dm.getWidth() >= 800 && dm.getWidth() < 1024))
 190             {
 191                 dms.add(dm);
 192                 found8 = true;
 193                 continue;
 194             }
 195             if (!found32 &&
 196                 (dm.getBitDepth() == 32 ||
 197                  dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI)  &&
 198                 dm.getWidth() >= 1280)
 199             {
 200                 dms.add(dm);
 201                 found32 = true;
 202                 continue;
 203             }
 204             if (!found16 &&
 205                dm.getBitDepth() == 16 &&
 206                 (dm.getWidth() >= 1024 && dm.getWidth() < 1280))
 207             {
 208                 dms.add(dm);
 209                 found16 = true;
 210                 continue;
 211             }
 212             if (found8 && found16 && found32) {
 213                 break;
 214             }
 215         }
 216         System.err.println("Found display modes:");
 217         for (DisplayMode dm : dms) {
 218             System.err.printf("DisplayMode[%dx%dx%d]\n",
 219                 dm.getWidth(), dm.getHeight(), dm.getBitDepth());
 220         }
 221     }
 222 
 223     public static void main(String[] args) throws Exception {
 224         DisplayChangeVITest test = new DisplayChangeVITest();
 225         GraphicsDevice gd =
 226             GraphicsEnvironment.getLocalGraphicsEnvironment().
 227                 getDefaultScreenDevice();
 228         if (gd.isFullScreenSupported()) {
 229             gd.setFullScreenWindow(test);
 230             Thread t = new Thread(test);
 231             t.run();
 232             synchronized (lock) {
 233                 while (!done) {
 234                     try {
 235                         lock.wait(50);
 236                     } catch (InterruptedException ex) {
 237                         ex.printStackTrace();
 238                     }
 239                 }
 240             }
 241             System.err.println("Test Passed.");
 242         } else {
 243             System.err.println("Full screen not supported. Test passed.");
 244         }
 245     }
 246 }