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  */
  33 
  34 import java.awt.Color;
  35 import java.awt.DisplayMode;
  36 import java.awt.Graphics;
  37 import java.awt.GraphicsDevice;
  38 import java.awt.GraphicsEnvironment;
  39 import java.awt.event.KeyAdapter;
  40 import java.awt.event.KeyEvent;
  41 import java.awt.image.BufferedImage;
  42 import java.awt.image.VolatileImage;
  43 import java.lang.Exception;
  44 import java.lang.Thread;
  45 import java.util.ArrayList;
  46 import java.util.Random;
  47 import javax.swing.JFrame;
  48 
  49 /**
  50  * The test enters fullscreen mode (if it's supported) and then tries
  51  * to switch between display moes with different depths and dimensions
  52  * while doing both rendering to the screen (via a VolatileImage)
  53  * and Swing repainting just to make things more chaotic.
  54  *
  55  * The procedure is repeated TEST_REPS times (3 by default).
  56  *
  57  * Don't pay attention to what happens on the screen, it won't be pretty.
  58  * If the test doesn't crash or throw exceptions, it passes, otherwise
  59  * it fails.
  60  */
  61 public class DisplayChangeVITest extends JFrame implements Runnable {
  62 
  63     private final Random rnd = new Random();
  64     private VolatileImage bb;
  65     private BufferedImage sprite;
  66     private VolatileImage volSprite;
  67 
  68     private static boolean done = false;
  69     private static final Object lock = new Object();
  70     private static final int TEST_REPS = 3;
  71 
  72     private ArrayList<DisplayMode> dms;
  73 
  74     DisplayChangeVITest() {
  75         selectDisplayModes();
  76         addKeyListener(new KeyAdapter() {
  77             public void keyPressed(KeyEvent e) {
  78                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
  79                     synchronized (lock) {
  80                         done = true;
  81                     }
  82                 }
  83             }
  84         });
  85         sprite = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  86         sprite.getRaster().getDataBuffer();
  87         Graphics g = sprite.getGraphics();
  88         g.setColor(Color.yellow);
  89         g.fillRect(0, 0, sprite.getWidth(), sprite.getHeight());
  90     }
  91 
  92     void render(Graphics g) {
  93         do {
  94             // volatile images validated here
  95             initBackbuffer();
  96 
  97             g.setColor(Color.black);
  98             g.fillRect(0, 0, getWidth(), getHeight());
  99 
 100             Graphics gg = bb.getGraphics();
 101             gg.setColor(new Color(rnd.nextInt(0x00ffffff)));
 102             gg.fillRect(0, 0, bb.getWidth(), bb.getHeight());
 103             for (int x = 0; x < 10; x++) {
 104                 gg.drawImage(sprite, x*200, 0, null);
 105                 gg.drawImage(volSprite, x*200, 500, null);
 106             }
 107 
 108             g.drawImage(bb, 0, 0, null);
 109         } while (bb.contentsLost());
 110     }
 111 
 112     private static void sleep(long msec) {
 113         try { Thread.sleep(msec); } catch (InterruptedException e) {}
 114     }
 115 
 116     private int reps = 0;
 117     public void run() {
 118         GraphicsDevice gd = getGraphicsConfiguration().getDevice();
 119         if (gd.isDisplayChangeSupported() && dms.size() > 0) {
 120             while (!done && reps++ < TEST_REPS) {
 121                 for (DisplayMode dm : dms) {
 122                     System.err.printf("Entering DisplayMode[%dx%dx%d]\n",
 123                         dm.getWidth(), dm.getHeight(), dm.getBitDepth());
 124                     gd.setDisplayMode(dm);
 125 
 126                     initBackbuffer();
 127                     for (int i = 0; i < 10; i++) {
 128                         // render to the screen
 129                         render(getGraphics());
 130                         // ask Swing to repaint
 131                         repaint();
 132                         sleep(100);
 133                     }
 134                     sleep(1500);
 135                 }
 136             }
 137         } else {
 138             System.err.println("Display mode change " +
 139                                "not supported. Test passed.");
 140         }
 141         dispose();
 142         synchronized (lock) {
 143             done = true;
 144             lock.notify();
 145         }
 146     }
 147 
 148     private void createBackbuffer() {
 149         if (bb == null ||
 150             bb.getWidth() != getWidth() || bb.getHeight() != getHeight())
 151         {
 152             bb = createVolatileImage(getWidth(), getHeight());
 153         }
 154     }
 155 
 156     private void initBackbuffer() {
 157         createBackbuffer();
 158 
 159         int res = bb.validate(getGraphicsConfiguration());
 160         if (res == VolatileImage.IMAGE_INCOMPATIBLE) {
 161             bb = null;
 162             createBackbuffer();
 163             bb.validate(getGraphicsConfiguration());
 164             res = VolatileImage.IMAGE_RESTORED;
 165         }
 166         if (res == VolatileImage.IMAGE_RESTORED) {
 167             Graphics g = bb.getGraphics();
 168             g.setColor(new Color(rnd.nextInt(0x00ffffff)));
 169             g.fillRect(0, 0, bb.getWidth(), bb.getHeight());
 170 
 171             volSprite = createVolatileImage(100, 100);
 172         }
 173         volSprite.validate(getGraphicsConfiguration());
 174     }
 175 
 176     private void selectDisplayModes() {
 177         GraphicsDevice gd =
 178             GraphicsEnvironment.getLocalGraphicsEnvironment().
 179                 getDefaultScreenDevice();
 180         dms = new ArrayList<DisplayMode>();
 181         DisplayMode dmArray[] = gd.getDisplayModes();
 182         boolean found8 = false, found16 = false,
 183                 found24 = false, found32 = false;
 184         for (DisplayMode dm : dmArray) {
 185             if (!found8 &&
 186                 (dm.getBitDepth() == 8 ||
 187                  dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI)  &&
 188                 (dm.getWidth() >= 800 && dm.getWidth() < 1024))
 189             {
 190                 dms.add(dm);
 191                 found8 = true;
 192                 continue;
 193             }
 194             if (!found32 &&
 195                 (dm.getBitDepth() == 32 ||
 196                  dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI)  &&
 197                 dm.getWidth() >= 1280)
 198             {
 199                 dms.add(dm);
 200                 found32 = true;
 201                 continue;
 202             }
 203             if (!found16 &&
 204                dm.getBitDepth() == 16 &&
 205                 (dm.getWidth() >= 1024 && dm.getWidth() < 1280))
 206             {
 207                 dms.add(dm);
 208                 found16 = true;
 209                 continue;
 210             }
 211             if (found8 && found16 && found32) {
 212                 break;
 213             }
 214         }
 215         System.err.println("Found display modes:");
 216         for (DisplayMode dm : dms) {
 217             System.err.printf("DisplayMode[%dx%dx%d]\n",
 218                 dm.getWidth(), dm.getHeight(), dm.getBitDepth());
 219         }
 220     }
 221 
 222     public static void main(String[] args) throws Exception {
 223         DisplayChangeVITest test = new DisplayChangeVITest();
 224         GraphicsDevice gd =
 225             GraphicsEnvironment.getLocalGraphicsEnvironment().
 226                 getDefaultScreenDevice();
 227         if (gd.isFullScreenSupported()) {
 228             gd.setFullScreenWindow(test);
 229             Thread t = new Thread(test);
 230             t.run();
 231             synchronized (lock) {
 232                 while (!done) {
 233                     try {
 234                         lock.wait(50);
 235                     } catch (InterruptedException ex) {
 236                         ex.printStackTrace();
 237                     }
 238                 }
 239             }
 240             System.err.println("Test Passed.");
 241         } else {
 242             System.err.println("Full screen not supported. Test passed.");
 243         }
 244     }
 245 }