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 /**
  25  * @test
  26  * @key headful
  27  * @bug 6613860 6691934
  28  * @summary Tests that the pipelines can handle (in somewhat limited
  29  * manner) mutable Colors
  30  *
  31  * @run main/othervm MutableColorTest
  32  * @run main/othervm -Dsun.java2d.noddraw=true MutableColorTest
  33  * @run main/othervm -Dsun.java2d.opengl=True MutableColorTest
  34  */
  35 
  36 import java.awt.Color;
  37 import java.awt.Graphics2D;
  38 import java.awt.GraphicsConfiguration;
  39 import java.awt.GraphicsEnvironment;
  40 import java.awt.Image;
  41 import java.awt.Transparency;
  42 import java.awt.geom.Ellipse2D;
  43 import java.awt.image.BufferedImage;
  44 import java.awt.image.VolatileImage;
  45 import java.io.File;
  46 import java.io.IOException;
  47 import javax.imageio.ImageIO;
  48 
  49 public class MutableColorTest {
  50 
  51     static Image bmImage;
  52     static Image argbImage;
  53 
  54     static class EvilColor extends Color {
  55         Color colors[] = { Color.red, Color.green, Color.blue };
  56         int currentIndex = 0;
  57         EvilColor() {
  58             super(Color.red.getRGB());
  59         }
  60 
  61         @Override
  62         public int getRGB() {
  63             return colors[currentIndex].getRGB();
  64         }
  65         void nextColor() {
  66             currentIndex++;
  67         }
  68     }
  69 
  70     private static int testImage(Image im,
  71                                  boolean doClip, boolean doTx)
  72     {
  73         int w = im.getWidth(null);
  74         int h = im.getHeight(null);
  75         Graphics2D g = (Graphics2D)im.getGraphics();
  76         EvilColor evilColor = new EvilColor();
  77         g.setColor(evilColor);
  78         g.fillRect(0, 0, w, h);
  79         g.dispose();
  80 
  81         evilColor.nextColor();
  82 
  83         g = (Graphics2D)im.getGraphics();
  84 
  85         if (doTx) {
  86             g.rotate(Math.PI/2.0, w/2, h/2);
  87         }
  88         g.setColor(evilColor);
  89         g.fillRect(0, 0, w, h);
  90         if (doClip) {
  91             g.clip(new Ellipse2D.Float(0, 0, w, h));
  92         }
  93         g.fillRect(0, h/3, w, h/3);
  94 
  95         // tests native BlitBg loop
  96         g.drawImage(bmImage, 0, 2*h/3, evilColor, null);
  97         // tests General BlitBg loop
  98         g.drawImage(argbImage, 0, 2*h/3+h/3/2, evilColor, null);
  99 
 100         return evilColor.getRGB();
 101     }
 102 
 103     private static void testResult(final String desc,
 104                                    final BufferedImage snapshot,
 105                                    final int evilColor) {
 106         for (int y = 0; y < snapshot.getHeight(); y++) {
 107             for (int x = 0; x < snapshot.getWidth(); x++) {
 108                 int snapRGB = snapshot.getRGB(x, y);
 109                 if (!isSameColor(snapRGB, evilColor)) {
 110                     System.err.printf("Wrong RGB for %s at (%d,%d): 0x%x " +
 111                         "instead of 0x%x\n", desc, x, y, snapRGB, evilColor);
 112                     String fileName = "MutableColorTest_"+desc+".png";
 113                     try {
 114                         ImageIO.write(snapshot, "png", new File(fileName));
 115                         System.err.println("Dumped snapshot to "+fileName);
 116                     } catch (IOException ex) {}
 117                     throw new RuntimeException("Test FAILED.");
 118                 }
 119             }
 120         }
 121     }
 122 
 123     public static void main(String[] args) {
 124         GraphicsConfiguration gc =
 125             GraphicsEnvironment.getLocalGraphicsEnvironment().
 126                 getDefaultScreenDevice().getDefaultConfiguration();
 127 
 128         bmImage = gc.createCompatibleImage(64, 64, Transparency.BITMASK);
 129         argbImage = gc.createCompatibleImage(64, 64, Transparency.TRANSLUCENT);
 130 
 131         if (gc.getColorModel().getPixelSize() > 8) {
 132             VolatileImage vi =
 133                 gc.createCompatibleVolatileImage(64, 64, Transparency.OPAQUE);
 134             do {
 135                 if (vi.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
 136                     vi = gc.createCompatibleVolatileImage(64, 64,
 137                                                           Transparency.OPAQUE);
 138                     vi.validate(gc);
 139                 }
 140 
 141                 int color = testImage(vi, false, false);
 142                 testResult("vi_noclip_notx", vi.getSnapshot(), color);
 143 
 144                 color = testImage(vi, true, true);
 145                 testResult("vi_clip_tx", vi.getSnapshot(), color);
 146 
 147                 color = testImage(vi, true, false);
 148                 testResult("vi_clip_notx", vi.getSnapshot(), color);
 149 
 150                 color = testImage(vi, false, true);
 151                 testResult("vi_noclip_tx", vi.getSnapshot(), color);
 152             } while (vi.contentsLost());
 153         }
 154 
 155         BufferedImage bi = new BufferedImage(64, 64, BufferedImage.TYPE_INT_RGB);
 156         int color = testImage(bi, false, false);
 157         testResult("bi_noclip_notx", bi, color);
 158 
 159         color = testImage(bi, true, true);
 160         testResult("bi_clip_tx", bi, color);
 161 
 162         color = testImage(bi, true, false);
 163         testResult("bi_clip_notx", bi, color);
 164 
 165         color = testImage(bi, false, true);
 166         testResult("bi_noclip_tx", bi, color);
 167 
 168         System.err.println("Test passed.");
 169     }
 170 
 171     /*
 172      * We assume that colors with slightly different components
 173      * are the same. This is done just in order to workaround
 174      * peculiarities of OGL rendering pipeline on some platforms.
 175      * See CR 6989217 for more details.
 176      */
 177      private static boolean isSameColor(int color1, int color2) {
 178         final int tolerance = 2;
 179 
 180         for (int i = 0; i < 32; i += 8) {
 181             int c1 = 0xff & (color1 >> i);
 182             int c2 = 0xff & (color2 >> i);
 183 
 184             if (Math.abs(c1 - c2) > tolerance) {
 185                 return false;
 186             }
 187         }
 188         return true;
 189     }
 190 }