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