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