1 /* 2 * Copyright (c) 2010, 2011, 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 @bug 5089429 6982632 8145808 27 @summary Checks that we don't crash if rendering operations and state 28 changes are performed on a graphics context from different threads. 29 30 @author Dmitri.Trembovetski@sun.com area=Graphics 31 @run main MTGraphicsAccessTest 32 */ 33 34 import java.awt.*; 35 import java.awt.image.*; 36 import java.awt.geom.*; 37 import java.util.concurrent.atomic.AtomicInteger; 38 39 public class MTGraphicsAccessTest { 40 41 // in seconds 42 static final long STANDALONE_RUN_TIME = 20; 43 static final long JTREG_RUN_TIME = 7; 44 45 static boolean standaloneMode; 46 static boolean allowExceptions = true; 47 static long testRunTime; 48 49 volatile boolean done; 50 AtomicInteger stillRunning = new AtomicInteger(0); 51 volatile int numexceptions; 52 53 Graphics2D sharedGraphics; 54 BufferedImage sharedBI = 55 new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); 56 57 static final Paint colors[] = { 58 Color.red, 59 new Color(0x7f, 0xff, 0x00, 0x7f), 60 new GradientPaint(0, 0, Color.red, 61 50, 50, new Color(0x7f, 0xff, 0x00, 0x7f)), 62 }; 63 static final Font fonts[] = { 64 new Font("Dialog", Font.PLAIN, 12), 65 new Font("Dialog", Font.BOLD, 16), 66 new Font("Dialog", Font.ITALIC, 18), 67 }; 68 static final AlphaComposite comps[] = { 69 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f), 70 AlphaComposite.Src, 71 AlphaComposite.Xor, 72 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f), 73 null, 74 }; 75 static final Stroke strokes[] = { 76 new BasicStroke(), 77 new BasicStroke(0.0f), 78 new BasicStroke(2.0f), 79 new BasicStroke(2.0f, BasicStroke.CAP_ROUND, 80 BasicStroke.JOIN_BEVEL), 81 new BasicStroke(5.0f, BasicStroke.CAP_SQUARE, 82 BasicStroke.JOIN_ROUND), 83 new BasicStroke(0.0f, BasicStroke.CAP_ROUND, 84 BasicStroke.JOIN_ROUND, 0, 85 new float[]{0,6,0,6}, 0), 86 }; 87 static final AffineTransform transforms[] = { 88 new AffineTransform(), 89 AffineTransform.getRotateInstance(10.0), 90 AffineTransform.getShearInstance(10.0, 4.0), 91 AffineTransform.getScaleInstance(1.1, 1.2), 92 AffineTransform.getScaleInstance(3.0, 2.0), 93 }; 94 95 public MTGraphicsAccessTest() { 96 BufferedImage bi = 97 new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); 98 sharedGraphics = (Graphics2D)bi.getGraphics(); 99 100 done = false; 101 numexceptions = 0; 102 103 for (int i = 0; i < (standaloneMode ? stateChangers.length : 3); i++) { 104 (new TesterThread(stateChangers[i])).start(); 105 } 106 for (int i = 0; i < (standaloneMode ? renderTests.length : 5); i++) { 107 (new TesterThread(renderTests[i])).start(); 108 } 109 110 mysleep(testRunTime); 111 done = true; 112 while (stillRunning.get() > 0) { mysleep(500); } 113 114 if (numexceptions == 0) { 115 System.err.println("Test passed"); 116 } else if (!allowExceptions) { 117 throw new RuntimeException("Test failed with "+ 118 numexceptions+" exceptions"); 119 } else { 120 System.err.println("Test finished with "+ 121 numexceptions+" exceptions"); 122 } 123 } 124 125 private void mysleep(long time) { 126 try { 127 // add +/-5ms variance to increase randomness 128 Thread.sleep(time + (long)(5 - Math.random()*10)); 129 } catch (InterruptedException e) {}; 130 } 131 132 public static void usage(String message) { 133 if (message != null) { 134 System.err.println(message); 135 } 136 System.err.println("Usage: MTGraphicsAccessTest [-full] "+ 137 "[-time N/forever] [-help]"); 138 System.err.println(" -full: run full suite of tests "+ 139 "(default: limited number of tests is run)"); 140 System.err.println(" -time N: test duration in seconds/forever"+ 141 " (default: "+JTREG_RUN_TIME+"s for the short suite, "+ 142 STANDALONE_RUN_TIME+"s for the full suite)"); 143 System.err.println(" -help: print this help page"); 144 System.exit(1); 145 } 146 147 public static void main(String[] args) { 148 boolean testRunSet = false; 149 for (int i = 0; i < args.length; i++) { 150 if ("-full".equals(args[i])) { 151 standaloneMode = true; 152 System.err.println("Running complete list of tests"); 153 } else if ("-noexc".equals(args[i])) { 154 allowExceptions = false; 155 } else if ("-time".equals(args[i])) { 156 try { 157 String time = args[++i]; 158 if ("forever".equals(time)) { 159 testRunTime = (Long.MAX_VALUE - 20)/1000; 160 } else { 161 testRunTime = 1000*Integer.parseInt(time); 162 } 163 testRunSet = true; 164 } catch (NumberFormatException e) { 165 usage("Can't parse number of seconds: " + args[i]); 166 } catch (ArrayIndexOutOfBoundsException e1) { 167 usage("Missing the 'seconds' argument for -time parameter"); 168 } 169 } else if ("-help".equals(args[i])) { 170 usage(null); 171 } else { 172 usage("Unknown argument:" + args[i]); 173 } 174 } 175 176 if (!testRunSet) { 177 testRunTime = 1000 * 178 (standaloneMode ? STANDALONE_RUN_TIME : JTREG_RUN_TIME); 179 } 180 181 System.err.println("Approximate test run time: "+ 182 testRunTime/1000+" seconds"); 183 184 new MTGraphicsAccessTest(); 185 } 186 187 class TesterThread extends Thread { 188 Runnable testRunnable; 189 190 public TesterThread(Runnable testRunnable) { 191 stillRunning.incrementAndGet(); 192 this.testRunnable = testRunnable; 193 } 194 195 public void run() { 196 try { 197 while (!done) { 198 try { 199 testRunnable.run(); 200 yield(); 201 } catch (Throwable t) { 202 numexceptions++; 203 t.printStackTrace(); 204 } 205 } 206 } finally { 207 stillRunning.decrementAndGet(); 208 } 209 } 210 } 211 212 final Runnable stateChangers[] = { 213 new Runnable() { 214 public void run() { 215 sharedGraphics.setClip(10, 10, 30, 30); 216 mysleep(10); 217 } 218 }, 219 new Runnable() { 220 public void run() { 221 sharedGraphics.setClip(10, 10, 30, 30); 222 mysleep(10); 223 } 224 }, 225 new Runnable() { 226 int c = 0; 227 public void run() { 228 sharedGraphics.setPaint(colors[c++ % colors.length]); 229 mysleep(10); 230 } 231 }, 232 new Runnable() { 233 boolean AA = false; 234 public void run() { 235 if (AA) { 236 sharedGraphics.setRenderingHint( 237 RenderingHints.KEY_ANTIALIASING, 238 RenderingHints.VALUE_ANTIALIAS_ON); 239 } else { 240 sharedGraphics.setRenderingHint( 241 RenderingHints.KEY_ANTIALIASING, 242 RenderingHints.VALUE_ANTIALIAS_OFF); 243 } 244 AA = !AA; 245 mysleep(10); 246 } 247 }, 248 new Runnable() { 249 int t = 0; 250 public void run() { 251 sharedGraphics.setTransform( 252 transforms[t++ % transforms.length]); 253 mysleep(10); 254 } 255 }, 256 new Runnable() { 257 int c = 0; 258 public void run() { 259 AlphaComposite comp = comps[c++ % comps.length]; 260 if (comp == null) { 261 sharedGraphics.setXORMode(Color.green); 262 } else { 263 sharedGraphics.setComposite(comp); 264 } 265 mysleep(10); 266 } 267 }, 268 new Runnable() { 269 int s = 0; 270 public void run() { 271 sharedGraphics.setStroke(strokes[s++ % strokes.length]); 272 mysleep(10); 273 } 274 }, 275 new Runnable() { 276 int f = 0; 277 public void run() { 278 sharedGraphics.setFont(fonts[f++ % fonts.length]); 279 mysleep(10); 280 } 281 }, 282 }; 283 284 final Runnable renderTests[] = { 285 new Runnable() { 286 public void run() { 287 sharedGraphics.drawLine(10, 10, 30, 30); 288 } 289 }, 290 new Runnable() { 291 public void run() { 292 sharedGraphics.drawLine(10, 10, 30, 30); 293 } 294 }, 295 new Runnable() { 296 public void run() { 297 sharedGraphics.drawRect(10, 10, 30, 30); 298 } 299 }, 300 new Runnable() { 301 public void run() { 302 sharedGraphics.fillRect(10, 10, 30, 30); 303 } 304 }, 305 new Runnable() { 306 public void run() { 307 sharedGraphics.drawString("Stuff", 10, 10); 308 } 309 }, 310 new Runnable() { 311 public void run() { 312 sharedGraphics.draw3DRect(10, 10, 30, 30, true); 313 } 314 }, 315 new Runnable() { 316 public void run() { 317 sharedGraphics.drawImage(sharedBI, 10, 10, null); 318 } 319 }, 320 new Runnable() { 321 public void run() { 322 sharedGraphics.fill3DRect(10, 10, 30, 30, false); 323 } 324 }, 325 // REMIND: copyArea doesn't work when transform is set.. 326 // new Runnable() { 327 // public void run() { 328 // sharedGraphics.copyArea(10, 10, 30, 30, 20, 20); 329 // } 330 // }, 331 new Runnable() { 332 public void run() { 333 sharedGraphics.drawRoundRect(10, 10, 30, 30, 20, 20); 334 } 335 }, 336 new Runnable() { 337 public void run() { 338 sharedGraphics.fillRoundRect(10, 10, 30, 30, 20, 20); 339 } 340 }, 341 new Runnable() { 342 public void run() { 343 sharedGraphics.drawArc(10, 10, 30, 30, 0, 90); 344 } 345 }, 346 new Runnable() { 347 public void run() { 348 sharedGraphics.fillArc(10, 10, 30, 30, 0, 90); 349 } 350 }, 351 new Runnable() { 352 public void run() { 353 sharedGraphics.drawOval(10, 10, 30, 30); 354 } 355 }, 356 new Runnable() { 357 public void run() { 358 sharedGraphics.fillOval(10, 10, 30, 30); 359 } 360 } 361 }; 362 }