--- old/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java 2015-04-15 14:07:34.031841000 +0530 +++ new/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java 2015-04-15 14:07:33.443266200 +0530 @@ -500,8 +500,9 @@ class D3DSurfaceToSwBlit extends Blit { private int typeval; + private WeakReference 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, @@ -509,11 +510,66 @@ 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 {