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 5009033 6603000 6666362 8159142
  27  * @summary Verifies that images transformed with bilinear filtering do not
  28  * leave artifacts at the edges.
  29  * @run main/othervm -Dsun.java2d.uiScale=2.5 DrawImageBilinear
  30  * @run main/othervm -Dsun.java2d.uiScale=2.5 -Dsun.java2d.opengl=True DrawImageBilinear
  31  * @run main/othervm -Dsun.java2d.uiScale=2.5 -Dsun.java2d.d3d=false DrawImageBilinear
  32  * @author campbelc
  33  */
  34 
  35 import java.awt.Canvas;
  36 import java.awt.Color;
  37 import java.awt.Component;
  38 import java.awt.Dimension;
  39 import java.awt.Frame;
  40 import java.awt.Graphics;
  41 import java.awt.Graphics2D;
  42 import java.awt.GraphicsConfiguration;
  43 import java.awt.Point;
  44 import java.awt.Rectangle;
  45 import java.awt.RenderingHints;
  46 import java.awt.Robot;
  47 import java.awt.Toolkit;
  48 import java.awt.image.BufferedImage;
  49 import java.awt.image.IndexColorModel;
  50 import java.awt.image.VolatileImage;
  51 
  52 public class DrawImageBilinear extends Canvas {
  53 
  54     private static final int SIZE = 5;
  55 
  56     private static boolean done;
  57     private BufferedImage bimg1, bimg2;
  58     private VolatileImage vimg;
  59     private static volatile BufferedImage capture;
  60     private static void doCapture(Component test) {
  61         try {
  62             Thread.sleep(2000);
  63         } catch (InterruptedException ex) {}
  64         // Grab the screen region
  65         try {
  66             Robot robot = new Robot();
  67             Point pt1 = test.getLocationOnScreen();
  68             Rectangle rect =
  69                 new Rectangle(pt1.x, pt1.y, test.getWidth(), test.getHeight());
  70             capture = robot.createScreenCapture(rect);
  71         } catch (Exception e) {
  72             e.printStackTrace();
  73         }
  74     }
  75 
  76     private void renderPattern(Graphics g) {
  77         g.setColor(Color.red);
  78         g.fillRect(0, 0, SIZE, SIZE);
  79         //g.setColor(Color.green);
  80         //g.drawRect(0, 0, SIZE-1, SIZE-1);
  81         g.dispose();
  82     }
  83 
  84     public void paint(Graphics g) {
  85         Graphics2D g2d = (Graphics2D)g;
  86 
  87         if (bimg1 == null) {
  88             bimg1 = (BufferedImage)createImage(SIZE, SIZE);
  89             bimg1.setAccelerationPriority(0.0f);
  90             renderPattern(bimg1.createGraphics());
  91 
  92             bimg2 = (BufferedImage)createImage(SIZE, SIZE);
  93             renderPattern(bimg2.createGraphics());
  94 
  95             vimg = createVolatileImage(SIZE, SIZE);
  96             vimg.validate(getGraphicsConfiguration());
  97             renderPattern(vimg.createGraphics());
  98         }
  99 
 100         do {
 101             g2d.setColor(Color.white);
 102             g2d.fillRect(0, 0, getWidth(), getHeight());
 103 
 104             g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 105                                  RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 106 
 107             // first time will be a sw->surface blit
 108             g2d.drawImage(bimg1, 10, 10, 40, 40, null);
 109 
 110             // second time will be a texture->surface blit
 111             g2d.drawImage(bimg2, 80, 10, 40, 40, null);
 112             if (!skipOglTextureTest) {
 113                 g2d.drawImage(bimg2, 80, 10, 40, 40, null);
 114             }
 115 
 116             // third time will be a pbuffer->surface blit
 117             if (vimg.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK) {
 118                 renderPattern(vimg.createGraphics());
 119             }
 120             g2d.drawImage(vimg, 150, 10, 40, 40, null);
 121 
 122             Toolkit.getDefaultToolkit().sync();
 123         } while (vimg.contentsLost());
 124 
 125         synchronized (this) {
 126             if (!done) {
 127                 doCapture(this);
 128                 done = true;
 129             }
 130             notifyAll();
 131         }
 132     }
 133 
 134     public Dimension getPreferredSize() {
 135         return new Dimension(200, 100);
 136     }
 137 
 138     private static void testRegion(BufferedImage bi,
 139                                    Rectangle affectedRegion)
 140     {
 141         int x1 = affectedRegion.x;
 142         int y1 = affectedRegion.y;
 143         int x2 = x1 + affectedRegion.width;
 144         int y2 = y1 + affectedRegion.height;
 145 
 146         for (int y = y1; y < y2; y++) {
 147             for (int x = x1; x < x2; x++) {
 148                 int actual = bi.getRGB(x, y);
 149                 if ((actual != 0xfffe0000) && (actual != 0xffff0000)) {
 150                     throw new RuntimeException("Test failed at x="+x+" y="+y+
 151                                                " (expected=0xffff0000"+
 152                                                " actual=0x"+
 153                                                Integer.toHexString(actual) +
 154                                                ")");
 155                 }
 156             }
 157         }
 158     }
 159 
 160     private static boolean skipOglTextureTest = false;
 161 
 162     public static void main(String[] args) {
 163         boolean show = false;
 164         for (String arg : args) {
 165             if ("-show".equals(arg)) {
 166                 show = true;
 167             }
 168         }
 169 
 170         String arch = System.getProperty("os.arch");
 171         boolean isOglEnabled = Boolean.getBoolean("sun.java2d.opengl");
 172         skipOglTextureTest = isOglEnabled && ("sparc".equals(arch));
 173         System.out.println("Skip OpenGL texture test: " + skipOglTextureTest);
 174 
 175         DrawImageBilinear test = new DrawImageBilinear();
 176         Frame frame = new Frame();
 177         frame.add(test);
 178         frame.pack();
 179         frame.setVisible(true);
 180 
 181         // Wait until the component's been painted
 182         synchronized (test) {
 183             while (!done) {
 184                 try {
 185                     test.wait();
 186                 } catch (InterruptedException e) {
 187                     throw new RuntimeException("Failed: Interrupted");
 188                 }
 189             }
 190         }
 191 
 192         GraphicsConfiguration gc = frame.getGraphicsConfiguration();
 193         if (gc.getColorModel() instanceof IndexColorModel) {
 194             System.out.println("IndexColorModel detected: " +
 195                                "test considered PASSED");
 196             frame.dispose();
 197             return;
 198         }
 199 
 200         if (!show) {
 201             frame.dispose();
 202         }
 203         if (capture == null) {
 204             throw new RuntimeException("Failed: capture is null");
 205         }
 206 
 207         // Test background color
 208         int pixel = capture.getRGB(5, 5);
 209         if (pixel != 0xffffffff) {
 210             throw new RuntimeException("Failed: Incorrect color for " +
 211                                        "background");
 212         }
 213 
 214         // Test pixels
 215         testRegion(capture, new Rectangle(10, 10, 40, 40));
 216         testRegion(capture, new Rectangle(80, 10, 40, 40));
 217         testRegion(capture, new Rectangle(150, 10, 40, 40));
 218     }
 219 }