/* * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4881082 4916294 5002129 8158524 * @summary The test verifies whether the rendering operations on transparent * and translucent VolatileImage objects generate identical output * as generated with transparent and translucent BufferedImages. * @key headful * @run main/othervm -Dsun.java2d.uiScale=1 TransparentVImage * @run main/othervm -Dsun.java2d.uiScale=1 -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=false TransparentVImage * @run main/othervm -Dsun.java2d.uiScale=1 -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=true TransparentVImage */ import java.awt.GraphicsConfiguration; import java.awt.Graphics; import java.awt.Image; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.awt.image.VolatileImage; import java.awt.Color; import javax.swing.JFrame; import javax.swing.JComponent; import javax.swing.ImageIcon; import javax.swing.SwingUtilities; /* * This test draws the same contents to 4 images: 2 BufferedImages that are * transparent and translucent and 2 VolatileImages that are transparent and * translucent. It compares the results pixel-by-pixel and fails if the * results are not the same. */ public class TransparentVImage extends JComponent { BufferedImage cImgTransparent, cImgTranslucent; VolatileImage vImgTransparent, vImgTranslucent; Image sprite; static final int IMAGE_SIZE = 250; static final int WINDOW_SIZE = 600; static boolean doneComparing = false; static JFrame testFrame = null; @Override public void paint(Graphics g) { if (cImgTransparent == null) { GraphicsConfiguration gc = getGraphicsConfiguration(); // doesn't exist yet: create it (and the other images) cImgTransparent = (BufferedImage) gc.createCompatibleImage(IMAGE_SIZE, IMAGE_SIZE, Transparency.BITMASK); cImgTranslucent = (BufferedImage) gc.createCompatibleImage(IMAGE_SIZE, IMAGE_SIZE, Transparency.TRANSLUCENT); vImgTransparent = gc.createCompatibleVolatileImage(IMAGE_SIZE, IMAGE_SIZE, Transparency.BITMASK); vImgTranslucent = gc.createCompatibleVolatileImage(IMAGE_SIZE, IMAGE_SIZE, Transparency.TRANSLUCENT); String fileName = "duke.gif"; String separator = System.getProperty("file.separator"); String dirPath = System.getProperty("test.src", "."); String filePath = dirPath + separator + fileName; sprite = new ImageIcon(filePath).getImage(); // Now they exist; render to them Graphics gImg[] = new Graphics[4]; gImg[0] = cImgTransparent.getGraphics(); gImg[1] = cImgTranslucent.getGraphics(); gImg[2] = vImgTransparent.getGraphics(); gImg[3] = vImgTranslucent.getGraphics(); for (int i = 0; i < gImg.length; ++i) { /* * VolatileImage utilizes the power of accelerated rendering * using GPU. The GPU drivers for D3d and OpenGL are supplied * by OEM vendors and are external to graphics subsystem. Thus * one cannot guarentee that the drivers will render the * primitives using exactly the same algorithms as those used * by BufferedImage. This could result in minor differences in * pixel values between BufferedImage and VolatileImage. * * The pipelines for D3d and OpenGL adjust the rendering with * fudge factors to align output of GPU rendering with that of * CPU rendering. Some of the draw calls in this paint method * are commented indicating a need to fine tune the fudge * factors in the future. Once they are found to work on all * hardware, the draw calls will be enabled. */ // rectangular fill gImg[i].setColor(Color.blue); gImg[i].fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE); /* * Image copy. Copy it 3 times to get any image management * acceleration going */ int spriteW = sprite.getWidth(null); gImg[i].drawImage(sprite, 0, 0, null); gImg[i].drawImage(sprite, spriteW, 0, null); gImg[i].drawImage(sprite, 2 * spriteW, 0, null); // horizontal/vertical/diagonal lines gImg[i].setColor(Color.red); gImg[i].drawLine(0, 0, IMAGE_SIZE - 1, IMAGE_SIZE - 1); gImg[i].drawLine(IMAGE_SIZE / 2, 0, IMAGE_SIZE / 2, IMAGE_SIZE - 1); //gImg[i].drawLine(IMAGE_SIZE, 0, // 0, IMAGE_SIZE - 1); gImg[i].drawLine(0, IMAGE_SIZE / 2, IMAGE_SIZE - 1, IMAGE_SIZE / 2); // filled circle //gImg[i].setColor(Color.yellow); //gImg[i].fillOval(IMAGE_SIZE / 2 - 20, IMAGE_SIZE / 2 - 20, // 40, 40); } /* * Now everything is drawn: let's compare pixels * First, grab the pixel arrays */ int cRgbTransparent[] = new int[IMAGE_SIZE * IMAGE_SIZE]; int cRgbTranslucent[] = new int[IMAGE_SIZE * IMAGE_SIZE]; int vRgbTransparent[] = new int[IMAGE_SIZE * IMAGE_SIZE]; int vRgbTranslucent[] = new int[IMAGE_SIZE * IMAGE_SIZE]; cImgTransparent.getRGB(0, 0, IMAGE_SIZE, IMAGE_SIZE, cRgbTransparent, 0, IMAGE_SIZE); cImgTranslucent.getRGB(0, 0, IMAGE_SIZE, IMAGE_SIZE, cRgbTranslucent, 0, IMAGE_SIZE); BufferedImage bImgTransparent = vImgTransparent.getSnapshot(); bImgTransparent.getRGB(0, 0, IMAGE_SIZE, IMAGE_SIZE, vRgbTransparent, 0, IMAGE_SIZE); BufferedImage bImgTranslucent = vImgTranslucent.getSnapshot(); bImgTranslucent.getRGB(0, 0, IMAGE_SIZE, IMAGE_SIZE, vRgbTranslucent, 0, IMAGE_SIZE); boolean failed = false; for (int pixel = 0; pixel < cRgbTransparent.length; ++pixel) { if (cRgbTransparent[pixel] != vRgbTransparent[pixel]) { failed = true; System.out.println("Error in transparent image: " + "BI[" + pixel + "] = " + Integer.toHexString(cRgbTransparent[pixel]) + "VI[" + pixel + "] = " + Integer.toHexString(vRgbTransparent[pixel])); break; } if (cRgbTranslucent[pixel] != vRgbTranslucent[pixel]) { failed = true; System.out.println("Error in translucent image: " + "BI[" + pixel + "] = " + Integer.toHexString(cRgbTranslucent[pixel]) + "VI[" + pixel + "] = " + Integer.toHexString(vRgbTranslucent[pixel])); break; } } if (failed) { throw new RuntimeException("Failed: Pixel mis-match observed"); } else { System.out.println("Passed"); } doneComparing = true; } g.drawImage(cImgTransparent, 0, 0, null); g.drawImage(cImgTranslucent, getWidth() - IMAGE_SIZE, 0, null); g.drawImage(vImgTransparent, 0, getHeight() - IMAGE_SIZE, null); g.drawImage(vImgTranslucent, getWidth() - IMAGE_SIZE, getHeight() - IMAGE_SIZE, null); } private static void constructTestUI() { testFrame = new JFrame(); testFrame.setSize(600, 600); testFrame.setResizable(false); testFrame.getContentPane().add(new TransparentVImage()); testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); testFrame.setLocationRelativeTo(null); testFrame.setVisible(true); } private static void destroyTestUI() { testFrame.dispose(); } public static void main(String args[]) throws Exception { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { try { // Construct the test interface constructTestUI(); } catch (Exception ex) { // Throw an exception indicating error while creating UI throw new RuntimeException("Test Failed: Error while" + " creating the test interface."); } } }); /* * Wait until the image comparison between VolatileImage and * BufferedImage is complete. */ while (!doneComparing) { try { Thread.sleep(100); } catch (Exception e) {} } /* * Now sleep just a little longer to let the user see the resulting * images in the frame */ try { Thread.sleep(5000); } catch (Exception e) {} SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { try { // Destroy the test interface destroyTestUI(); } catch (Exception ex) { // Throw an exception indicating error while deleting UI throw new RuntimeException("Test Failed: Error while" + " deleting the test interface."); } } }); } }