< prev index next >

src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java

Print this page

        

@@ -498,24 +498,80 @@
 }
 
 class D3DSurfaceToSwBlit extends Blit {
 
     private int typeval;
+    private WeakReference<SurfaceData> srcTmp;
 
-    // REMIND: destination will actually be opaque/premultiplied...
+    // destination will actually be ArgbPre or Argb
     D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) {
         super(D3DSurfaceData.D3DSurface,
               CompositeType.SrcNoEa,
               dstType);
         this.typeval = typeval;
     }
 
+    private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
+                                              Composite comp, Region clip,
+                                              int sx, int sy, int dx, int dy,
+                                              int w, int h) {
+        SurfaceData cachedSrc = null;
+        if (srcTmp != null) {
+            // use cached intermediate surface, if available
+            cachedSrc = srcTmp.get();
+        }
+
+        // We can convert argb_pre data from D3d surface in two places:
+        // - During D3d surface -> SW blit
+        // - During SW -> SW blit
+        // The first one is faster when we use opaque D3d surface, because in
+        // this case we simply skip conversion and use color components as is.
+        // Because of this we align intermediate buffer type with type of
+        // destination not source.
+        final int type = typeval == D3DSurfaceData.ST_INT_ARGB_PRE ?
+                         BufferedImage.TYPE_INT_ARGB_PRE :
+                         BufferedImage.TYPE_INT_ARGB;
+
+        src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
+
+        // copy intermediate SW to destination SW using complex clip
+        final Blit performop = Blit.getFromCache(src.getSurfaceType(),
+                                                 CompositeType.SrcNoEa,
+                                                 dst.getSurfaceType());
+        performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
+
+        if (src != cachedSrc) {
+            // cache the intermediate surface
+            srcTmp = new WeakReference<>(src);
+        }
+    }
+
     public void Blit(SurfaceData src, SurfaceData dst,
                      Composite comp, Region clip,
                      int sx, int sy, int dx, int dy,
                      int w, int h)
     {
+        if (clip != null) {
+            clip = clip.getIntersectionXYWH(dx, dy, w, h);
+            // At the end this method will flush the RenderQueue, we should exit
+            // from it as soon as possible.
+            if (clip.isEmpty()) {
+                return;
+            }
+            sx += clip.getLoX() - dx;
+            sy += clip.getLoY() - dy;
+            dx = clip.getLoX();
+            dy = clip.getLoY();
+            w = clip.getWidth();
+            h = clip.getHeight();
+
+            if (!clip.isRectangular()) {
+                complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
+                return;
+            }
+        }
+
         D3DRenderQueue rq = D3DRenderQueue.getInstance();
         rq.lock();
         try {
             // make sure the RenderQueue keeps a hard reference to the
             // destination (sysmem) SurfaceData to prevent it from being
< prev index next >