1 /*
   2  * Copyright (c) 2007, 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  * @test
  25  * @key headful
  26  * @bug 6664068 6666931
  27  * @summary Tests that resizing a window to which a tight loop is rendering
  28  * doesn't produce artifacts or crashes
  29  * @author Dmitri.Trembovetski@sun.com: area=Graphics
  30  * @run main/othervm OnScreenRenderingResizeTest
  31  * @run main/othervm -Dsun.java2d.d3d=false OnScreenRenderingResizeTest
  32  */
  33 
  34 import java.awt.AWTException;
  35 import java.awt.Color;
  36 import java.awt.EventQueue;
  37 import java.awt.Frame;
  38 import java.awt.Graphics;
  39 import java.awt.Graphics2D;
  40 import java.awt.GraphicsConfiguration;
  41 import java.awt.Insets;
  42 import java.awt.Point;
  43 import java.awt.Rectangle;
  44 import java.awt.Robot;
  45 import java.awt.event.WindowAdapter;
  46 import java.awt.event.WindowEvent;
  47 import java.awt.image.BufferedImage;
  48 import java.awt.image.VolatileImage;
  49 import java.io.File;
  50 import java.io.IOException;
  51 import javax.imageio.ImageIO;
  52 
  53 public class OnScreenRenderingResizeTest {
  54 
  55     private static volatile boolean done = false;
  56     private static volatile boolean nocheck = false;
  57 
  58     private static final int FRAME_W = 256;
  59     private static final int FRAME_H = 256;
  60     private static final int IMAGE_W = 128;
  61     private static final int IMAGE_H = 128;
  62     private static long RUN_TIME = 1000*20;
  63 
  64     private static final Color renderColor = Color.green;
  65     private static final Color bgColor = Color.white;
  66 
  67     public static void main(String[] args) {
  68 
  69         for (String arg : args) {
  70             if ("-inf".equals(arg)) {
  71                 System.err.println("Test will run indefinitely");
  72                 RUN_TIME = Long.MAX_VALUE;
  73             } else  if ("-nocheck".equals(arg)) {
  74                 System.err.println("Test will not check rendering results");
  75                 nocheck = true;
  76             } else {
  77                 System.err.println("Usage: OnScreenRenderingResizeTest [-inf][-nocheck]");
  78             }
  79         }
  80 
  81         BufferedImage output =
  82             new BufferedImage(IMAGE_W, IMAGE_H, BufferedImage.TYPE_INT_RGB);
  83         output.setAccelerationPriority(0.0f);
  84         Graphics g = output.getGraphics();
  85         g.setColor(renderColor);
  86         g.fillRect(0, 0, output.getWidth(), output.getHeight());
  87 
  88         final Frame frame = new Frame("OnScreenRenderingResizeTest") {
  89             public void paint(Graphics g) {}
  90             public void update(Graphics g) {}
  91         };
  92         frame.setBackground(bgColor);
  93         frame.setUndecorated(true);
  94         frame.pack();
  95 
  96         GraphicsConfiguration gc = frame.getGraphicsConfiguration();
  97         Rectangle gcBounds = gc.getBounds();
  98         frame.setBounds(gcBounds.width / 4, gcBounds.height / 4, FRAME_W, FRAME_H);
  99 
 100         frame.addWindowListener(new WindowAdapter() {
 101             public void windowClosing(WindowEvent e) {
 102                 done = true;
 103             }
 104         });
 105         try {
 106             EventQueue.invokeAndWait(new Runnable() {
 107                 public void run() {
 108                     frame.setVisible(true);
 109                 }
 110             });
 111             // wait for Vista's effects to complete
 112             Thread.sleep(2000);
 113         } catch (Exception ex) {
 114             ex.printStackTrace();
 115         }
 116 
 117         int maxW = gcBounds.width /2;
 118         int maxH = gcBounds.height/2;
 119         int minW = frame.getWidth();
 120         int minH = frame.getHeight();
 121         int incW = 10, incH = 10, cnt = 0;
 122         Robot robot = null;
 123         if (!nocheck && gc.getColorModel().getPixelSize() > 8) {
 124             try {
 125                 robot = new Robot();
 126             } catch (AWTException ex) {
 127                 System.err.println("Robot creation failed, continuing.");
 128             }
 129         } else {
 130             System.err.println("No screen rendering checks.");
 131         }
 132 
 133         VolatileImage vi = gc.createCompatibleVolatileImage(512, 512);
 134         vi.validate(gc);
 135 
 136         long timeStarted = System.currentTimeMillis();
 137         while (!done && (System.currentTimeMillis() - timeStarted) < RUN_TIME) {
 138 
 139             if (++cnt > 100) {
 140                 int w = frame.getWidth() + incW;
 141                 int h = frame.getHeight() + incH;
 142                 if (w < minW || w > maxW ) {
 143                     incW = -incW;
 144                 }
 145                 if (h < minH || h > maxH ) {
 146                     incH = -incH;
 147                 }
 148                 frame.setSize(w, h);
 149                 cnt = 0;
 150             }
 151 
 152             // try to put the device into non-default state, for example,
 153             // this operation below will set the transform
 154             vi.validate(gc);
 155             Graphics2D vig = (Graphics2D)vi.getGraphics();
 156             vig.rotate(30.0f, vi.getWidth()/2, vi.getHeight()/2);
 157             vig.drawImage(output, 0, 0,
 158                           vi.getWidth(), vi.getHeight(), null);
 159 
 160             Insets in = frame.getInsets();
 161             frame.getGraphics().drawImage(output, in.left, in.top, null);
 162             if (cnt == 90 && robot != null) {
 163                 robot.waitForIdle();
 164                 // area where we blitted to should be either white or green
 165                 Point p = frame.getLocationOnScreen();
 166                 p.translate(in.left+10, in.top+10);
 167                 BufferedImage bi =
 168                     robot.createScreenCapture(
 169                         new Rectangle(p.x, p.y, IMAGE_W/2, IMAGE_H/2));
 170                 int accepted1[] = { Color.white.getRGB(), Color.green.getRGB()};
 171                 checkBI(bi, accepted1);
 172 
 173                 // the are where we didn't render should stay white
 174                 p = frame.getLocationOnScreen();
 175                 p.translate(in.left, in.top+IMAGE_H+5);
 176                 bi = robot.createScreenCapture(
 177                     new Rectangle(p.x, p.y,
 178                                   frame.getWidth()-in.left-in.right,
 179                                   frame.getHeight()-in.top-in.bottom-5-IMAGE_H));
 180                 int accepted2[] = { Color.white.getRGB() };
 181                 checkBI(bi, accepted2);
 182             }
 183 
 184             Thread.yield();
 185         }
 186         frame.dispose();
 187         System.out.println("Test Passed");
 188     }
 189 
 190     private static void checkBI(BufferedImage bi, int accepted[]) {
 191         for (int x = 0; x < bi.getWidth(); x++) {
 192             for (int y = 0; y < bi.getHeight(); y++) {
 193                 int pix = bi.getRGB(x, y);
 194                 boolean found = false;
 195                 for (int acc : accepted) {
 196                     if (pix == acc) {
 197                         found = true;
 198                         break;
 199                     }
 200                 }
 201                 if (!found) {
 202                     try {
 203                         String name = "OnScreenRenderingResizeTest.png";
 204                         ImageIO.write(bi, "png", new File(name));
 205                         System.out.println("Screen shot file: " + name);
 206                     } catch (IOException ex) {}
 207 
 208                     throw new
 209                         RuntimeException("Test failed at " + x + "-" + y +
 210                                          " rgb=0x" + Integer.toHexString(pix));
 211                 }
 212             }
 213         }
 214     }
 215 }