1/*
2 * Copyright (c) 2006, 2016, 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 * @key headful
27 * @bug 6366359
28 * @summary Test that we don't crash when changing from 8 to 16/32 bit modes
29 * @author Dmitri.Trembovetski@Sun.COM area=FullScreen
30 * @run main/othervm/timeout=200 DisplayChangeVITest
31 * @run main/othervm/timeout=200 -Dsun.java2d.d3d=false DisplayChangeVITest
32 * @run main/othervm/timeout=200 -Dsun.java2d.opengl=true DisplayChangeVITest
33 */
34
35import java.awt.Color;
36import java.awt.DisplayMode;
37import java.awt.Graphics;
38import java.awt.GraphicsDevice;
39import java.awt.GraphicsEnvironment;
40import java.awt.event.KeyAdapter;
41import java.awt.event.KeyEvent;
42import java.awt.image.BufferedImage;
43import java.awt.image.VolatileImage;
44import java.lang.Exception;
45import java.lang.Thread;
46import java.util.ArrayList;
47import java.util.Random;
48import 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 */
62public 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}
247