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