1 /*
   2  * Copyright (c) 2007, 2008, 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  * @bug 6635805 6653780 6667607
  26  * @summary Tests that the resource sharing layer API is not broken
  27  * @author Dmitri.Trembovetski@sun.com: area=Graphics
  28  * @compile -XDignore.symbol.file=true RSLAPITest.java
  29  * @run main/othervm RSLAPITest
  30  * @run main/othervm -Dsun.java2d.noddraw=true RSLAPITest
  31  * @run main/othervm -Dsun.java2d.opengl=True RSLAPITest
  32  */
  33 
  34 import java.awt.Graphics;
  35 import java.awt.GraphicsConfiguration;
  36 import java.awt.GraphicsDevice;
  37 import java.awt.GraphicsEnvironment;
  38 import java.awt.Rectangle;
  39 import java.awt.Transparency;
  40 import java.awt.image.VolatileImage;
  41 import java.util.HashSet;
  42 import sun.java2d.DestSurfaceProvider;
  43 import sun.java2d.Surface;
  44 import sun.java2d.pipe.BufferedContext;
  45 import sun.java2d.pipe.RenderQueue;
  46 import sun.java2d.pipe.hw.AccelDeviceEventListener;
  47 import sun.java2d.pipe.hw.AccelGraphicsConfig;
  48 import sun.java2d.pipe.hw.AccelSurface;
  49 import static java.awt.Transparency.*;
  50 import java.lang.reflect.Field;
  51 import static sun.java2d.pipe.hw.AccelSurface.*;
  52 import static sun.java2d.pipe.hw.ContextCapabilities.*;
  53 
  54 public class RSLAPITest {
  55     private static volatile boolean failed = false;
  56 
  57     public static void main(String[] args) {
  58         GraphicsEnvironment ge =
  59                 GraphicsEnvironment.getLocalGraphicsEnvironment();
  60         GraphicsDevice gd = ge.getDefaultScreenDevice();
  61         GraphicsConfiguration gc = gd.getDefaultConfiguration();
  62         testGC(gc);
  63 
  64         if (failed) {
  65             throw new RuntimeException("Test FAILED. See err output for more");
  66         }
  67 
  68         System.out.println("Test PASSED.");
  69     }
  70 
  71     private static void testInvalidType(AccelSurface surface, int type) {
  72         long ret = surface.getNativeResource(type);
  73         System.out.printf("  getNativeResource(%d)=0x%x\n", type, ret);
  74         if (ret != 0l) {
  75             System.err.printf(
  76                     "FAILED: surface.getNativeResource(%d) returned" +
  77                     " 0x%s. It should have have returned 0L\n",
  78                     type, ret);
  79             failed = true;
  80         }
  81     }
  82 
  83     private static void testD3DDeviceResourceField(final AccelSurface surface) {
  84         try {
  85             Class d3dc = Class.forName("sun.java2d.d3d.D3DSurfaceData");
  86             if (d3dc.isInstance(surface)) {
  87                 Field f = d3dc.getDeclaredField("D3D_DEVICE_RESOURCE");
  88                 f.setAccessible(true);
  89                 int d3dDR = (Integer)f.get(null);
  90 
  91                 System.out.printf(
  92                         "  getNativeResource(D3D_DEVICE_RESOURCE)=0x%x\n",
  93                         surface.getNativeResource(d3dDR));
  94             }
  95         } catch (ClassNotFoundException e) {}
  96         catch (IllegalAccessException e) {}
  97         catch (NoSuchFieldException e) {
  98             System.err.println("Failed: D3DSurfaceData.D3D_DEVICE_RESOURCE" +
  99                                " field not found!");
 100             failed = true;
 101         }
 102     }
 103 
 104     private static void printSurface(Surface s) {
 105         if (s instanceof AccelSurface) {
 106             final AccelSurface surface = (AccelSurface) s;
 107             System.out.println(" Accel Surface: ");
 108             System.out.println("  type=" + surface.getType());
 109             System.out.println("  bounds=" + surface.getBounds());
 110             System.out.println("  nativeBounds=" + surface.getNativeBounds());
 111             System.out.println("  isSurfaceLost=" + surface.isSurfaceLost());
 112             System.out.println("  isValid=" + surface.isValid());
 113             RenderQueue rq = surface.getContext().getRenderQueue();
 114             rq.lock();
 115             try {
 116                 rq.flushAndInvokeNow(new Runnable() {
 117                     public void run() {
 118                         System.out.printf("  getNativeResource(TEXTURE)=0x%x\n",
 119                             surface.getNativeResource(TEXTURE));
 120                         System.out.printf("  getNativeResource(RT_TEXTURE)=0x%x\n",
 121                             surface.getNativeResource(RT_TEXTURE));
 122                         System.out.printf("  getNativeResource(RT_PLAIN)=0x%x\n",
 123                             surface.getNativeResource(RT_PLAIN));
 124                         System.out.printf(
 125                             "  getNativeResource(FLIP_BACKBUFFER)=0x%x\n",
 126                             surface.getNativeResource(FLIP_BACKBUFFER));
 127 
 128                         testD3DDeviceResourceField(surface);
 129 
 130                         testInvalidType(surface, -1);
 131                         testInvalidType(surface, -150);
 132                         testInvalidType(surface, 300);
 133                         testInvalidType(surface, Integer.MAX_VALUE);
 134                         testInvalidType(surface, Integer.MIN_VALUE);
 135                     }
 136                 });
 137             } finally {
 138                 rq.unlock();
 139             }
 140         } else {
 141             System.out.println("null accelerated surface");
 142         }
 143     }
 144 
 145     private static void printAGC(AccelGraphicsConfig agc) {
 146         System.out.println("Accelerated Graphics Config: " + agc);
 147         System.out.println("Capabilities:");
 148         System.out.printf("AGC caps: 0x%x\n",
 149                           agc.getContextCapabilities().getCaps());
 150         System.out.println(agc.getContextCapabilities());
 151     }
 152 
 153     private static void testGC(GraphicsConfiguration gc) {
 154         if (!(gc instanceof AccelGraphicsConfig)) {
 155             System.out.println("Test passed: no hw accelerated configs found.");
 156             return;
 157         }
 158         System.out.println("AccelGraphicsConfig exists, testing.");
 159         AccelGraphicsConfig agc = (AccelGraphicsConfig) gc;
 160         printAGC(agc);
 161 
 162         testContext(agc);
 163 
 164         VolatileImage vi = gc.createCompatibleVolatileImage(10, 10);
 165         vi.validate(gc);
 166         if (vi instanceof DestSurfaceProvider) {
 167             System.out.println("Passed: VI is DestSurfaceProvider");
 168             Surface s = ((DestSurfaceProvider) vi).getDestSurface();
 169             if (s instanceof AccelSurface) {
 170                 System.out.println("Passed: Obtained Accel Surface");
 171                 printSurface((AccelSurface) s);
 172             }
 173             Graphics g = vi.getGraphics();
 174             if (g instanceof DestSurfaceProvider) {
 175                 System.out.println("Passed: VI graphics is " +
 176                                    "DestSurfaceProvider");
 177                 printSurface(((DestSurfaceProvider) g).getDestSurface());
 178             }
 179         } else {
 180             System.out.println("VI is not DestSurfaceProvider");
 181         }
 182         testVICreation(agc, CAPS_RT_TEXTURE_ALPHA, TRANSLUCENT, RT_TEXTURE);
 183         testVICreation(agc, CAPS_RT_TEXTURE_OPAQUE, OPAQUE, RT_TEXTURE);
 184         testVICreation(agc, CAPS_RT_PLAIN_ALPHA, TRANSLUCENT, RT_PLAIN);
 185         testVICreation(agc, agc.getContextCapabilities().getCaps(), OPAQUE,
 186                        TEXTURE);
 187         testForNPEDuringCreation(agc);
 188     }
 189 
 190     private static void testVICreation(AccelGraphicsConfig agc, int cap,
 191                                        int transparency, int type)
 192     {
 193         int caps = agc.getContextCapabilities().getCaps();
 194         int w = 11, h = 17;
 195 
 196         VolatileImage vi =
 197             agc.createCompatibleVolatileImage(w, h, transparency, type);
 198         if ((cap & caps) != 0) {
 199             if (vi == null) {
 200                 System.out.printf("Failed: cap=%d is supported but " +
 201                                   "image wasn't created\n", cap);
 202                 throw new RuntimeException("Failed: image wasn't created " +
 203                                            "for supported cap");
 204             } else {
 205                 if (!(vi instanceof DestSurfaceProvider)) {
 206                     throw new RuntimeException("Failed: created VI is not " +
 207                                                "DestSurfaceProvider");
 208                 }
 209                 Surface s = ((DestSurfaceProvider) vi).getDestSurface();
 210                 if (s instanceof AccelSurface) {
 211                     AccelSurface as = (AccelSurface) s;
 212                     printSurface(as);
 213                     if (as.getType() != type) {
 214                         throw new RuntimeException("Failed: returned VI is" +
 215                                 " of incorrect type: " + as.getType() +
 216                                 " requested type=" + type);
 217                     } else {
 218                         System.out.printf("Passed: VI of type %d was " +
 219                                 "created for cap=%d\n", type, cap);
 220                     }
 221                     if (as.getType() == TEXTURE) {
 222                         boolean ex = false;
 223                         try {
 224                             Graphics g = vi.getGraphics();
 225                             g.dispose();
 226                         } catch (UnsupportedOperationException e) {
 227                             ex = true;
 228                         }
 229                         if (!ex) {
 230                             throw new RuntimeException("Failed: " +
 231                                 "texture.getGraphics() didn't throw exception");
 232                         } else {
 233                             System.out.println("Passed: VI.getGraphics()" +
 234                                     " threw exception for texture-based VI");
 235                         }
 236                     }
 237                 } else {
 238                     System.out.printf("Passed: VI of type %d was " +
 239                             "created for cap=%d but accel surface is null\n",
 240                             type, cap);
 241                 }
 242             }
 243         } else {
 244             if (vi != null) {
 245                 throw new RuntimeException("Failed: created VI for " +
 246                                            "unsupported cap=" + cap);
 247             }
 248         }
 249     }
 250 
 251     private static void testContext(final AccelGraphicsConfig agc) {
 252         BufferedContext c = agc.getContext();
 253         final AccelDeviceEventListener l = new AccelDeviceEventListener() {
 254             public void onDeviceDispose() {
 255                 System.out.println("onDeviceDispose invoked");
 256                 agc.removeDeviceEventListener(this);
 257             }
 258             public void onDeviceReset() {
 259                 System.out.println("onDeviceReset invoked");
 260             }
 261         };
 262         agc.addDeviceEventListener(l);
 263 
 264         RenderQueue rq = c.getRenderQueue();
 265         rq.lock();
 266         try {
 267             c.saveState();
 268             rq.flushNow();
 269             c.restoreState();
 270             rq.flushNow();
 271             System.out.println("Passed: Save/Restore");
 272         } finally {
 273             rq.unlock();
 274         }
 275     }
 276 
 277     private static void testForNPEDuringCreation(AccelGraphicsConfig agc) {
 278         int iterations = 100;
 279         HashSet<VolatileImage> vis = new HashSet<VolatileImage>();
 280         GraphicsConfiguration gc = (GraphicsConfiguration)agc;
 281         Rectangle r = gc.getBounds();
 282         long ram = gc.getDevice().getAvailableAcceleratedMemory();
 283         if (ram > 0) {
 284             // guesstimate the number of iterations needed to exhaust vram
 285             int i = 2 *
 286                 (int)(ram / (r.width * r.height * gc.getColorModel().getPixelSize()/8));
 287             iterations = Math.max(iterations, i);
 288             System.err.println("iterations="+iterations);
 289         }
 290         for (int i = 0; i < iterations; i++) {
 291             VolatileImage vi =
 292                 agc.createCompatibleVolatileImage(r.width, r.height,
 293                                                   Transparency.OPAQUE,
 294                                                   AccelSurface.RT_PLAIN);
 295             if (vi == null) {
 296                 break;
 297             }
 298             vis.add(vi);
 299         }
 300         for (VolatileImage vi : vis) {
 301             vi.flush();
 302         }
 303         vis = null;
 304 
 305         System.out.println("Passed: testing for possible NPEs " +
 306                            "during VI creation");
 307     }
 308 }