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