1 /*
   2  * Copyright (c) 2004, 2017, 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 4994702
  27  * @key headful
  28  * @summary verifies that no regression were introduced with the fix for this
  29  *          bug
  30  */
  31 
  32 import java.awt.AlphaComposite;
  33 import java.awt.Color;
  34 import java.awt.Component;
  35 import java.awt.Dimension;
  36 import java.awt.Frame;
  37 import java.awt.Graphics;
  38 import java.awt.Graphics2D;
  39 import java.awt.ImageCapabilities;
  40 import java.awt.Rectangle;
  41 import java.awt.event.MouseAdapter;
  42 import java.awt.event.MouseEvent;
  43 import java.awt.image.BufferedImage;
  44 import java.awt.image.DataBuffer;
  45 import java.awt.image.VolatileImage;
  46 import java.awt.image.WritableRaster;
  47 import java.io.File;
  48 import java.io.IOException;
  49 
  50 import javax.imageio.IIOImage;
  51 import javax.imageio.ImageIO;
  52 import javax.imageio.ImageReadParam;
  53 import javax.imageio.ImageReader;
  54 import javax.imageio.ImageWriteParam;
  55 import javax.imageio.ImageWriter;
  56 import javax.imageio.stream.FileImageInputStream;
  57 import javax.imageio.stream.ImageOutputStream;
  58 
  59 public class JPEGsNotAcceleratedTest {
  60 
  61     public static final int testRGB = Color.red.getRGB();
  62     public static final int TEST_W = 100;
  63     public static final int TEST_H = 100;
  64     public static final Rectangle roi =
  65         new Rectangle(TEST_W/4, TEST_H/4, TEST_W/2, TEST_H/2);
  66 
  67     static Frame f;
  68     static boolean showRes = false;
  69     static int testsFinished = 0;
  70     static int testsStarted = 0;
  71     static boolean lowCompression = false;
  72 
  73     static boolean failed = false;
  74 
  75     public JPEGsNotAcceleratedTest(String name) {
  76         BufferedImage bi = readTestImage(name, null, null);
  77         runTestOnImage("no dest image, no region of interest", bi, null);
  78 
  79         BufferedImage destBI = getDestImage();
  80         bi = readTestImage(name, destBI, null);
  81         runTestOnImage("w/ dest image, no region of interest", bi, null);
  82 
  83         // steal the raster, see if the destination image
  84         // gets accelerated
  85         destBI = getDestImage();
  86         DataBuffer db =
  87             ((WritableRaster)destBI.getRaster()).getDataBuffer();
  88         bi = readTestImage(name, destBI, null);
  89         runTestOnImage("w/ dest image (with stolen raster),"+
  90                        " no region of interest", bi, null);
  91 
  92         bi = readTestImage(name, null, roi);
  93         runTestOnImage("no dest image, region of interest", bi, roi);
  94 
  95         destBI = getDestImage();
  96         bi = readTestImage(name, destBI, roi);
  97         runTestOnImage("w/ dest image, region of interest", bi, roi);
  98 
  99         // accelerate the destination image first, then load
 100         // an image into it. Check that the accelerated copy gets
 101         // updated
 102         destBI = getDestImage();
 103         accelerateImage(destBI);
 104         bi = readTestImage(name, destBI, roi);
 105         runTestOnImage("w/ accelerated dest image,"+
 106                        " region of interest", bi, roi);
 107 
 108         synchronized (JPEGsNotAcceleratedTest.class) {
 109             testsFinished++;
 110             JPEGsNotAcceleratedTest.class.notify();
 111         }
 112 
 113     }
 114 
 115     public static BufferedImage readTestImage(String fileName,
 116                                    BufferedImage dest,
 117                                    Rectangle srcROI)
 118     {
 119         BufferedImage bi = null;
 120 
 121         try {
 122             FileImageInputStream is =
 123                 new FileImageInputStream(new File(fileName));
 124             ImageReader reader =
 125                 (ImageReader)ImageIO.getImageReaders(is).next();
 126             ImageReadParam param = reader.getDefaultReadParam();
 127             if (dest != null) {
 128                 param.setDestination(dest);
 129             }
 130             if (srcROI != null) {
 131                 param.setSourceRegion(srcROI);
 132             }
 133             reader.setInput(is);
 134             bi = reader.read(0, param);
 135         } catch (IOException e) {
 136             System.err.println("Error " + e +
 137                                " when reading file: " + fileName);
 138             throw new RuntimeException(e);
 139         }
 140 
 141         return bi;
 142     }
 143 
 144     public static void writeTestImage(String fileName) {
 145         BufferedImage bi =
 146             new BufferedImage(TEST_W, TEST_H, BufferedImage.TYPE_INT_RGB);
 147         Graphics g = bi.getGraphics();
 148         g.setColor(new Color(testRGB));
 149         g.fillRect(0, 0, TEST_W, TEST_H);
 150         try {
 151             System.err.printf("Writing %s\n", fileName);
 152             if (lowCompression) {
 153                 ImageWriter iw = (ImageWriter)ImageIO.getImageWritersBySuffix("jpeg").next();
 154                 if(iw == null) {
 155                     throw new RuntimeException("No available image writer for "
 156                                                + "jpeg "
 157                                                + " Test failed.");
 158                 }
 159 
 160                 File file = new File(fileName);
 161                 ImageOutputStream ios = ImageIO.createImageOutputStream(file);
 162                 iw.setOutput(ios);
 163 
 164                 ImageWriteParam param = iw.getDefaultWriteParam();
 165                 param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
 166                 param.setCompressionQuality(1);
 167 
 168                 IIOImage iioImg = new IIOImage(bi, null, null);
 169                 iw.write(null, iioImg, param);
 170 
 171             } else {
 172                 ImageIO.write(bi, "jpeg", new File(fileName));
 173             }
 174         } catch (IOException e) {
 175             System.err.println("Error " + e +
 176                                " when writing file: " + fileName);
 177             throw new RuntimeException(e);
 178         }
 179     }
 180 
 181     public VolatileImage accelerateImage(BufferedImage bi) {
 182         VolatileImage testVI = f.createVolatileImage(TEST_W, TEST_H);
 183         do {
 184             if (testVI.validate(f.getGraphicsConfiguration()) ==
 185                 VolatileImage.IMAGE_INCOMPATIBLE)
 186             {
 187                 testVI = f.createVolatileImage(TEST_W, TEST_H);
 188             }
 189             Graphics2D g = testVI.createGraphics();
 190             g.setComposite(AlphaComposite.Src);
 191             g.setColor(Color.green);
 192             g.fillRect(0, 0, TEST_W, TEST_H);
 193 
 194             g.drawImage(bi, 0, 0, null);
 195             g.drawImage(bi, 0, 0, null);
 196             g.drawImage(bi, 0, 0, null);
 197             g.dispose();
 198         } while (testVI.contentsLost());
 199 
 200         return testVI;
 201     }
 202 
 203     public BufferedImage getDestImage() {
 204         BufferedImage destBI =
 205             new BufferedImage(TEST_W, TEST_H, BufferedImage.TYPE_INT_RGB);
 206         Graphics2D g = (Graphics2D)destBI.getGraphics();
 207         g.setComposite(AlphaComposite.Src);
 208         g.setColor(Color.blue);
 209         g.fillRect(0, 0, TEST_W, TEST_H);
 210         return destBI;
 211     }
 212 
 213     public void runTestOnImage(String desc, BufferedImage bi,
 214                                Rectangle srcROI)
 215     {
 216 
 217         if (srcROI == null) {
 218             srcROI = new Rectangle(0, 0, TEST_W, TEST_H);
 219         }
 220 
 221         VolatileImage testVI = accelerateImage(bi);
 222 
 223         ImageCapabilities ic =
 224             bi.getCapabilities(f.getGraphicsConfiguration());
 225         boolean accelerated = ic.isAccelerated();
 226 
 227         System.err.println("Testing: " + desc +
 228                            " -- bi.isAccelerated(): " + accelerated );
 229 
 230         BufferedImage snapshot = testVI.getSnapshot();
 231         if (showRes) {
 232             showRes(desc, snapshot);
 233         }
 234 
 235         for (int y = 0; y < srcROI.height; y++) {
 236             for (int x = 0; x < srcROI.width; x++) {
 237                 int destRGB = snapshot.getRGB(x, y);
 238                 if (destRGB != testRGB && destRGB != 0xfffe0000) {
 239                     failed = true;
 240                     System.err.printf("Test failed at %dx%d pixel=%x\n",
 241                                       x, y, snapshot.getRGB(x, y));
 242                     if (!showRes) {
 243                         showRes(desc, snapshot);
 244                     }
 245                     break;
 246                 }
 247             }
 248         }
 249     }
 250 
 251     static int startX = 64, startY = 0;
 252     static int frameX = startX, frameY = startY;
 253     private static void showRes(String desc, final BufferedImage src) {
 254         final int w = src.getWidth();
 255         final int h = src.getHeight();
 256 
 257         Frame f = new Frame(desc+": dbl-click to exit");
 258         Component c;
 259         f.add(c = new Component() {
 260             public Dimension getPreferredSize() {
 261                 return new Dimension(w,h);
 262             }
 263 
 264             public void paint(Graphics g) {
 265                 g.clearRect(0, 0, getWidth(), getHeight());
 266                 g.drawImage(src, 0,0, null);
 267             }
 268         });
 269         c.addMouseListener(new MouseAdapter() {
 270             public void mouseClicked(MouseEvent e) {
 271                 if (e.getClickCount() > 1) {
 272                     System.exit(0);
 273                 }
 274             }
 275         });
 276         f.pack();
 277         synchronized (JPEGsNotAcceleratedTest.class) {
 278             f.setLocation(frameX, frameY);
 279             frameX += f.getWidth();
 280             if ((frameX + f.getWidth()) >
 281                 f.getGraphicsConfiguration().getBounds().width)
 282             {
 283                 frameY += TEST_H;
 284                 if ((frameY + f.getHeight()) >
 285                     f.getGraphicsConfiguration().getBounds().height)
 286                 {
 287                     startY += 30;
 288                     startX += 30;
 289                     frameY = startY;
 290                 }
 291                 frameX = startX;
 292             }
 293         };
 294         f.setVisible(true);
 295     }
 296 
 297     public static void usage() {
 298         System.err.println("Usage: java Test [file name] [-write][-show][-low]");
 299         System.exit(0);
 300     }
 301 
 302     public static void main(String[] args) {
 303         System.setProperty("sun.java2d.pmoffscreen", "true");
 304         System.setProperty("sun.java2d.ddforcevram", "true");
 305         String name = "red.jpg";
 306 
 307         f = new Frame();
 308         f.pack();
 309 
 310         if (f.getGraphicsConfiguration().getColorModel().getPixelSize() < 16) {
 311             System.err.println("8-bit display mode detected, dithering issues possible, "+
 312                                "considering test passed.");
 313             f.dispose();
 314             return;
 315         }
 316 
 317 
 318         for (String arg : args) {
 319             if (arg.equals("-write")) {
 320                 writeTestImage(name);
 321                 System.exit(0);
 322             } else if (arg.equals("-show")) {
 323                 showRes = true;
 324             } else if (arg.equals("-low")) {
 325                 lowCompression = true;
 326                 name ="red_low.jpg";
 327                 System.err.println("Using low jpeg compression");
 328             } else if (arg.equals("-help")) {
 329                 usage();
 330             } else {
 331                 final String filename = arg;
 332                 testsStarted++;
 333                 new Thread(new Runnable() {
 334                     public void run() {
 335                         new JPEGsNotAcceleratedTest(filename);
 336                     }
 337                 }).start();
 338             }
 339         }
 340 
 341         if (testsStarted == 0) {
 342             writeTestImage(name);
 343             testsStarted++;
 344             new JPEGsNotAcceleratedTest(name);
 345         }
 346 
 347 
 348         synchronized (JPEGsNotAcceleratedTest.class) {
 349             while (testsFinished < testsStarted) {
 350                 try {
 351                     JPEGsNotAcceleratedTest.class.wait(100);
 352                 } catch (InterruptedException e) {
 353                     failed = true; break;
 354                 }
 355             }
 356         }
 357 
 358         f.dispose();
 359         if (failed) {
 360             throw new RuntimeException("Test failed");
 361         }
 362 
 363         System.err.println("Passed.");
 364     }
 365 }