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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.d3d;
  27 
  28 import java.awt.AWTException;
  29 import java.awt.BufferCapabilities;
  30 import java.awt.Component;
  31 import java.awt.Graphics;
  32 import java.awt.ImageCapabilities;
  33 import java.awt.Transparency;
  34 import java.awt.color.ColorSpace;
  35 import java.awt.image.ColorModel;
  36 import java.awt.image.DataBuffer;
  37 import java.awt.image.DirectColorModel;
  38 import java.awt.image.VolatileImage;
  39 import sun.awt.Win32GraphicsConfig;
  40 import sun.awt.image.SunVolatileImage;
  41 import sun.awt.image.SurfaceManager;
  42 import sun.awt.windows.WComponentPeer;
  43 import sun.java2d.Surface;
  44 import sun.java2d.SurfaceData;
  45 import sun.java2d.pipe.hw.AccelTypedVolatileImage;
  46 import sun.java2d.pipe.hw.AccelGraphicsConfig;
  47 import sun.java2d.pipe.hw.AccelSurface;
  48 import sun.java2d.pipe.hw.ContextCapabilities;
  49 import static sun.java2d.pipe.hw.AccelSurface.*;
  50 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
  51 
  52 public class D3DGraphicsConfig
  53     extends Win32GraphicsConfig
  54     implements AccelGraphicsConfig
  55 {
  56     private static ImageCapabilities imageCaps = new D3DImageCaps();
  57 
  58     private BufferCapabilities bufferCaps;
  59     private D3DGraphicsDevice device;
  60 
  61     @SuppressWarnings("deprecation")
  62     protected D3DGraphicsConfig(D3DGraphicsDevice device) {
  63         super(device, 0);
  64         this.device = device;
  65     }
  66 
  67     public SurfaceData createManagedSurface(int w, int h, int transparency) {
  68         return D3DSurfaceData.createData(this, w, h,
  69                                          getColorModel(transparency),
  70                                          null,
  71                                          D3DSurfaceData.TEXTURE);
  72     }
  73 
  74     @Override
  75     public synchronized void displayChanged() {
  76         super.displayChanged();
  77         // the context could hold a reference to a D3DSurfaceData, which in
  78         // turn has a reference back to this D3DGraphicsConfig, so in order
  79         // for this instance to be disposed we need to break the connection
  80         D3DRenderQueue rq = D3DRenderQueue.getInstance();
  81         rq.lock();
  82         try {
  83             D3DContext.invalidateCurrentContext();
  84         } finally {
  85             rq.unlock();
  86         }
  87     }
  88 
  89     @Override
  90     public ColorModel getColorModel(int transparency) {
  91         switch (transparency) {
  92         case Transparency.OPAQUE:
  93             // REMIND: once the ColorModel spec is changed, this should be
  94             //         an opaque premultiplied DCM...
  95             return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
  96         case Transparency.BITMASK:
  97             return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
  98         case Transparency.TRANSLUCENT:
  99             ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 100             return new DirectColorModel(cs, 32,
 101                                         0xff0000, 0xff00, 0xff, 0xff000000,
 102                                         true, DataBuffer.TYPE_INT);
 103         default:
 104             return null;
 105         }
 106     }
 107 
 108     @Override
 109     public String toString() {
 110         return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");
 111     }
 112 
 113     /**
 114      * The following methods are invoked from WComponentPeer.java rather
 115      * than having the Win32-dependent implementations hardcoded in that
 116      * class.  This way the appropriate actions are taken based on the peer's
 117      * GraphicsConfig, whether it is a Win32GraphicsConfig or a
 118      * D3DGraphicsConfig.
 119      */
 120 
 121     /**
 122      * Creates a new SurfaceData that will be associated with the given
 123      * WComponentPeer. D3D9 doesn't allow rendering to the screen,
 124      * so a GDI surface will be returned.
 125      */
 126     @Override
 127     public SurfaceData createSurfaceData(WComponentPeer peer,
 128                                          int numBackBuffers)
 129     {
 130         return super.createSurfaceData(peer, numBackBuffers);
 131     }
 132 
 133     /**
 134      * The following methods correspond to the multibuffering methods in
 135      * WComponentPeer.java...
 136      */
 137 
 138     /**
 139      * Checks that the requested configuration is natively supported; if not,
 140      * an AWTException is thrown.
 141      */
 142     @Override
 143     public void assertOperationSupported(Component target,
 144                                          int numBuffers,
 145                                          BufferCapabilities caps)
 146         throws AWTException
 147     {
 148         if (numBuffers < 2 || numBuffers > 4) {
 149             throw new AWTException("Only 2-4 buffers supported");
 150         }
 151         if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED &&
 152             numBuffers != 2)
 153         {
 154             throw new AWTException("FlipContents.COPIED is only" +
 155                                    "supported for 2 buffers");
 156         }
 157     }
 158 
 159     /**
 160      * Creates a D3D-based backbuffer for the given peer and returns the
 161      * image wrapper.
 162      */
 163     @Override
 164     public VolatileImage createBackBuffer(WComponentPeer peer) {
 165         Component target = (Component)peer.getTarget();
 166         // it is possible for the component to have size 0x0, adjust it to
 167         // be at least 1x1 to avoid IAE
 168         int w = Math.max(1, target.getWidth());
 169         int h = Math.max(1, target.getHeight());
 170         return new SunVolatileImage(target, w, h, Boolean.TRUE);
 171     }
 172 
 173     /**
 174      * Performs the native D3D flip operation for the given target Component.
 175      */
 176     @Override
 177     public void flip(WComponentPeer peer,
 178                      Component target, VolatileImage backBuffer,
 179                      int x1, int y1, int x2, int y2,
 180                      BufferCapabilities.FlipContents flipAction)
 181     {
 182         // REMIND: we should actually get a surface data for the
 183         // backBuffer's VI
 184         SurfaceManager d3dvsm =
 185             SurfaceManager.getManager(backBuffer);
 186         SurfaceData sd = d3dvsm.getPrimarySurfaceData();
 187         if (sd instanceof D3DSurfaceData) {
 188             D3DSurfaceData d3dsd = (D3DSurfaceData)sd;
 189             D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2);
 190         } else {
 191             // the surface was likely lost could not have been restored
 192             Graphics g = peer.getGraphics();
 193             try {
 194                 g.drawImage(backBuffer,
 195                             x1, y1, x2, y2,
 196                             x1, y1, x2, y2,
 197                             null);
 198             } finally {
 199                 g.dispose();
 200             }
 201         }
 202 
 203         if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
 204             Graphics g = backBuffer.getGraphics();
 205             try {
 206                 g.setColor(target.getBackground());
 207                 g.fillRect(0, 0,
 208                            backBuffer.getWidth(),
 209                            backBuffer.getHeight());
 210             } finally {
 211                 g.dispose();
 212             }
 213         }
 214     }
 215 
 216     private static class D3DBufferCaps extends BufferCapabilities {
 217         public D3DBufferCaps() {
 218             // REMIND: should we indicate that the front-buffer
 219             // (the on-screen rendering) is not accelerated?
 220             super(imageCaps, imageCaps, FlipContents.UNDEFINED);
 221         }
 222         @Override
 223         public boolean isMultiBufferAvailable() {
 224             return true;
 225         }
 226 
 227     }
 228 
 229     @Override
 230     public BufferCapabilities getBufferCapabilities() {
 231         if (bufferCaps == null) {
 232             bufferCaps = new D3DBufferCaps();
 233         }
 234         return bufferCaps;
 235     }
 236 
 237     private static class D3DImageCaps extends ImageCapabilities {
 238         private D3DImageCaps() {
 239             super(true);
 240         }
 241         @Override
 242         public boolean isTrueVolatile() {
 243             return true;
 244         }
 245     }
 246 
 247     @Override
 248     public ImageCapabilities getImageCapabilities() {
 249         return imageCaps;
 250     }
 251 
 252     D3DGraphicsDevice getD3DDevice() {
 253         return device;
 254     }
 255 
 256     /**
 257      * {@inheritDoc}
 258      *
 259      * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
 260      */
 261     @Override
 262     public D3DContext getContext() {
 263         return device.getContext();
 264     }
 265 
 266     /**
 267      * {@inheritDoc}
 268      *
 269      * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
 270      */
 271     @Override
 272     public VolatileImage
 273         createCompatibleVolatileImage(int width, int height,
 274                                       int transparency, int type)
 275     {
 276         if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
 277             transparency == Transparency.BITMASK)
 278         {
 279             return null;
 280         }
 281         boolean isOpaque = transparency == Transparency.OPAQUE;
 282         if (type == RT_TEXTURE) {
 283             int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
 284             if (!device.isCapPresent(cap)) {
 285                 return null;
 286             }
 287         } else if (type == RT_PLAIN) {
 288             if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
 289                 return null;
 290             }
 291         }
 292 
 293         SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
 294                                                           transparency, type);
 295         Surface sd = vi.getDestSurface();
 296         if (!(sd instanceof AccelSurface) ||
 297             ((AccelSurface)sd).getType() != type)
 298         {
 299             vi.flush();
 300             vi = null;
 301         }
 302 
 303         return vi;
 304     }
 305 
 306     /**
 307      * {@inheritDoc}
 308      *
 309      * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
 310      */
 311     @Override
 312     public ContextCapabilities getContextCapabilities() {
 313         return device.getContextCapabilities();
 314     }
 315 }