| /* |
| * Copyright (c) 2010, 2011, 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 5089429 6982632 8145808 |
| @summary Checks that we don't crash if rendering operations and state |
| changes are performed on a graphics context from different threads. |
| |
| @author Dmitri.Trembovetski@sun.com area=Graphics |
| @run main MTGraphicsAccessTest |
| */ |
| |
| import java.awt.*; |
| import java.awt.image.*; |
| import java.awt.geom.*; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| public class MTGraphicsAccessTest { |
| |
| // in seconds |
| static final long STANDALONE_RUN_TIME = 20; |
| static final long JTREG_RUN_TIME = 7; |
| |
| static boolean standaloneMode; |
| static boolean allowExceptions = true; |
| static long testRunTime; |
| |
| volatile boolean done; |
| AtomicInteger stillRunning = new AtomicInteger(0); |
| volatile int numexceptions; |
| |
| Graphics2D sharedGraphics; |
| BufferedImage sharedBI = |
| new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); |
| |
| static final Paint colors[] = { |
| Color.red, |
| new Color(0x7f, 0xff, 0x00, 0x7f), |
| new GradientPaint(0, 0, Color.red, |
| 50, 50, new Color(0x7f, 0xff, 0x00, 0x7f)), |
| }; |
| static final Font fonts[] = { |
| new Font("Dialog", Font.PLAIN, 12), |
| new Font("Dialog", Font.BOLD, 16), |
| new Font("Dialog", Font.ITALIC, 18), |
| }; |
| static final AlphaComposite comps[] = { |
| AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f), |
| AlphaComposite.Src, |
| AlphaComposite.Xor, |
| AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f), |
| null, |
| }; |
| static final Stroke strokes[] = { |
| new BasicStroke(), |
| new BasicStroke(0.0f), |
| new BasicStroke(2.0f), |
| new BasicStroke(2.0f, BasicStroke.CAP_ROUND, |
| BasicStroke.JOIN_BEVEL), |
| new BasicStroke(5.0f, BasicStroke.CAP_SQUARE, |
| BasicStroke.JOIN_ROUND), |
| new BasicStroke(0.0f, BasicStroke.CAP_ROUND, |
| BasicStroke.JOIN_ROUND, 0, |
| new float[]{0,6,0,6}, 0), |
| }; |
| static final AffineTransform transforms[] = { |
| new AffineTransform(), |
| AffineTransform.getRotateInstance(10.0), |
| AffineTransform.getShearInstance(10.0, 4.0), |
| AffineTransform.getScaleInstance(1.1, 1.2), |
| AffineTransform.getScaleInstance(3.0, 2.0), |
| }; |
| |
| public MTGraphicsAccessTest() { |
| BufferedImage bi = |
| new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); |
| sharedGraphics = (Graphics2D)bi.getGraphics(); |
| |
| done = false; |
| numexceptions = 0; |
| |
| for (int i = 0; i < (standaloneMode ? stateChangers.length : 3); i++) { |
| (new TesterThread(stateChangers[i])).start(); |
| } |
| for (int i = 0; i < (standaloneMode ? renderTests.length : 5); i++) { |
| (new TesterThread(renderTests[i])).start(); |
| } |
| |
| mysleep(testRunTime); |
| done = true; |
| while (stillRunning.get() > 0) { mysleep(500); } |
| |
| if (numexceptions == 0) { |
| System.err.println("Test passed"); |
| } else if (!allowExceptions) { |
| throw new RuntimeException("Test failed with "+ |
| numexceptions+" exceptions"); |
| } else { |
| System.err.println("Test finished with "+ |
| numexceptions+" exceptions"); |
| } |
| } |
| |
| private void mysleep(long time) { |
| try { |
| // add +/-5ms variance to increase randomness |
| Thread.sleep(time + (long)(5 - Math.random()*10)); |
| } catch (InterruptedException e) {}; |
| } |
| |
| public static void usage(String message) { |
| if (message != null) { |
| System.err.println(message); |
| } |
| System.err.println("Usage: MTGraphicsAccessTest [-full] "+ |
| "[-time N/forever] [-help]"); |
| System.err.println(" -full: run full suite of tests "+ |
| "(default: limited number of tests is run)"); |
| System.err.println(" -time N: test duration in seconds/forever"+ |
| " (default: "+JTREG_RUN_TIME+"s for the short suite, "+ |
| STANDALONE_RUN_TIME+"s for the full suite)"); |
| System.err.println(" -help: print this help page"); |
| System.exit(1); |
| } |
| |
| public static void main(String[] args) { |
| boolean testRunSet = false; |
| for (int i = 0; i < args.length; i++) { |
| if ("-full".equals(args[i])) { |
| standaloneMode = true; |
| System.err.println("Running complete list of tests"); |
| } else if ("-noexc".equals(args[i])) { |
| allowExceptions = false; |
| } else if ("-time".equals(args[i])) { |
| try { |
| String time = args[++i]; |
| if ("forever".equals(time)) { |
| testRunTime = (Long.MAX_VALUE - 20)/1000; |
| } else { |
| testRunTime = 1000*Integer.parseInt(time); |
| } |
| testRunSet = true; |
| } catch (NumberFormatException e) { |
| usage("Can't parse number of seconds: " + args[i]); |
| } catch (ArrayIndexOutOfBoundsException e1) { |
| usage("Missing the 'seconds' argument for -time parameter"); |
| } |
| } else if ("-help".equals(args[i])) { |
| usage(null); |
| } else { |
| usage("Unknown argument:" + args[i]); |
| } |
| } |
| |
| if (!testRunSet) { |
| testRunTime = 1000 * |
| (standaloneMode ? STANDALONE_RUN_TIME : JTREG_RUN_TIME); |
| } |
| |
| System.err.println("Approximate test run time: "+ |
| testRunTime/1000+" seconds"); |
| |
| new MTGraphicsAccessTest(); |
| } |
| |
| class TesterThread extends Thread { |
| Runnable testRunnable; |
| |
| public TesterThread(Runnable testRunnable) { |
| stillRunning.incrementAndGet(); |
| this.testRunnable = testRunnable; |
| } |
| |
| public void run() { |
| try { |
| while (!done) { |
| try { |
| testRunnable.run(); |
| yield(); |
| } catch (Throwable t) { |
| numexceptions++; |
| t.printStackTrace(); |
| } |
| } |
| } finally { |
| stillRunning.decrementAndGet(); |
| } |
| } |
| } |
| |
| final Runnable stateChangers[] = { |
| new Runnable() { |
| public void run() { |
| sharedGraphics.setClip(10, 10, 30, 30); |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.setClip(10, 10, 30, 30); |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| int c = 0; |
| public void run() { |
| sharedGraphics.setPaint(colors[c++ % colors.length]); |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| boolean AA = false; |
| public void run() { |
| if (AA) { |
| sharedGraphics.setRenderingHint( |
| RenderingHints.KEY_ANTIALIASING, |
| RenderingHints.VALUE_ANTIALIAS_ON); |
| } else { |
| sharedGraphics.setRenderingHint( |
| RenderingHints.KEY_ANTIALIASING, |
| RenderingHints.VALUE_ANTIALIAS_OFF); |
| } |
| AA = !AA; |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| int t = 0; |
| public void run() { |
| sharedGraphics.setTransform( |
| transforms[t++ % transforms.length]); |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| int c = 0; |
| public void run() { |
| AlphaComposite comp = comps[c++ % comps.length]; |
| if (comp == null) { |
| sharedGraphics.setXORMode(Color.green); |
| } else { |
| sharedGraphics.setComposite(comp); |
| } |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| int s = 0; |
| public void run() { |
| sharedGraphics.setStroke(strokes[s++ % strokes.length]); |
| mysleep(10); |
| } |
| }, |
| new Runnable() { |
| int f = 0; |
| public void run() { |
| sharedGraphics.setFont(fonts[f++ % fonts.length]); |
| mysleep(10); |
| } |
| }, |
| }; |
| |
| final Runnable renderTests[] = { |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawLine(10, 10, 30, 30); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawLine(10, 10, 30, 30); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawRect(10, 10, 30, 30); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.fillRect(10, 10, 30, 30); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawString("Stuff", 10, 10); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.draw3DRect(10, 10, 30, 30, true); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawImage(sharedBI, 10, 10, null); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.fill3DRect(10, 10, 30, 30, false); |
| } |
| }, |
| // REMIND: copyArea doesn't work when transform is set.. |
| // new Runnable() { |
| // public void run() { |
| // sharedGraphics.copyArea(10, 10, 30, 30, 20, 20); |
| // } |
| // }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawRoundRect(10, 10, 30, 30, 20, 20); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.fillRoundRect(10, 10, 30, 30, 20, 20); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawArc(10, 10, 30, 30, 0, 90); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.fillArc(10, 10, 30, 30, 0, 90); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.drawOval(10, 10, 30, 30); |
| } |
| }, |
| new Runnable() { |
| public void run() { |
| sharedGraphics.fillOval(10, 10, 30, 30); |
| } |
| } |
| }; |
| } |