430N/A/*
2362N/A * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
430N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
430N/A *
430N/A * This code is free software; you can redistribute it and/or modify it
430N/A * under the terms of the GNU General Public License version 2 only, as
430N/A * published by the Free Software Foundation.
430N/A *
430N/A * This code is distributed in the hope that it will be useful, but WITHOUT
430N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
430N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
430N/A * version 2 for more details (a copy is included in the LICENSE file that
430N/A * accompanied this code).
430N/A *
430N/A * You should have received a copy of the GNU General Public License version
430N/A * 2 along with this work; if not, write to the Free Software Foundation,
430N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
430N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
430N/A */
430N/A
430N/A/*
430N/A * @test
430N/A * @bug 4832224 6322584 6328478 6328481 6322580 6588884 6587863
430N/A * @summary Verifies that the pixelization of simple primitives (drawLine,
430N/A * fillRect, drawRect, fill, draw) with the OGL pipeline enabled
430N/A * matches that produced by our software loops. (The primitives tested here
430N/A * are simple enough that the OGL results should match the software results
430N/A * exactly.) There is some overlap with PolyVertTest as we test both
430N/A * solid and XOR rendering here, but this testcase is a bit simpler and
430N/A * more appropriate for quick OGL testing. This test is also useful for
430N/A * comparing quality between our X11/GDI and software pipelines.
430N/A * @run main/othervm SimplePrimQuality
430N/A * @run main/othervm -Dsun.java2d.opengl=True SimplePrimQuality
430N/A * @author campbelc
430N/A */
430N/A
430N/Aimport java.awt.*;
430N/Aimport java.awt.geom.*;
430N/Aimport java.awt.image.*;
430N/Aimport java.io.File;
430N/Aimport java.io.IOException;
430N/Aimport javax.imageio.ImageIO;
430N/A
430N/Apublic class SimplePrimQuality extends Canvas {
430N/A
430N/A private static final int SIZE = 300;
430N/A private static boolean done;
430N/A private static boolean testVI;
430N/A private static volatile BufferedImage capture;
430N/A private static void doCapture(Component test) {
430N/A // Grab the screen region
430N/A try {
430N/A Robot robot = new Robot();
430N/A Point pt1 = test.getLocationOnScreen();
430N/A Rectangle rect =
430N/A new Rectangle(pt1.x, pt1.y, test.getWidth(), test.getHeight());
430N/A capture = robot.createScreenCapture(rect);
430N/A } catch (Exception e) {
430N/A e.printStackTrace();
430N/A }
430N/A }
430N/A
430N/A private static final int[][] rpts = {
430N/A {2, 0, 0, 0},
430N/A {12, 0, 1, 0},
430N/A {22, 0, 0, 1},
430N/A {32, 0, 1, 1},
430N/A {42, 0, 2, 1},
430N/A {52, 0, 1, 2},
430N/A {62, 0, 2, 2},
430N/A {72, 0, 5, 5},
430N/A {82, 0, 10, 10},
430N/A {97, 0, 15, 15},
430N/A };
430N/A
430N/A private void drawLine(Graphics2D g, int x, int y, int dx, int dy) {
430N/A g.drawLine(x, y, x + dx, y + dy);
430N/A }
430N/A
430N/A private void drawLines(Graphics2D g, int s) {
430N/A drawLine(g, 2, 0, 0, 0);
430N/A drawLine(g, 12, 0, 0, s);
430N/A drawLine(g, 22, 0, s, 0);
430N/A drawLine(g, 32, 0, s, s);
430N/A drawLine(g, 42, 0, 0, -s);
430N/A drawLine(g, 52, 0, -s, 0);
430N/A drawLine(g, 62, 0, -s, -s);
430N/A drawLine(g, 72, 0, -s, s);
430N/A drawLine(g, 82, 0, s, -s);
430N/A }
430N/A
430N/A private void fillRects(Graphics2D g) {
430N/A for (int i = 0; i < rpts.length; i++) {
430N/A g.fillRect(rpts[i][0], rpts[i][1], rpts[i][2], rpts[i][3]);
430N/A }
430N/A }
430N/A
430N/A private void drawRects(Graphics2D g) {
430N/A for (int i = 0; i < rpts.length; i++) {
430N/A g.drawRect(rpts[i][0], rpts[i][1], rpts[i][2], rpts[i][3]);
430N/A }
430N/A }
430N/A
430N/A private void fillOvals(Graphics2D g) {
430N/A for (int i = 0; i < rpts.length; i++) {
430N/A // use fill() instead of fillOval(), since the former is more
430N/A // likely to be consistent with our software loops when the
430N/A // OGL pipeline cannot be enabled
430N/A g.fill(new Ellipse2D.Float(rpts[i][0], rpts[i][1],
430N/A rpts[i][2], rpts[i][3]));
430N/A }
430N/A }
430N/A
430N/A private void drawOvals(Graphics2D g) {
430N/A for (int i = 0; i < rpts.length; i++) {
430N/A // use draw() instead of drawOval(), since the former is more
430N/A // likely to be consistent with our software loops when the
430N/A // OGL pipeline cannot be enabled
430N/A g.draw(new Ellipse2D.Float(rpts[i][0], rpts[i][1],
430N/A rpts[i][2], rpts[i][3]));
430N/A }
430N/A }
430N/A
430N/A private void renderShapes(Graphics2D g) {
430N/A // drawLine tests...
430N/A g.translate(0, 5);
430N/A drawLines(g, 1);
430N/A g.translate(0, 10);
430N/A drawLines(g, 4);
430N/A
430N/A // fillRect tests...
430N/A g.translate(0, 10);
430N/A fillRects(g);
430N/A
430N/A // drawRect tests...
430N/A g.translate(0, 20);
430N/A drawRects(g);
430N/A
430N/A // fillOval tests...
430N/A g.translate(0, 20);
430N/A fillOvals(g);
430N/A
430N/A // drawOval tests...
430N/A g.translate(0, 20);
430N/A drawOvals(g);
430N/A }
430N/A
430N/A private void renderTest(Graphics2D g, int w, int h) {
430N/A // on the left side, render the shapes in solid mode
430N/A g.setColor(Color.black);
430N/A g.fillRect(0, 0, w, h);
430N/A g.setColor(Color.green);
430N/A renderShapes(g);
430N/A
430N/A // on the right side, render the shapes in XOR mode
430N/A g.setTransform(AffineTransform.getTranslateInstance(SIZE/2, 0));
430N/A g.setXORMode(Color.black);
430N/A renderShapes(g);
430N/A g.setTransform(AffineTransform.getTranslateInstance(SIZE/2, 0));
430N/A renderShapes(g);
430N/A }
430N/A
430N/A public void paint(Graphics g) {
430N/A
430N/A Graphics2D g2d = (Graphics2D)g;
430N/A renderTest(g2d, SIZE, SIZE);
430N/A
430N/A Toolkit.getDefaultToolkit().sync();
430N/A
430N/A synchronized (this) {
430N/A if (!done) {
430N/A doCapture(this);
430N/A done = true;
430N/A }
430N/A notifyAll();
430N/A }
430N/A }
430N/A
430N/A public Dimension getPreferredSize() {
430N/A return new Dimension(SIZE, SIZE);
430N/A }
430N/A
430N/A public static void main(String[] args) {
430N/A boolean show = false;
430N/A for (String arg : args) {
430N/A if (arg.equals("-testvi")) {
430N/A System.out.println("Testing VolatileImage, not screen");
430N/A testVI = true;
430N/A } else if (arg.equals("-show")) {
430N/A show = true;
430N/A }
430N/A }
430N/A
430N/A SimplePrimQuality test = new SimplePrimQuality();
430N/A Frame frame = new Frame();
430N/A frame.add(test);
430N/A frame.pack();
430N/A frame.setVisible(true);
430N/A
430N/A // Wait until the component's been painted
430N/A synchronized (test) {
430N/A while (!done) {
430N/A try {
430N/A test.wait();
430N/A } catch (InterruptedException e) {
430N/A throw new RuntimeException("Failed: Interrupted");
430N/A }
430N/A }
430N/A }
430N/A
430N/A // REMIND: We will allow this test to pass silently on Windows
430N/A // (when OGL is not enabled) until we fix the GDI pipeline so that
430N/A // its stroked/filled GeneralPaths match our software loops (see
430N/A // 6322554). This check should be removed when 6322554 is fixed.
430N/A GraphicsConfiguration gc = frame.getGraphicsConfiguration();
430N/A if (gc.getClass().getSimpleName().startsWith("Win")) {
430N/A System.out.println("GDI pipeline detected: " +
430N/A "test considered PASSED");
430N/A frame.dispose();
430N/A return;
430N/A }
430N/A
430N/A
430N/A if (testVI) {
430N/A // render to a VI instead of the screen
430N/A VolatileImage vi = frame.createVolatileImage(SIZE, SIZE);
430N/A do {
430N/A vi.validate(frame.getGraphicsConfiguration());
430N/A Graphics2D g1 = vi.createGraphics();
430N/A test.renderTest(g1, SIZE, SIZE);
430N/A g1.dispose();
430N/A capture = vi.getSnapshot();
430N/A } while (vi.contentsLost());
430N/A frame.dispose();
430N/A }
430N/A
430N/A if (!show) {
430N/A frame.dispose();
430N/A }
430N/A if (capture == null) {
430N/A throw new RuntimeException("Error capturing the rendering");
430N/A }
430N/A
430N/A // Create reference image
430N/A int w = SIZE, h = SIZE;
430N/A BufferedImage refimg = new BufferedImage(w, h,
430N/A BufferedImage.TYPE_INT_RGB);
430N/A Graphics2D g = refimg.createGraphics();
430N/A test.renderTest(g, w, h);
430N/A g.dispose();
430N/A
430N/A // Test pixels
430N/A for (int y = 0; y < h; y++) {
430N/A for (int x = 0; x < w; x++) {
430N/A int actual = capture.getRGB(x, y);
430N/A int expected = refimg.getRGB(x, y);
430N/A if (actual != expected) {
430N/A String expectedName = "SimplePrimQuality_expected.png";
430N/A String actualName = "SimplePrimQuality_actual.png";
430N/A try {
430N/A System.out.println("Writing expected image to: "+
430N/A expectedName);
430N/A ImageIO.write(refimg, "png", new File(expectedName));
430N/A System.out.println("Writing actual image to: "+
430N/A actualName);
430N/A ImageIO.write(capture, "png", new File(actualName));
430N/A } catch (IOException ex) {}
430N/A throw new RuntimeException("Test failed at x="+x+" y="+y+
430N/A " (expected="+
430N/A Integer.toHexString(expected) +
430N/A " actual="+
430N/A Integer.toHexString(actual) +
430N/A ")");
430N/A }
430N/A }
430N/A }
430N/A }
430N/A}