1 /*
   2  * Copyright (c) 2007, 2008, 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.pack();
  93         frame.setSize(FRAME_W, FRAME_H);
  94         frame.addWindowListener(new WindowAdapter() {
  95             public void windowClosing(WindowEvent e) {
  96                 done = true;
  97             }
  98         });
  99         try {
 100             EventQueue.invokeAndWait(new Runnable() {
 101                 public void run() {
 102                     frame.setVisible(true);
 103                 }
 104             });
 105             // wait for Vista's effects to complete
 106             Thread.sleep(2000);
 107         } catch (Exception ex) {
 108             ex.printStackTrace();
 109         }
 110 
 111         GraphicsConfiguration gc = frame.getGraphicsConfiguration();
 112         int maxW = gc.getBounds().width /2;
 113         int maxH = gc.getBounds().height/2;
 114         int minW = frame.getWidth();
 115         int minH = frame.getHeight();
 116         int incW = 10, incH = 10, cnt = 0;
 117         Robot robot = null;
 118         if (!nocheck && gc.getColorModel().getPixelSize() > 8) {
 119             try {
 120                 robot = new Robot();
 121             } catch (AWTException ex) {
 122                 System.err.println("Robot creation failed, continuing.");
 123             }
 124         } else {
 125             System.err.println("No screen rendering checks.");
 126         }
 127 
 128         VolatileImage vi = gc.createCompatibleVolatileImage(512, 512);
 129         vi.validate(gc);
 130 
 131         long timeStarted = System.currentTimeMillis();
 132         while (!done && (System.currentTimeMillis() - timeStarted) < RUN_TIME) {
 133 
 134             if (++cnt > 100) {
 135                 int w = frame.getWidth() + incW;
 136                 int h = frame.getHeight() + incH;
 137                 if (w < minW || w > maxW ) {
 138                     incW = -incW;
 139                 }
 140                 if (h < minH || h > maxH ) {
 141                     incH = -incH;
 142                 }
 143                 frame.setSize(w, h);
 144                 cnt = 0;
 145             }
 146 
 147             // try to put the device into non-default state, for example,
 148             // this operation below will set the transform
 149             vi.validate(gc);
 150             Graphics2D vig = (Graphics2D)vi.getGraphics();
 151             vig.rotate(30.0f, vi.getWidth()/2, vi.getHeight()/2);
 152             vig.drawImage(output, 0, 0,
 153                           vi.getWidth(), vi.getHeight(), null);
 154 
 155             Insets in = frame.getInsets();
 156             frame.getGraphics().drawImage(output, in.left, in.top, null);
 157             if (cnt == 90 && robot != null) {
 158                 // area where we blitted to should be either white or green
 159                 Point p = frame.getLocationOnScreen();
 160                 p.move(in.left+10, in.top+10);
 161                 BufferedImage bi =
 162                     robot.createScreenCapture(
 163                         new Rectangle(p.x, p.y, IMAGE_W/2, IMAGE_H/2));
 164                 int accepted1[] = { Color.white.getRGB(), Color.green.getRGB()};
 165                 checkBI(bi, accepted1);
 166 
 167                 // the are where we didn't render should stay white
 168                 p = frame.getLocationOnScreen();
 169                 p.move(in.left, in.top+IMAGE_H+5);
 170                 bi = robot.createScreenCapture(
 171                     new Rectangle(p.x, p.y,
 172                                   frame.getWidth()-in.left-in.right,
 173                                   frame.getHeight()-in.top-in.bottom-5-IMAGE_H));
 174                 int accepted2[] = { Color.white.getRGB() };
 175                 checkBI(bi, accepted1);
 176             }
 177 
 178             Thread.yield();
 179         }
 180         frame.dispose();
 181         System.out.println("Test Passed");
 182     }
 183 
 184     private static void checkBI(BufferedImage bi, int accepted[]) {
 185         for (int x = 0; x < bi.getWidth(); x++) {
 186             for (int y = 0; y < bi.getHeight(); y++) {
 187                 int pix = bi.getRGB(x, y);
 188                 boolean found = false;
 189                 for (int acc : accepted) {
 190                     if (pix == acc) {
 191                         found = true;
 192                         break;
 193                     }
 194                 }
 195                 if (!found) {
 196                     try {
 197                         String name = "OnScreenRenderingResizeTest.png";
 198                         ImageIO.write(bi, "png", new File(name));
 199                         System.out.println("Screen shot file: " + name);
 200                     } catch (IOException ex) {}
 201 
 202                     throw new
 203                         RuntimeException("Test failed at " + x + "-" + y +
 204                                          " rgb=0x" + Integer.toHexString(pix));
 205                 }
 206             }
 207         }
 208     }
 209 }