jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
changeset 25859 3317bb8137f4
parent 22567 5816a47fa4dd
child 30948 0a0972d3b58d
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 2007, 2014, 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.AlphaComposite;
       
    29 import java.awt.BufferCapabilities;
       
    30 import java.awt.Component;
       
    31 import java.awt.GraphicsConfiguration;
       
    32 import java.awt.GraphicsDevice;
       
    33 import java.awt.GraphicsEnvironment;
       
    34 import java.awt.Image;
       
    35 import java.awt.Rectangle;
       
    36 import java.awt.Transparency;
       
    37 import java.awt.image.ColorModel;
       
    38 import java.awt.image.DataBuffer;
       
    39 import java.awt.image.DirectColorModel;
       
    40 import java.awt.image.Raster;
       
    41 import java.awt.image.SampleModel;
       
    42 import java.awt.image.SinglePixelPackedSampleModel;
       
    43 import sun.awt.SunHints;
       
    44 import sun.awt.image.DataBufferNative;
       
    45 import sun.awt.image.PixelConverter;
       
    46 import sun.awt.image.SurfaceManager;
       
    47 import sun.awt.image.WritableRasterNative;
       
    48 import sun.awt.windows.WComponentPeer;
       
    49 import sun.java2d.pipe.hw.AccelSurface;
       
    50 import sun.java2d.InvalidPipeException;
       
    51 import sun.java2d.SunGraphics2D;
       
    52 import sun.java2d.SurfaceData;
       
    53 import sun.java2d.loops.GraphicsPrimitive;
       
    54 import sun.java2d.loops.MaskFill;
       
    55 import sun.java2d.loops.SurfaceType;
       
    56 import sun.java2d.loops.CompositeType;
       
    57 import sun.java2d.pipe.ParallelogramPipe;
       
    58 import sun.java2d.pipe.PixelToParallelogramConverter;
       
    59 import sun.java2d.pipe.RenderBuffer;
       
    60 import sun.java2d.pipe.TextPipe;
       
    61 import static sun.java2d.pipe.BufferedOpCodes.*;
       
    62 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
       
    63 import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
       
    64 import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
       
    65 import java.awt.BufferCapabilities.FlipContents;
       
    66 import java.awt.Window;
       
    67 import sun.awt.SunToolkit;
       
    68 import sun.awt.image.SunVolatileImage;
       
    69 import sun.java2d.ScreenUpdateManager;
       
    70 import sun.java2d.StateTracker;
       
    71 import sun.java2d.SurfaceDataProxy;
       
    72 import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
       
    73 
       
    74 /**
       
    75  * This class describes a D3D "surface", that is, a region of pixels
       
    76  * managed via D3D.  An D3DSurfaceData can be tagged with one of three
       
    77  * different SurfaceType objects for the purpose of registering loops, etc.
       
    78  * This diagram shows the hierarchy of D3D SurfaceTypes:
       
    79  *
       
    80  *                               Any
       
    81  *                             /     \
       
    82  *                    D3DSurface     D3DTexture
       
    83  *                         |
       
    84  *                   D3DSurfaceRTT
       
    85  *
       
    86  * D3DSurface
       
    87  * This kind of surface can be rendered to using D3D APIs.  It is also
       
    88  * possible to copy a D3DSurface to another D3DSurface (or to itself).
       
    89  *
       
    90  * D3DTexture
       
    91  * This kind of surface cannot be rendered to using D3D (in the same sense
       
    92  * as in D3DSurface).  However, it is possible to upload a region of pixels
       
    93  * to a D3DTexture object via Lock/UnlockRect().  One can also copy a
       
    94  * surface of type D3DTexture to a D3DSurface by binding the texture
       
    95  * to a quad and then rendering it to the destination surface (this process
       
    96  * is known as "texture mapping").
       
    97  *
       
    98  * D3DSurfaceRTT
       
    99  * This kind of surface can be thought of as a sort of hybrid between
       
   100  * D3DSurface and D3DTexture, in that one can render to this kind of
       
   101  * surface as if it were of type D3DSurface, but the process of copying
       
   102  * this kind of surface to another is more like a D3DTexture.  (Note that
       
   103  * "RTT" stands for "render-to-texture".)
       
   104  *
       
   105  * In addition to these SurfaceType variants, we have also defined some
       
   106  * constants that describe in more detail the type of underlying D3D
       
   107  * surface.  This table helps explain the relationships between those
       
   108  * "type" constants and their corresponding SurfaceType:
       
   109  *
       
   110  * D3D Type          Corresponding SurfaceType
       
   111  * --------          -------------------------
       
   112  * RT_PLAIN          D3DSurface
       
   113  * TEXTURE           D3DTexture
       
   114  * FLIP_BACKBUFFER   D3DSurface
       
   115  * RT_TEXTURE        D3DSurfaceRTT
       
   116  */
       
   117 public class D3DSurfaceData extends SurfaceData implements AccelSurface {
       
   118 
       
   119     /**
       
   120      * To be used with getNativeResource() only.
       
   121      * @see #getNativeResource()
       
   122      */
       
   123     public static final int D3D_DEVICE_RESOURCE= 100;
       
   124     /*
       
   125      * Surface types.
       
   126      * We use these surface types when copying from a sw surface
       
   127      * to a surface or texture.
       
   128      */
       
   129     public static final int ST_INT_ARGB        = 0;
       
   130     public static final int ST_INT_ARGB_PRE    = 1;
       
   131     public static final int ST_INT_ARGB_BM     = 2;
       
   132     public static final int ST_INT_RGB         = 3;
       
   133     public static final int ST_INT_BGR         = 4;
       
   134     public static final int ST_USHORT_565_RGB  = 5;
       
   135     public static final int ST_USHORT_555_RGB  = 6;
       
   136     public static final int ST_BYTE_INDEXED    = 7;
       
   137     public static final int ST_BYTE_INDEXED_BM = 8;
       
   138     public static final int ST_3BYTE_BGR       = 9;
       
   139 
       
   140     /** Equals to D3DSWAPEFFECT_DISCARD */
       
   141     public static final int SWAP_DISCARD       = 1;
       
   142     /** Equals to D3DSWAPEFFECT_FLIP    */
       
   143     public static final int SWAP_FLIP          = 2;
       
   144     /** Equals to D3DSWAPEFFECT_COPY    */
       
   145     public static final int SWAP_COPY          = 3;
       
   146     /*
       
   147      * SurfaceTypes
       
   148      */
       
   149     private static final String DESC_D3D_SURFACE = "D3D Surface";
       
   150     private static final String DESC_D3D_SURFACE_RTT =
       
   151         "D3D Surface (render-to-texture)";
       
   152     private static final String DESC_D3D_TEXTURE = "D3D Texture";
       
   153 
       
   154     // REMIND: regarding ArgbPre??
       
   155     static final SurfaceType D3DSurface =
       
   156         SurfaceType.Any.deriveSubType(DESC_D3D_SURFACE,
       
   157                                       PixelConverter.ArgbPre.instance);
       
   158     static final SurfaceType D3DSurfaceRTT =
       
   159         D3DSurface.deriveSubType(DESC_D3D_SURFACE_RTT);
       
   160     static final SurfaceType D3DTexture =
       
   161         SurfaceType.Any.deriveSubType(DESC_D3D_TEXTURE);
       
   162 
       
   163     private int type;
       
   164     private int width, height;
       
   165     // these fields are set from the native code when the surface is
       
   166     // initialized
       
   167     private int nativeWidth, nativeHeight;
       
   168     protected WComponentPeer peer;
       
   169     private Image offscreenImage;
       
   170     protected D3DGraphicsDevice graphicsDevice;
       
   171 
       
   172     private int swapEffect;
       
   173     private VSyncType syncType;
       
   174     private int backBuffersNum;
       
   175 
       
   176     private WritableRasterNative wrn;
       
   177 
       
   178     protected static D3DRenderer d3dRenderPipe;
       
   179     protected static PixelToParallelogramConverter d3dTxRenderPipe;
       
   180     protected static ParallelogramPipe d3dAAPgramPipe;
       
   181     protected static D3DTextRenderer d3dTextPipe;
       
   182     protected static D3DDrawImage d3dImagePipe;
       
   183 
       
   184     private native boolean initTexture(long pData, boolean isRTT,
       
   185                                        boolean isOpaque);
       
   186     private native boolean initFlipBackbuffer(long pData, long pPeerData,
       
   187                                               int numbuffers,
       
   188                                               int swapEffect, int syncType);
       
   189     private native boolean initRTSurface(long pData, boolean isOpaque);
       
   190     private native void initOps(int screen, int width, int height);
       
   191 
       
   192     static {
       
   193         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   194         d3dImagePipe = new D3DDrawImage();
       
   195         d3dTextPipe = new D3DTextRenderer(rq);
       
   196         d3dRenderPipe = new D3DRenderer(rq);
       
   197         if (GraphicsPrimitive.tracingEnabled()) {
       
   198             d3dTextPipe = d3dTextPipe.traceWrap();
       
   199             d3dRenderPipe = d3dRenderPipe.traceWrap();
       
   200             //The wrapped d3dRenderPipe will wrap the AA pipe as well...
       
   201             //d3dAAPgramPipe = d3dRenderPipe.traceWrap();
       
   202         }
       
   203         d3dAAPgramPipe = d3dRenderPipe.getAAParallelogramPipe();
       
   204         d3dTxRenderPipe =
       
   205             new PixelToParallelogramConverter(d3dRenderPipe, d3dRenderPipe,
       
   206                                               1.0, 0.25, true);
       
   207 
       
   208         D3DBlitLoops.register();
       
   209         D3DMaskFill.register();
       
   210         D3DMaskBlit.register();
       
   211     }
       
   212 
       
   213     protected D3DSurfaceData(WComponentPeer peer, D3DGraphicsConfig gc,
       
   214                              int width, int height, Image image,
       
   215                              ColorModel cm, int numBackBuffers,
       
   216                              int swapEffect, VSyncType vSyncType,
       
   217                              int type)
       
   218     {
       
   219         super(getCustomSurfaceType(type), cm);
       
   220         this.graphicsDevice = gc.getD3DDevice();
       
   221         this.peer = peer;
       
   222         this.type = type;
       
   223         this.width = width;
       
   224         this.height = height;
       
   225         this.offscreenImage = image;
       
   226         this.backBuffersNum = numBackBuffers;
       
   227         this.swapEffect = swapEffect;
       
   228         this.syncType = vSyncType;
       
   229 
       
   230         initOps(graphicsDevice.getScreen(), width, height);
       
   231         if (type == WINDOW) {
       
   232             // we put the surface into the "lost"
       
   233             // state; it will be restored by the D3DScreenUpdateManager
       
   234             // prior to rendering to it for the first time. This is done
       
   235             // so that vram is not wasted for surfaces never rendered to
       
   236             setSurfaceLost(true);
       
   237         } else {
       
   238             initSurface();
       
   239         }
       
   240         setBlitProxyKey(gc.getProxyKey());
       
   241     }
       
   242 
       
   243     @Override
       
   244     public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
       
   245         return D3DSurfaceDataProxy.
       
   246             createProxy(srcData,
       
   247                         (D3DGraphicsConfig)graphicsDevice.getDefaultConfiguration());
       
   248     }
       
   249 
       
   250     /**
       
   251      * Creates a SurfaceData object representing the back buffer of a
       
   252      * double-buffered on-screen Window.
       
   253      */
       
   254     public static D3DSurfaceData createData(WComponentPeer peer, Image image) {
       
   255         D3DGraphicsConfig gc = getGC(peer);
       
   256         if (gc == null || !peer.isAccelCapable()) {
       
   257             return null;
       
   258         }
       
   259         BufferCapabilities caps = peer.getBackBufferCaps();
       
   260         VSyncType vSyncType = VSYNC_DEFAULT;
       
   261         if (caps instanceof ExtendedBufferCapabilities) {
       
   262             vSyncType = ((ExtendedBufferCapabilities)caps).getVSync();
       
   263         }
       
   264         Rectangle r = peer.getBounds();
       
   265         BufferCapabilities.FlipContents flip = caps.getFlipContents();
       
   266         int swapEffect;
       
   267         if (flip == FlipContents.COPIED) {
       
   268             swapEffect = SWAP_COPY;
       
   269         } else if (flip == FlipContents.PRIOR) {
       
   270             swapEffect = SWAP_FLIP;
       
   271         } else { // flip == FlipContents.UNDEFINED || .BACKGROUND
       
   272             swapEffect = SWAP_DISCARD;
       
   273         }
       
   274         return new D3DSurfaceData(peer, gc, r.width, r.height,
       
   275                                   image, peer.getColorModel(),
       
   276                                   peer.getBackBuffersNum(),
       
   277                                   swapEffect, vSyncType, FLIP_BACKBUFFER);
       
   278     }
       
   279 
       
   280     /**
       
   281      * Returns a WINDOW type of surface - a
       
   282      * swap chain which serves as an on-screen surface,
       
   283      * handled by the D3DScreenUpdateManager.
       
   284      *
       
   285      * Note that the native surface is not initialized
       
   286      * when the surface is created to avoid using excessive
       
   287      * resources, and the surface is placed into the lost
       
   288      * state. It will be restored prior to any rendering
       
   289      * to it.
       
   290      *
       
   291      * @param peer peer for which the onscreen surface is to be created
       
   292      * @return a D3DWindowSurfaceData (flip chain) surface
       
   293      */
       
   294     public static D3DSurfaceData createData(WComponentPeer peer) {
       
   295         D3DGraphicsConfig gc = getGC(peer);
       
   296         if (gc == null || !peer.isAccelCapable()) {
       
   297             return null;
       
   298         }
       
   299         return new D3DWindowSurfaceData(peer, gc);
       
   300     }
       
   301 
       
   302     /**
       
   303      * Creates a SurfaceData object representing an off-screen buffer (either
       
   304      * a plain surface or Texture).
       
   305      */
       
   306     public static D3DSurfaceData createData(D3DGraphicsConfig gc,
       
   307                                             int width, int height,
       
   308                                             ColorModel cm,
       
   309                                             Image image, int type)
       
   310     {
       
   311         if (type == RT_TEXTURE) {
       
   312             boolean isOpaque = cm.getTransparency() == Transparency.OPAQUE;
       
   313             int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
       
   314             if (!gc.getD3DDevice().isCapPresent(cap)) {
       
   315                 type = RT_PLAIN;
       
   316             }
       
   317         }
       
   318         D3DSurfaceData ret = null;
       
   319         try {
       
   320             ret = new D3DSurfaceData(null, gc, width, height,
       
   321                                      image, cm, 0, SWAP_DISCARD, VSYNC_DEFAULT,
       
   322                                      type);
       
   323         } catch (InvalidPipeException ipe) {
       
   324             // try again - we might have ran out of vram, and rt textures
       
   325             // could take up more than a plain surface, so it might succeed
       
   326             if (type == RT_TEXTURE) {
       
   327                 // If a RT_TEXTURE was requested do not attempt to create a
       
   328                 // plain surface. (note that RT_TEXTURE can only be requested
       
   329                 // from a VI so the cast is safe)
       
   330                 if (((SunVolatileImage)image).getForcedAccelSurfaceType() !=
       
   331                     RT_TEXTURE)
       
   332                 {
       
   333                     type = RT_PLAIN;
       
   334                     ret = new D3DSurfaceData(null, gc, width, height,
       
   335                                              image, cm, 0, SWAP_DISCARD,
       
   336                                              VSYNC_DEFAULT, type);
       
   337                 }
       
   338             }
       
   339         }
       
   340         return ret;
       
   341     }
       
   342 
       
   343     /**
       
   344      * Returns the appropriate SurfaceType corresponding to the given D3D
       
   345      * surface type constant (e.g. TEXTURE -> D3DTexture).
       
   346      */
       
   347     private static SurfaceType getCustomSurfaceType(int d3dType) {
       
   348         switch (d3dType) {
       
   349         case TEXTURE:
       
   350             return D3DTexture;
       
   351         case RT_TEXTURE:
       
   352             return D3DSurfaceRTT;
       
   353         default:
       
   354             return D3DSurface;
       
   355         }
       
   356     }
       
   357 
       
   358     private boolean initSurfaceNow() {
       
   359         boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
       
   360         switch (type) {
       
   361             case RT_PLAIN:
       
   362                 return initRTSurface(getNativeOps(), isOpaque);
       
   363             case TEXTURE:
       
   364                 return initTexture(getNativeOps(), false/*isRTT*/, isOpaque);
       
   365             case RT_TEXTURE:
       
   366                 return initTexture(getNativeOps(), true/*isRTT*/,  isOpaque);
       
   367             // REMIND: we may want to pass the exact type to the native
       
   368             // level here so that we could choose the right presentation
       
   369             // interval for the frontbuffer (immediate vs v-synced)
       
   370             case WINDOW:
       
   371             case FLIP_BACKBUFFER:
       
   372                 return initFlipBackbuffer(getNativeOps(), peer.getData(),
       
   373                                           backBuffersNum, swapEffect,
       
   374                                           syncType.id());
       
   375             default:
       
   376                 return false;
       
   377         }
       
   378     }
       
   379 
       
   380     /**
       
   381      * Initializes the appropriate D3D offscreen surface based on the value
       
   382      * of the type parameter.  If the surface creation fails for any reason,
       
   383      * an OutOfMemoryError will be thrown.
       
   384      */
       
   385     protected void initSurface() {
       
   386         // any time we create or restore the surface, recreate the raster
       
   387         synchronized (this) {
       
   388             wrn = null;
       
   389         }
       
   390         // REMIND: somewhere a puppy died
       
   391         class Status {
       
   392             boolean success = false;
       
   393         };
       
   394         final Status status = new Status();
       
   395         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   396         rq.lock();
       
   397         try {
       
   398             rq.flushAndInvokeNow(new Runnable() {
       
   399                 public void run() {
       
   400                     status.success = initSurfaceNow();
       
   401                 }
       
   402             });
       
   403             if (!status.success) {
       
   404                 throw new InvalidPipeException("Error creating D3DSurface");
       
   405             }
       
   406         } finally {
       
   407             rq.unlock();
       
   408         }
       
   409     }
       
   410 
       
   411     /**
       
   412      * Returns the D3DContext for the GraphicsConfig associated with this
       
   413      * surface.
       
   414      */
       
   415     public final D3DContext getContext() {
       
   416         return graphicsDevice.getContext();
       
   417     }
       
   418 
       
   419     /**
       
   420      * Returns one of the surface type constants defined above.
       
   421      */
       
   422     public final int getType() {
       
   423         return type;
       
   424     }
       
   425 
       
   426     private static native int  dbGetPixelNative(long pData, int x, int y);
       
   427     private static native void dbSetPixelNative(long pData, int x, int y,
       
   428                                                 int pixel);
       
   429     static class D3DDataBufferNative extends DataBufferNative {
       
   430         int pixel;
       
   431         protected D3DDataBufferNative(SurfaceData sData,
       
   432                                       int type, int w, int h)
       
   433         {
       
   434             super(sData, type, w, h);
       
   435         }
       
   436 
       
   437         protected int getElem(final int x, final int y,
       
   438                               final SurfaceData sData)
       
   439         {
       
   440             if (sData.isSurfaceLost()) {
       
   441                 return 0;
       
   442             }
       
   443 
       
   444             int retPixel;
       
   445             D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   446             rq.lock();
       
   447             try {
       
   448                 rq.flushAndInvokeNow(new Runnable() {
       
   449                     public void run() {
       
   450                         pixel = dbGetPixelNative(sData.getNativeOps(), x, y);
       
   451                     }
       
   452                 });
       
   453             } finally {
       
   454                 retPixel = pixel;
       
   455                 rq.unlock();
       
   456             }
       
   457             return retPixel;
       
   458         }
       
   459 
       
   460         protected void setElem(final int x, final int y, final int pixel,
       
   461                                final SurfaceData sData)
       
   462         {
       
   463             if (sData.isSurfaceLost()) {
       
   464                   return;
       
   465             }
       
   466 
       
   467             D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   468             rq.lock();
       
   469             try {
       
   470                 rq.flushAndInvokeNow(new Runnable() {
       
   471                     public void run() {
       
   472                         dbSetPixelNative(sData.getNativeOps(), x, y, pixel);
       
   473                     }
       
   474                 });
       
   475                 sData.markDirty();
       
   476             } finally {
       
   477                 rq.unlock();
       
   478             }
       
   479         }
       
   480     }
       
   481 
       
   482     public synchronized Raster getRaster(int x, int y, int w, int h) {
       
   483         if (wrn == null) {
       
   484             DirectColorModel dcm = (DirectColorModel)getColorModel();
       
   485             SampleModel smHw;
       
   486             int dataType = 0;
       
   487             int scanStride = width;
       
   488 
       
   489             if (dcm.getPixelSize() > 16) {
       
   490                 dataType = DataBuffer.TYPE_INT;
       
   491             } else {
       
   492                 // 15, 16
       
   493                 dataType = DataBuffer.TYPE_USHORT;
       
   494             }
       
   495 
       
   496             // note that we have to use the surface width and height here,
       
   497             // not the passed w,h
       
   498             smHw = new SinglePixelPackedSampleModel(dataType, width, height,
       
   499                                                     scanStride, dcm.getMasks());
       
   500             DataBuffer dbn = new D3DDataBufferNative(this, dataType,
       
   501                                                      width, height);
       
   502             wrn = WritableRasterNative.createNativeRaster(smHw, dbn);
       
   503         }
       
   504 
       
   505         return wrn;
       
   506     }
       
   507 
       
   508     /**
       
   509      * For now, we can only render LCD text if:
       
   510      *   - the pixel shaders are available, and
       
   511      *   - blending is disabled, and
       
   512      *   - the source color is opaque
       
   513      *   - and the destination is opaque
       
   514      */
       
   515     public boolean canRenderLCDText(SunGraphics2D sg2d) {
       
   516         return
       
   517             graphicsDevice.isCapPresent(CAPS_LCD_SHADER) &&
       
   518             sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
       
   519             sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR   &&
       
   520             sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
       
   521     }
       
   522 
       
   523     /**
       
   524      * If acceleration should no longer be used for this surface.
       
   525      * This implementation flags to the manager that it should no
       
   526      * longer attempt to re-create a D3DSurface.
       
   527      */
       
   528     void disableAccelerationForSurface() {
       
   529         if (offscreenImage != null) {
       
   530             SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
       
   531             if (sm instanceof D3DVolatileSurfaceManager) {
       
   532                 setSurfaceLost(true);
       
   533                 ((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false);
       
   534             }
       
   535         }
       
   536     }
       
   537 
       
   538     public void validatePipe(SunGraphics2D sg2d) {
       
   539         TextPipe textpipe;
       
   540         boolean validated = false;
       
   541 
       
   542         // REMIND: the D3D pipeline doesn't support XOR!, more
       
   543         // fixes will be needed below. For now we disable D3D rendering
       
   544         // for the surface which had any XOR rendering done to.
       
   545         if (sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
       
   546             super.validatePipe(sg2d);
       
   547             sg2d.imagepipe = d3dImagePipe;
       
   548             disableAccelerationForSurface();
       
   549             return;
       
   550         }
       
   551 
       
   552         // D3DTextRenderer handles both AA and non-AA text, but
       
   553         // only works with the following modes:
       
   554         // (Note: For LCD text we only enter this code path if
       
   555         // canRenderLCDText() has already validated that the mode is
       
   556         // CompositeType.SrcNoEa (opaque color), which will be subsumed
       
   557         // by the CompositeType.SrcNoEa (any color) test below.)
       
   558 
       
   559         if (/* CompositeType.SrcNoEa (any color) */
       
   560             (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
       
   561              sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR)        ||
       
   562 
       
   563             /* CompositeType.SrcOver (any color) */
       
   564             (sg2d.compositeState == SunGraphics2D.COMP_ALPHA    &&
       
   565              sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
       
   566              (((AlphaComposite)sg2d.composite).getRule() ==
       
   567               AlphaComposite.SRC_OVER))                       ||
       
   568 
       
   569             /* CompositeType.Xor (any color) */
       
   570             (sg2d.compositeState == SunGraphics2D.COMP_XOR &&
       
   571              sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR))
       
   572         {
       
   573             textpipe = d3dTextPipe;
       
   574         } else {
       
   575             // do this to initialize textpipe correctly; we will attempt
       
   576             // to override the non-text pipes below
       
   577             super.validatePipe(sg2d);
       
   578             textpipe = sg2d.textpipe;
       
   579             validated = true;
       
   580         }
       
   581 
       
   582         PixelToParallelogramConverter txPipe = null;
       
   583         D3DRenderer nonTxPipe = null;
       
   584 
       
   585         if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
       
   586             if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
       
   587                 if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
       
   588                     txPipe = d3dTxRenderPipe;
       
   589                     nonTxPipe = d3dRenderPipe;
       
   590                 }
       
   591             } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
       
   592                 if (D3DPaints.isValid(sg2d)) {
       
   593                     txPipe = d3dTxRenderPipe;
       
   594                     nonTxPipe = d3dRenderPipe;
       
   595                 }
       
   596                 // custom paints handled by super.validatePipe() below
       
   597             }
       
   598         } else {
       
   599             if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
       
   600                 if (graphicsDevice.isCapPresent(CAPS_AA_SHADER) &&
       
   601                     (sg2d.imageComp == CompositeType.SrcOverNoEa ||
       
   602                      sg2d.imageComp == CompositeType.SrcOver))
       
   603                 {
       
   604                     if (!validated) {
       
   605                         super.validatePipe(sg2d);
       
   606                         validated = true;
       
   607                     }
       
   608                     PixelToParallelogramConverter aaConverter =
       
   609                         new PixelToParallelogramConverter(sg2d.shapepipe,
       
   610                                                           d3dAAPgramPipe,
       
   611                                                           1.0/8.0, 0.499,
       
   612                                                           false);
       
   613                     sg2d.drawpipe = aaConverter;
       
   614                     sg2d.fillpipe = aaConverter;
       
   615                     sg2d.shapepipe = aaConverter;
       
   616                 } else if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
       
   617                     // install the solid pipes when AA and XOR are both enabled
       
   618                     txPipe = d3dTxRenderPipe;
       
   619                     nonTxPipe = d3dRenderPipe;
       
   620                 }
       
   621             }
       
   622             // other cases handled by super.validatePipe() below
       
   623         }
       
   624 
       
   625         if (txPipe != null) {
       
   626             if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
       
   627                 sg2d.drawpipe = txPipe;
       
   628                 sg2d.fillpipe = txPipe;
       
   629             } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
       
   630                 sg2d.drawpipe = txPipe;
       
   631                 sg2d.fillpipe = nonTxPipe;
       
   632             } else {
       
   633                 sg2d.drawpipe = nonTxPipe;
       
   634                 sg2d.fillpipe = nonTxPipe;
       
   635             }
       
   636             // Note that we use the transforming pipe here because it
       
   637             // will examine the shape and possibly perform an optimized
       
   638             // operation if it can be simplified.  The simplifications
       
   639             // will be valid for all STROKE and TRANSFORM types.
       
   640             sg2d.shapepipe = txPipe;
       
   641         } else {
       
   642             if (!validated) {
       
   643                 super.validatePipe(sg2d);
       
   644             }
       
   645         }
       
   646 
       
   647         // install the text pipe based on our earlier decision
       
   648         sg2d.textpipe = textpipe;
       
   649 
       
   650         // always override the image pipe with the specialized D3D pipe
       
   651         sg2d.imagepipe = d3dImagePipe;
       
   652     }
       
   653 
       
   654     @Override
       
   655     protected MaskFill getMaskFill(SunGraphics2D sg2d) {
       
   656         if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
       
   657             /*
       
   658              * We can only accelerate non-Color MaskFill operations if
       
   659              * all of the following conditions hold true:
       
   660              *   - there is an implementation for the given paintState
       
   661              *   - the current Paint can be accelerated for this destination
       
   662              *   - multitexturing is available (since we need to modulate
       
   663              *     the alpha mask texture with the paint texture)
       
   664              *
       
   665              * In all other cases, we return null, in which case the
       
   666              * validation code will choose a more general software-based loop.
       
   667              */
       
   668             if (!D3DPaints.isValid(sg2d) ||
       
   669                 !graphicsDevice.isCapPresent(CAPS_MULTITEXTURE))
       
   670             {
       
   671                 return null;
       
   672             }
       
   673         }
       
   674         return super.getMaskFill(sg2d);
       
   675     }
       
   676 
       
   677     @Override
       
   678     public boolean copyArea(SunGraphics2D sg2d,
       
   679                             int x, int y, int w, int h, int dx, int dy)
       
   680     {
       
   681         if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&
       
   682             sg2d.compositeState < SunGraphics2D.COMP_XOR)
       
   683         {
       
   684             x += sg2d.transX;
       
   685             y += sg2d.transY;
       
   686 
       
   687             d3dRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
       
   688 
       
   689             return true;
       
   690         }
       
   691         return false;
       
   692     }
       
   693 
       
   694     @Override
       
   695     public void flush() {
       
   696         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   697         rq.lock();
       
   698         try {
       
   699             RenderBuffer buf = rq.getBuffer();
       
   700             rq.ensureCapacityAndAlignment(12, 4);
       
   701             buf.putInt(FLUSH_SURFACE);
       
   702             buf.putLong(getNativeOps());
       
   703 
       
   704             // this call is expected to complete synchronously, so flush now
       
   705             rq.flushNow();
       
   706         } finally {
       
   707             rq.unlock();
       
   708         }
       
   709     }
       
   710 
       
   711     /**
       
   712      * Disposes the native resources associated with the given D3DSurfaceData
       
   713      * (referenced by the pData parameter).  This method is invoked from
       
   714      * the native Dispose() method from the Disposer thread when the
       
   715      * Java-level D3DSurfaceData object is about to go away.
       
   716      */
       
   717     static void dispose(long pData) {
       
   718         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   719         rq.lock();
       
   720         try {
       
   721             RenderBuffer buf = rq.getBuffer();
       
   722             rq.ensureCapacityAndAlignment(12, 4);
       
   723             buf.putInt(DISPOSE_SURFACE);
       
   724             buf.putLong(pData);
       
   725 
       
   726             // this call is expected to complete synchronously, so flush now
       
   727             rq.flushNow();
       
   728         } finally {
       
   729             rq.unlock();
       
   730         }
       
   731     }
       
   732 
       
   733     static void swapBuffers(D3DSurfaceData sd,
       
   734                             final int x1, final int y1,
       
   735                             final int x2, final int y2)
       
   736     {
       
   737         long pData = sd.getNativeOps();
       
   738         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   739         // swapBuffers can be called from the toolkit thread by swing, we
       
   740         // should detect this and prevent the deadlocks
       
   741         if (D3DRenderQueue.isRenderQueueThread()) {
       
   742             if (!rq.tryLock()) {
       
   743                 // if we could not obtain the lock, repaint the area
       
   744                 // that was supposed to be swapped, and no-op this swap
       
   745                 final Component target = (Component)sd.getPeer().getTarget();
       
   746                 SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
       
   747                     public void run() {
       
   748                         target.repaint(x1, y1, x2, y2);
       
   749                     }
       
   750                 });
       
   751                 return;
       
   752             }
       
   753         } else {
       
   754             rq.lock();
       
   755         }
       
   756         try {
       
   757             RenderBuffer buf = rq.getBuffer();
       
   758             rq.ensureCapacityAndAlignment(28, 4);
       
   759             buf.putInt(SWAP_BUFFERS);
       
   760             buf.putLong(pData);
       
   761             buf.putInt(x1);
       
   762             buf.putInt(y1);
       
   763             buf.putInt(x2);
       
   764             buf.putInt(y2);
       
   765             rq.flushNow();
       
   766         } finally {
       
   767             rq.unlock();
       
   768         }
       
   769     }
       
   770 
       
   771     /**
       
   772      * Returns destination Image associated with this SurfaceData.
       
   773      */
       
   774     public Object getDestination() {
       
   775         return offscreenImage;
       
   776     }
       
   777 
       
   778     public Rectangle getBounds() {
       
   779         if (type == FLIP_BACKBUFFER || type == WINDOW) {
       
   780             Rectangle r = peer.getBounds();
       
   781             r.x = r.y = 0;
       
   782             return r;
       
   783         } else {
       
   784             return new Rectangle(width, height);
       
   785         }
       
   786     }
       
   787 
       
   788     public Rectangle getNativeBounds() {
       
   789         D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   790         // need to lock to make sure nativeWidth and Height are consistent
       
   791         // since they are set from the render thread from the native
       
   792         // level
       
   793         rq.lock();
       
   794         try {
       
   795             // REMIND: use xyoffsets?
       
   796             return new Rectangle(nativeWidth, nativeHeight);
       
   797         } finally {
       
   798             rq.unlock();
       
   799         }
       
   800     }
       
   801 
       
   802 
       
   803     public GraphicsConfiguration getDeviceConfiguration() {
       
   804         return graphicsDevice.getDefaultConfiguration();
       
   805     }
       
   806 
       
   807     public SurfaceData getReplacement() {
       
   808         return restoreContents(offscreenImage);
       
   809     }
       
   810 
       
   811     private static D3DGraphicsConfig getGC(WComponentPeer peer) {
       
   812         GraphicsConfiguration gc;
       
   813         if (peer != null) {
       
   814             gc =  peer.getGraphicsConfiguration();
       
   815         } else {
       
   816             GraphicsEnvironment env =
       
   817                     GraphicsEnvironment.getLocalGraphicsEnvironment();
       
   818             GraphicsDevice gd = env.getDefaultScreenDevice();
       
   819             gc = gd.getDefaultConfiguration();
       
   820         }
       
   821         return (gc instanceof D3DGraphicsConfig) ? (D3DGraphicsConfig)gc : null;
       
   822     }
       
   823 
       
   824     /**
       
   825      * Attempts to restore the surface by initializing the native data
       
   826      */
       
   827     void restoreSurface() {
       
   828         initSurface();
       
   829     }
       
   830 
       
   831     WComponentPeer getPeer() {
       
   832         return peer;
       
   833     }
       
   834 
       
   835     /**
       
   836      * We need to let the surface manager know that the surface is lost so
       
   837      * that for example BufferStrategy.contentsLost() returns correct result.
       
   838      * Normally the status of contentsLost is set in validate(), but in some
       
   839      * cases (like Swing's buffer per window) we intentionally don't call
       
   840      * validate from the toolkit thread but only check for the BS status.
       
   841      */
       
   842     @Override
       
   843     public void setSurfaceLost(boolean lost) {
       
   844         super.setSurfaceLost(lost);
       
   845         if (lost && offscreenImage != null) {
       
   846             SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
       
   847             sm.acceleratedSurfaceLost();
       
   848         }
       
   849     }
       
   850 
       
   851     private static native long getNativeResourceNative(long sdops, int resType);
       
   852     /**
       
   853      * Returns a pointer to the native resource of specified {@code resType}
       
   854      * associated with this surface.
       
   855      *
       
   856      * Specifically, for {@code D3DSurfaceData} this method returns pointers of
       
   857      * the following:
       
   858      * <pre>
       
   859      * TEXTURE              - (IDirect3DTexture9*)
       
   860      * RT_TEXTURE, RT_PLAIN - (IDirect3DSurface9*)
       
   861      * FLIP_BACKBUFFER      - (IDirect3DSwapChain9*)
       
   862      * D3D_DEVICE_RESOURCE  - (IDirect3DDevice9*)
       
   863      * </pre>
       
   864      *
       
   865      * Multiple resources may be available for some types (i.e. for render to
       
   866      * texture one could retrieve both a destination surface by specifying
       
   867      * RT_TEXTURE, and a texture by using TEXTURE).
       
   868      *
       
   869      * Note: the pointer returned by this method is only valid on the rendering
       
   870      * thread.
       
   871      *
       
   872      * @return pointer to the native resource of specified type or 0L if
       
   873      * such resource doesn't exist or can not be retrieved.
       
   874      * @see sun.java2d.pipe.hw.AccelSurface#getNativeResource
       
   875      */
       
   876     public long getNativeResource(int resType) {
       
   877         return getNativeResourceNative(getNativeOps(), resType);
       
   878     }
       
   879 
       
   880     /**
       
   881      * Class representing an on-screen d3d surface. Since d3d can't
       
   882      * render to the screen directly, it is implemented as a swap chain,
       
   883      * controlled by D3DScreenUpdateManager.
       
   884      *
       
   885      * @see D3DScreenUpdateManager
       
   886      */
       
   887     public static class D3DWindowSurfaceData extends D3DSurfaceData {
       
   888         StateTracker dirtyTracker;
       
   889 
       
   890         public D3DWindowSurfaceData(WComponentPeer peer,
       
   891                                     D3DGraphicsConfig gc)
       
   892         {
       
   893             super(peer, gc,
       
   894                   peer.getBounds().width, peer.getBounds().height,
       
   895                   null, peer.getColorModel(), 1, SWAP_COPY, VSYNC_DEFAULT,
       
   896                   WINDOW);
       
   897             dirtyTracker = getStateTracker();
       
   898         }
       
   899 
       
   900         /**
       
   901          * {@inheritDoc}
       
   902          *
       
   903          * Overridden to use ScreenUpdateManager to obtain the replacement
       
   904          * surface.
       
   905          *
       
   906          * @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface
       
   907          */
       
   908         @Override
       
   909         public SurfaceData getReplacement() {
       
   910             ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
       
   911             return mgr.getReplacementScreenSurface(peer, this);
       
   912         }
       
   913 
       
   914         /**
       
   915          * Returns destination Component associated with this SurfaceData.
       
   916          */
       
   917         @Override
       
   918         public Object getDestination() {
       
   919             return peer.getTarget();
       
   920         }
       
   921 
       
   922         @Override
       
   923         void disableAccelerationForSurface() {
       
   924             // for on-screen surfaces we need to make sure a backup GDI surface is
       
   925             // is used until a new one is set (which may happen during a resize). We
       
   926             // don't want the screen update maanger to replace the surface right way
       
   927             // because it causes repainting issues in Swing, so we invalidate it,
       
   928             // this will prevent SUM from issuing a replaceSurfaceData call.
       
   929             setSurfaceLost(true);
       
   930             invalidate();
       
   931             flush();
       
   932             peer.disableAcceleration();
       
   933             ScreenUpdateManager.getInstance().dropScreenSurface(this);
       
   934         }
       
   935 
       
   936         @Override
       
   937         void restoreSurface() {
       
   938             if (!peer.isAccelCapable()) {
       
   939                 throw new InvalidPipeException("Onscreen acceleration " +
       
   940                                                "disabled for this surface");
       
   941             }
       
   942             Window fsw = graphicsDevice.getFullScreenWindow();
       
   943             if (fsw != null && fsw != peer.getTarget()) {
       
   944                 throw new InvalidPipeException("Can't restore onscreen surface"+
       
   945                                                " when in full-screen mode");
       
   946             }
       
   947             super.restoreSurface();
       
   948             // if initialization was unsuccessful, an IPE will be thrown
       
   949             // and the surface will remain lost
       
   950             setSurfaceLost(false);
       
   951 
       
   952             // This is to make sure the render target is reset after this
       
   953             // surface is restored. The reason for this is that sometimes this
       
   954             // surface can be restored from multiple threads (the screen update
       
   955             // manager's thread and app's rendering thread) at the same time,
       
   956             // and when that happens the second restoration will create the
       
   957             // native resource which will not be set as render target because
       
   958             // the BufferedContext's validate method will think that since the
       
   959             // surface data object didn't change then the current render target
       
   960             // is correct and no rendering will appear on the screen.
       
   961             D3DRenderQueue rq = D3DRenderQueue.getInstance();
       
   962             rq.lock();
       
   963             try {
       
   964                 getContext().invalidateContext();
       
   965             } finally {
       
   966                 rq.unlock();
       
   967             }
       
   968         }
       
   969 
       
   970         public boolean isDirty() {
       
   971             return !dirtyTracker.isCurrent();
       
   972         }
       
   973 
       
   974         public void markClean() {
       
   975             dirtyTracker = getStateTracker();
       
   976         }
       
   977     }
       
   978 
       
   979     /**
       
   980      * Updates the layered window with the contents of the surface.
       
   981      *
       
   982      * @param pd3dsd pointer to the D3DSDOps structure
       
   983      * @param pData pointer to the AwtWindow peer data
       
   984      * @param w width of the window
       
   985      * @param h height of the window
       
   986      * @see sun.awt.windows.TranslucentWindowPainter
       
   987      */
       
   988     public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
       
   989                                                        int w, int h);
       
   990 }