1 /*
   2  * Copyright (c) 2007, 2019, 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 8198613
  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  */
  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.RenderQueue;
  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         VolatileImage vi = gc.createCompatibleVolatileImage(10, 10);
 164         vi.validate(gc);
 165         if (vi instanceof DestSurfaceProvider) {
 166             System.out.println("Passed: VI is DestSurfaceProvider");
 167             Surface s = ((DestSurfaceProvider) vi).getDestSurface();
 168             if (s instanceof AccelSurface) {
 169                 System.out.println("Passed: Obtained Accel Surface");
 170                 printSurface((AccelSurface) s);
 171             }
 172             Graphics g = vi.getGraphics();
 173             if (g instanceof DestSurfaceProvider) {
 174                 System.out.println("Passed: VI graphics is " +
 175                                    "DestSurfaceProvider");
 176                 printSurface(((DestSurfaceProvider) g).getDestSurface());
 177             }
 178         } else {
 179             System.out.println("VI is not DestSurfaceProvider");
 180         }
 181         testVICreation(agc, CAPS_RT_TEXTURE_ALPHA, TRANSLUCENT, RT_TEXTURE);
 182         testVICreation(agc, CAPS_RT_TEXTURE_OPAQUE, OPAQUE, RT_TEXTURE);
 183         testVICreation(agc, CAPS_RT_PLAIN_ALPHA, TRANSLUCENT, RT_PLAIN);
 184         testVICreation(agc, agc.getContextCapabilities().getCaps(), OPAQUE,
 185                        TEXTURE);
 186         testForNPEDuringCreation(agc);
 187     }
 188 
 189     private static void testVICreation(AccelGraphicsConfig agc, int cap,
 190                                        int transparency, int type)
 191     {
 192         int caps = agc.getContextCapabilities().getCaps();
 193         int w = 11, h = 17;
 194 
 195         VolatileImage vi =
 196             agc.createCompatibleVolatileImage(w, h, transparency, type);
 197         if ((cap & caps) != 0) {
 198             if (vi == null) {
 199                 System.out.printf("Failed: cap=%d is supported but " +
 200                                   "image wasn't created\n", cap);
 201                 throw new RuntimeException("Failed: image wasn't created " +
 202                                            "for supported cap");
 203             } else {
 204                 if (!(vi instanceof DestSurfaceProvider)) {
 205                     throw new RuntimeException("Failed: created VI is not " +
 206                                                "DestSurfaceProvider");
 207                 }
 208                 Surface s = ((DestSurfaceProvider) vi).getDestSurface();
 209                 if (s instanceof AccelSurface) {
 210                     AccelSurface as = (AccelSurface) s;
 211                     printSurface(as);
 212                     if (as.getType() != type) {
 213                         throw new RuntimeException("Failed: returned VI is" +
 214                                 " of incorrect type: " + as.getType() +
 215                                 " requested type=" + type);
 216                     } else {
 217                         System.out.printf("Passed: VI of type %d was " +
 218                                 "created for cap=%d\n", type, cap);
 219                     }
 220                     if (as.getType() == TEXTURE) {
 221                         boolean ex = false;
 222                         try {
 223                             Graphics g = vi.getGraphics();
 224                             g.dispose();
 225                         } catch (UnsupportedOperationException e) {
 226                             ex = true;
 227                         }
 228                         if (!ex) {
 229                             throw new RuntimeException("Failed: " +
 230                                 "texture.getGraphics() didn't throw exception");
 231                         } else {
 232                             System.out.println("Passed: VI.getGraphics()" +
 233                                     " threw exception for texture-based VI");
 234                         }
 235                     }
 236                 } else {
 237                     System.out.printf("Passed: VI of type %d was " +
 238                             "created for cap=%d but accel surface is null\n",
 239                             type, cap);
 240                 }
 241             }
 242         } else {
 243             if (vi != null) {
 244                 throw new RuntimeException("Failed: created VI for " +
 245                                            "unsupported cap=" + cap);
 246             }
 247         }
 248     }
 249 
 250     private static void testForNPEDuringCreation(AccelGraphicsConfig agc) {
 251         int iterations = 100;
 252         HashSet<VolatileImage> vis = new HashSet<VolatileImage>();
 253         GraphicsConfiguration gc = (GraphicsConfiguration)agc;
 254         Rectangle r = gc.getBounds();
 255         long ram = gc.getDevice().getAvailableAcceleratedMemory();
 256         if (ram > 0) {
 257             // guesstimate the number of iterations needed to exhaust vram
 258             int i = 2 *
 259                 (int)(ram / (r.width * r.height * gc.getColorModel().getPixelSize()/8));
 260             iterations = Math.max(iterations, i);
 261             System.err.println("iterations="+iterations);
 262         }
 263         for (int i = 0; i < iterations; i++) {
 264             VolatileImage vi =
 265                 agc.createCompatibleVolatileImage(r.width, r.height,
 266                                                   Transparency.OPAQUE,
 267                                                   AccelSurface.RT_PLAIN);
 268             if (vi == null) {
 269                 break;
 270             }
 271             vis.add(vi);
 272         }
 273         for (VolatileImage vi : vis) {
 274             vi.flush();
 275         }
 276         vis = null;
 277 
 278         System.out.println("Passed: testing for possible NPEs " +
 279                            "during VI creation");
 280     }
 281 }