Enable resize operation for drawing primitives by adding high level blit loops logic metal-prototype-branch
authorjdv
Tue, 05 Mar 2019 16:36:45 +0530
branchmetal-prototype-branch
changeset 57243 8c3a74033daf
parent 57234 e1e5386479c4
child 57247 48f2dc62ba77
Enable resize operation for drawing primitives by adding high level blit loops logic
src/java.desktop/macosx/classes/sun/java2d/metal/MetalBlitLoops.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalBlitLoops.java	Tue Mar 05 16:36:45 2019 +0530
@@ -0,0 +1,952 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.java2d.metal;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.lang.ref.WeakReference;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.Blit;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.loops.GraphicsPrimitiveMgr;
+import sun.java2d.loops.ScaledBlit;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.loops.TransformBlit;
+import sun.java2d.pipe.Region;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+import static sun.java2d.pipe.BufferedOpCodes.*;
+import java.lang.annotation.Native;
+
+final class MetalBlitLoops {
+
+    static void register() {
+        /*Blit blitIntArgbPreToSurface =
+                new OGLSwToSurfaceBlit(SurfaceType.IntArgbPre,
+                        OGLSurfaceData.PF_INT_ARGB_PRE);
+        Blit blitIntArgbPreToTexture =
+                new OGLSwToTextureBlit(SurfaceType.IntArgbPre,
+                        OGLSurfaceData.PF_INT_ARGB_PRE);
+        TransformBlit transformBlitIntArgbPreToSurface =
+                new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre,
+                        OGLSurfaceData.PF_INT_ARGB_PRE);
+        OGLSurfaceToSwBlit blitSurfaceToIntArgbPre =
+                new OGLSurfaceToSwBlit(SurfaceType.IntArgbPre,
+                        OGLSurfaceData.PF_INT_ARGB_PRE);*/
+
+        GraphicsPrimitive[] primitives = {
+                // surface->surface ops
+                new MetalSurfaceToSurfaceBlit(),
+                /*new OGLSurfaceToSurfaceBlit(),
+                new OGLSurfaceToSurfaceScale(),
+                new OGLSurfaceToSurfaceTransform(),
+
+                // render-to-texture surface->surface ops
+                new OGLRTTSurfaceToSurfaceBlit(),
+                new OGLRTTSurfaceToSurfaceScale(),
+                new OGLRTTSurfaceToSurfaceTransform(),
+
+                // surface->sw ops
+                new OGLSurfaceToSwBlit(SurfaceType.IntArgb,
+                        OGLSurfaceData.PF_INT_ARGB),
+                blitSurfaceToIntArgbPre,
+
+                // sw->surface ops
+                blitIntArgbPreToSurface,
+                new OGLSwToSurfaceBlit(SurfaceType.IntRgb,
+                        OGLSurfaceData.PF_INT_RGB),
+                new OGLSwToSurfaceBlit(SurfaceType.IntRgbx,
+                        OGLSurfaceData.PF_INT_RGBX),
+                new OGLSwToSurfaceBlit(SurfaceType.IntBgr,
+                        OGLSurfaceData.PF_INT_BGR),
+                new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
+                        OGLSurfaceData.PF_INT_BGRX),
+                new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+                        OGLSurfaceData.PF_3BYTE_BGR),
+                new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
+                        OGLSurfaceData.PF_USHORT_565_RGB),
+                new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
+                        OGLSurfaceData.PF_USHORT_555_RGB),
+                new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx,
+                        OGLSurfaceData.PF_USHORT_555_RGBX),
+                new OGLSwToSurfaceBlit(SurfaceType.ByteGray,
+                        OGLSurfaceData.PF_BYTE_GRAY),
+                new OGLSwToSurfaceBlit(SurfaceType.UshortGray,
+                        OGLSurfaceData.PF_USHORT_GRAY),
+                new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface,
+                        CompositeType.AnyAlpha,
+                        blitIntArgbPreToSurface),
+
+                new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface,
+                        blitSurfaceToIntArgbPre,
+                        blitSurfaceToIntArgbPre,
+                        blitIntArgbPreToSurface),
+                new OGLAnyCompositeBlit(SurfaceType.Any,
+                        null,
+                        blitSurfaceToIntArgbPre,
+                        blitIntArgbPreToSurface),
+
+                new OGLSwToSurfaceScale(SurfaceType.IntRgb,
+                        OGLSurfaceData.PF_INT_RGB),
+                new OGLSwToSurfaceScale(SurfaceType.IntRgbx,
+                        OGLSurfaceData.PF_INT_RGBX),
+                new OGLSwToSurfaceScale(SurfaceType.IntBgr,
+                        OGLSurfaceData.PF_INT_BGR),
+                new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
+                        OGLSurfaceData.PF_INT_BGRX),
+                new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+                        OGLSurfaceData.PF_3BYTE_BGR),
+                new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
+                        OGLSurfaceData.PF_USHORT_565_RGB),
+                new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
+                        OGLSurfaceData.PF_USHORT_555_RGB),
+                new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx,
+                        OGLSurfaceData.PF_USHORT_555_RGBX),
+                new OGLSwToSurfaceScale(SurfaceType.ByteGray,
+                        OGLSurfaceData.PF_BYTE_GRAY),
+                new OGLSwToSurfaceScale(SurfaceType.UshortGray,
+                        OGLSurfaceData.PF_USHORT_GRAY),
+                new OGLSwToSurfaceScale(SurfaceType.IntArgbPre,
+                        OGLSurfaceData.PF_INT_ARGB_PRE),
+
+                new OGLSwToSurfaceTransform(SurfaceType.IntRgb,
+                        OGLSurfaceData.PF_INT_RGB),
+                new OGLSwToSurfaceTransform(SurfaceType.IntRgbx,
+                        OGLSurfaceData.PF_INT_RGBX),
+                new OGLSwToSurfaceTransform(SurfaceType.IntBgr,
+                        OGLSurfaceData.PF_INT_BGR),
+                new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
+                        OGLSurfaceData.PF_INT_BGRX),
+                new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+                        OGLSurfaceData.PF_3BYTE_BGR),
+                new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
+                        OGLSurfaceData.PF_USHORT_565_RGB),
+                new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
+                        OGLSurfaceData.PF_USHORT_555_RGB),
+                new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx,
+                        OGLSurfaceData.PF_USHORT_555_RGBX),
+                new OGLSwToSurfaceTransform(SurfaceType.ByteGray,
+                        OGLSurfaceData.PF_BYTE_GRAY),
+                new OGLSwToSurfaceTransform(SurfaceType.UshortGray,
+                        OGLSurfaceData.PF_USHORT_GRAY),
+                transformBlitIntArgbPreToSurface,
+
+                new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
+
+                // texture->surface ops
+                new OGLTextureToSurfaceBlit(),
+                new OGLTextureToSurfaceScale(),
+                new OGLTextureToSurfaceTransform(),
+
+                // sw->texture ops
+                blitIntArgbPreToTexture,
+                new OGLSwToTextureBlit(SurfaceType.IntRgb,
+                        OGLSurfaceData.PF_INT_RGB),
+                new OGLSwToTextureBlit(SurfaceType.IntRgbx,
+                        OGLSurfaceData.PF_INT_RGBX),
+                new OGLSwToTextureBlit(SurfaceType.IntBgr,
+                        OGLSurfaceData.PF_INT_BGR),
+                new OGLSwToTextureBlit(SurfaceType.IntBgrx,
+                        OGLSurfaceData.PF_INT_BGRX),
+                new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
+                        OGLSurfaceData.PF_3BYTE_BGR),
+                new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
+                        OGLSurfaceData.PF_USHORT_565_RGB),
+                new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
+                        OGLSurfaceData.PF_USHORT_555_RGB),
+                new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx,
+                        OGLSurfaceData.PF_USHORT_555_RGBX),
+                new OGLSwToTextureBlit(SurfaceType.ByteGray,
+                        OGLSurfaceData.PF_BYTE_GRAY),
+                new OGLSwToTextureBlit(SurfaceType.UshortGray,
+                        OGLSurfaceData.PF_USHORT_GRAY),
+                new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture,
+                        CompositeType.SrcNoEa,
+                        blitIntArgbPreToTexture),*/
+        };
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    /**
+     * The following offsets are used to pack the parameters in
+     * createPackedParams().  (They are also used at the native level when
+     * unpacking the params.)
+     */
+    @Native private static final int OFFSET_SRCTYPE = 16;
+    @Native private static final int OFFSET_HINT    =  8;
+    @Native private static final int OFFSET_TEXTURE =  3;
+    @Native private static final int OFFSET_RTT     =  2;
+    @Native private static final int OFFSET_XFORM   =  1;
+    @Native private static final int OFFSET_ISOBLIT =  0;
+
+    /**
+     * Packs the given parameters into a single int value in order to save
+     * space on the rendering queue.
+     */
+    private static int createPackedParams(boolean isoblit, boolean texture,
+                                          boolean rtt, boolean xform,
+                                          int hint, int srctype)
+    {
+        return
+                ((srctype           << OFFSET_SRCTYPE) |
+                        (hint              << OFFSET_HINT   ) |
+                        ((texture ? 1 : 0) << OFFSET_TEXTURE) |
+                        ((rtt     ? 1 : 0) << OFFSET_RTT    ) |
+                        ((xform   ? 1 : 0) << OFFSET_XFORM  ) |
+                        ((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
+    }
+
+    /**
+     * Enqueues a BLIT operation with the given parameters.  Note that the
+     * RenderQueue lock must be held before calling this method.
+     */
+    private static void enqueueBlit(RenderQueue rq,
+                                    SurfaceData src, SurfaceData dst,
+                                    int packedParams,
+                                    int sx1, int sy1,
+                                    int sx2, int sy2,
+                                    double dx1, double dy1,
+                                    double dx2, double dy2)
+    {
+        // assert rq.lock.isHeldByCurrentThread();
+        RenderBuffer buf = rq.getBuffer();
+        rq.ensureCapacityAndAlignment(72, 24);
+        buf.putInt(BLIT);
+        buf.putInt(packedParams);
+        buf.putInt(sx1).putInt(sy1);
+        buf.putInt(sx2).putInt(sy2);
+        buf.putDouble(dx1).putDouble(dy1);
+        buf.putDouble(dx2).putDouble(dy2);
+        buf.putLong(src.getNativeOps());
+        buf.putLong(dst.getNativeOps());
+    }
+
+    /*static void Blit(SurfaceData srcData, SurfaceData dstData,
+                     Composite comp, Region clip,
+                     AffineTransform xform, int hint,
+                     int sx1, int sy1,
+                     int sx2, int sy2,
+                     double dx1, double dy1,
+                     double dx2, double dy2,
+                     int srctype, boolean texture)
+    {
+        int ctxflags = 0;
+        if (srcData.getTransparency() == Transparency.OPAQUE) {
+            ctxflags |= OGLContext.SRC_IS_OPAQUE;
+        }
+
+        OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            // make sure the RenderQueue keeps a hard reference to the
+            // source (sysmem) SurfaceData to prevent it from being
+            // disposed while the operation is processed on the QFT
+            rq.addReference(srcData);
+
+            OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
+            if (texture) {
+                // make sure we have a current context before uploading
+                // the sysmem data to the texture object
+                OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig();
+                OGLContext.setScratchSurface(gc);
+            } else {
+                OGLContext.validateContext(oglDst, oglDst,
+                        clip, comp, xform, null, null,
+                        ctxflags);
+            }
+
+            int packedParams = createPackedParams(false, texture,
+                    false, xform != null,
+                    hint, srctype);
+            enqueueBlit(rq, srcData, dstData,
+                    packedParams,
+                    sx1, sy1, sx2, sy2,
+                    dx1, dy1, dx2, dy2);
+
+            // always flush immediately, since we (currently) have no means
+            // of tracking changes to the system memory surface
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
+    }*/
+
+    /**
+     * Note: The srcImg and biop parameters are only used when invoked
+     * from the OGLBufImgOps.renderImageWithOp() method; in all other cases,
+     * this method can be called with null values for those two parameters,
+     * and they will be effectively ignored.
+     */
+    static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
+                        BufferedImage srcImg, BufferedImageOp biop,
+                        Composite comp, Region clip,
+                        AffineTransform xform, int hint,
+                        int sx1, int sy1,
+                        int sx2, int sy2,
+                        double dx1, double dy1,
+                        double dx2, double dy2,
+                        boolean texture)
+    {
+        /*int ctxflags = 0;
+        if (srcData.getTransparency() == Transparency.OPAQUE) {
+            ctxflags |= OGLContext.SRC_IS_OPAQUE;
+        }*/
+
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        rq.lock();
+        try {
+            MetalSurfaceData metalSrc = (MetalSurfaceData)srcData;
+            MetalSurfaceData metalDst = (MetalSurfaceData)dstData;
+            int srctype = metalSrc.getType();
+            /*boolean rtt;
+            OGLSurfaceData srcCtxData;
+            if (srctype == OGLSurfaceData.TEXTURE) {
+                // the source is a regular texture object; we substitute
+                // the destination surface for the purposes of making a
+                // context current
+                rtt = false;
+                srcCtxData = oglDst;
+            } else {
+                // the source is a pbuffer, backbuffer, or render-to-texture
+                // surface; we set rtt to true to differentiate this kind
+                // of surface from a regular texture object
+                rtt = true;
+                if (srctype == OGLSurfaceData.FBOBJECT) {
+                    srcCtxData = oglDst;
+                } else {
+                    srcCtxData = oglSrc;
+                }
+            }
+
+            OGLContext.validateContext(srcCtxData, oglDst,
+                    clip, comp, xform, null, null,
+                    ctxflags);
+
+            if (biop != null) {
+                OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop);
+            }*/
+
+            int packedParams = createPackedParams(true, texture,
+                    false, xform != null,
+                    hint, 0 /*unused*/);
+            enqueueBlit(rq, srcData, dstData,
+                    packedParams,
+                    sx1, sy1, sx2, sy2,
+                    dx1, dy1, dx2, dy2);
+
+            /*if (biop != null) {
+                OGLBufImgOps.disableBufImgOp(rq, biop);
+            }
+
+            if (rtt && oglDst.isOnScreen()) {
+                // we only have to flush immediately when copying from a
+                // (non-texture) surface to the screen; otherwise Swing apps
+                // might appear unresponsive until the auto-flush completes
+                rq.flushNow();
+            }*/
+        } finally {
+            rq.unlock();
+        }
+    }
+}
+
+/*class OGLSurfaceToSurfaceBlit extends Blit {
+
+    OGLSurfaceToSurfaceBlit() {
+        super(OGLSurfaceData.OpenGLSurface,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                false);
+    }
+}
+
+class OGLSurfaceToSurfaceScale extends ScaledBlit {
+
+    OGLSurfaceToSurfaceScale() {
+        super(OGLSurfaceData.OpenGLSurface,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Scale(SurfaceData src, SurfaceData dst,
+                      Composite comp, Region clip,
+                      int sx1, int sy1,
+                      int sx2, int sy2,
+                      double dx1, double dy1,
+                      double dx2, double dy2)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                false);
+    }
+}
+
+class OGLSurfaceToSurfaceTransform extends TransformBlit {
+
+    OGLSurfaceToSurfaceTransform() {
+        super(OGLSurfaceData.OpenGLSurface,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst,
+                          Composite comp, Region clip,
+                          AffineTransform at, int hint,
+                          int sx, int sy, int dx, int dy,
+                          int w, int h)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                false);
+    }
+}*/
+
+class MetalSurfaceToSurfaceBlit extends Blit {
+
+    MetalSurfaceToSurfaceBlit() {
+        super(MetalSurfaceData.MetalSurface,
+                CompositeType.AnyAlpha,
+                MetalSurfaceData.MetalSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        // TODO : Eventhough we push IsoBlit logic into queue,
+        // in renderer we have not yet implemented blit.
+        MetalBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                true);
+    }
+}
+
+/*class OGLRTTSurfaceToSurfaceScale extends ScaledBlit {
+
+    OGLRTTSurfaceToSurfaceScale() {
+        super(OGLSurfaceData.OpenGLSurfaceRTT,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Scale(SurfaceData src, SurfaceData dst,
+                      Composite comp, Region clip,
+                      int sx1, int sy1,
+                      int sx2, int sy2,
+                      double dx1, double dy1,
+                      double dx2, double dy2)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                true);
+    }
+}
+
+class OGLRTTSurfaceToSurfaceTransform extends TransformBlit {
+
+    OGLRTTSurfaceToSurfaceTransform() {
+        super(OGLSurfaceData.OpenGLSurfaceRTT,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst,
+                          Composite comp, Region clip,
+                          AffineTransform at, int hint,
+                          int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                true);
+    }
+}
+
+final class OGLSurfaceToSwBlit extends Blit {
+
+    private final int typeval;
+    private WeakReference<SurfaceData> srcTmp;
+
+    // destination will actually be ArgbPre or Argb
+    OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval) {
+        super(OGLSurfaceData.OpenGLSurface,
+                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 OpenGL surface in two places:
+        // - During OpenGL surface -> SW blit
+        // - During SW -> SW blit
+        // The first one is faster when we use opaque OGL 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 == OGLSurfaceData.PF_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;
+            }
+        }
+
+        OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            // make sure the RenderQueue keeps a hard reference to the
+            // destination (sysmem) SurfaceData to prevent it from being
+            // disposed while the operation is processed on the QFT
+            rq.addReference(dst);
+
+            RenderBuffer buf = rq.getBuffer();
+            OGLContext.validateContext((OGLSurfaceData)src);
+
+            rq.ensureCapacityAndAlignment(48, 32);
+            buf.putInt(SURFACE_TO_SW_BLIT);
+            buf.putInt(sx).putInt(sy);
+            buf.putInt(dx).putInt(dy);
+            buf.putInt(w).putInt(h);
+            buf.putInt(typeval);
+            buf.putLong(src.getNativeOps());
+            buf.putLong(dst.getNativeOps());
+
+            // always flush immediately
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
+    }
+}
+
+class OGLSwToSurfaceBlit extends Blit {
+
+    private int typeval;
+
+    OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+        this.typeval = typeval;
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.Blit(src, dst,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                typeval, false);
+    }
+}
+
+class OGLSwToSurfaceScale extends ScaledBlit {
+
+    private int typeval;
+
+    OGLSwToSurfaceScale(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+        this.typeval = typeval;
+    }
+
+    public void Scale(SurfaceData src, SurfaceData dst,
+                      Composite comp, Region clip,
+                      int sx1, int sy1,
+                      int sx2, int sy2,
+                      double dx1, double dy1,
+                      double dx2, double dy2)
+    {
+        OGLBlitLoops.Blit(src, dst,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                typeval, false);
+    }
+}
+
+class OGLSwToSurfaceTransform extends TransformBlit {
+
+    private int typeval;
+
+    OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+        this.typeval = typeval;
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst,
+                          Composite comp, Region clip,
+                          AffineTransform at, int hint,
+                          int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.Blit(src, dst,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                typeval, false);
+    }
+}
+
+class OGLSwToTextureBlit extends Blit {
+
+    private int typeval;
+
+    OGLSwToTextureBlit(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.SrcNoEa,
+                OGLSurfaceData.OpenGLTexture);
+        this.typeval = typeval;
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.Blit(src, dst,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                typeval, true);
+    }
+}
+
+class OGLTextureToSurfaceBlit extends Blit {
+
+    OGLTextureToSurfaceBlit() {
+        super(OGLSurfaceData.OpenGLTexture,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                true);
+    }
+}
+
+class OGLTextureToSurfaceScale extends ScaledBlit {
+
+    OGLTextureToSurfaceScale() {
+        super(OGLSurfaceData.OpenGLTexture,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Scale(SurfaceData src, SurfaceData dst,
+                      Composite comp, Region clip,
+                      int sx1, int sy1,
+                      int sx2, int sy2,
+                      double dx1, double dy1,
+                      double dx2, double dy2)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                true);
+    }
+}
+
+class OGLTextureToSurfaceTransform extends TransformBlit {
+
+    OGLTextureToSurfaceTransform() {
+        super(OGLSurfaceData.OpenGLTexture,
+                CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst,
+                          Composite comp, Region clip,
+                          AffineTransform at, int hint,
+                          int sx, int sy, int dx, int dy,
+                          int w, int h)
+    {
+        OGLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                true);
+    }
+}*/
+
+/**
+ * This general Blit implementation converts any source surface to an
+ * intermediate IntArgbPre surface, and then uses the more specific
+ * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
+ * (premultiplied) surface down to OpenGL using simple blit.
+ */
+/*class OGLGeneralBlit extends Blit {
+
+    private final Blit performop;
+    private WeakReference<SurfaceData> srcTmp;
+
+    OGLGeneralBlit(SurfaceType dstType,
+                   CompositeType compType,
+                   Blit performop)
+    {
+        super(SurfaceType.Any, compType, dstType);
+        this.performop = performop;
+    }
+
+    public synchronized void Blit(SurfaceData src, SurfaceData dst,
+                                  Composite comp, Region clip,
+                                  int sx, int sy, int dx, int dy,
+                                  int w, int h)
+    {
+        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
+                CompositeType.SrcNoEa,
+                SurfaceType.IntArgbPre);
+
+        SurfaceData cachedSrc = null;
+        if (srcTmp != null) {
+            // use cached intermediate surface, if available
+            cachedSrc = srcTmp.get();
+        }
+
+        // convert source to IntArgbPre
+        src = convertFrom(convertsrc, src, sx, sy, w, h,
+                cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
+
+        // copy IntArgbPre intermediate surface to OpenGL surface
+        performop.Blit(src, dst, comp, clip,
+                0, 0, dx, dy, w, h);
+
+        if (src != cachedSrc) {
+            // cache the intermediate surface
+            srcTmp = new WeakReference<>(src);
+        }
+    }
+}*/
+
+/**
+ * This general TransformedBlit implementation converts any source surface to an
+ * intermediate IntArgbPre surface, and then uses the more specific
+ * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
+ * (premultiplied) surface down to OpenGL using simple transformBlit.
+ */
+/*final class OGLGeneralTransformedBlit extends TransformBlit {
+
+    private final TransformBlit performop;
+    private WeakReference<SurfaceData> srcTmp;
+
+    OGLGeneralTransformedBlit(final TransformBlit performop) {
+        super(SurfaceType.Any, CompositeType.AnyAlpha,
+                OGLSurfaceData.OpenGLSurface);
+        this.performop = performop;
+    }
+
+    @Override
+    public synchronized void Transform(SurfaceData src, SurfaceData dst,
+                                       Composite comp, Region clip,
+                                       AffineTransform at, int hint, int srcx,
+                                       int srcy, int dstx, int dsty, int width,
+                                       int height){
+        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
+                CompositeType.SrcNoEa,
+                SurfaceType.IntArgbPre);
+        // use cached intermediate surface, if available
+        final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
+        // convert source to IntArgbPre
+        src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
+                BufferedImage.TYPE_INT_ARGB_PRE);
+
+        // transform IntArgbPre intermediate surface to OpenGL surface
+        performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
+                width, height);
+
+        if (src != cachedSrc) {
+            // cache the intermediate surface
+            srcTmp = new WeakReference<>(src);
+        }
+    }
+}*/
+
+/**
+ * This general OGLAnyCompositeBlit implementation can convert any source/target
+ * surface to an intermediate surface using convertsrc/convertdst loops, applies
+ * necessary composite operation, and then uses convertresult loop to get the
+ * intermediate surface down to OpenGL.
+ */
+/*final class OGLAnyCompositeBlit extends Blit {
+
+    private WeakReference<SurfaceData> dstTmp;
+    private WeakReference<SurfaceData> srcTmp;
+    private final Blit convertsrc;
+    private final Blit convertdst;
+    private final Blit convertresult;
+
+    OGLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,
+                        Blit convertresult) {
+        super(srctype, CompositeType.Any, OGLSurfaceData.OpenGLSurface);
+        this.convertsrc = convertsrc;
+        this.convertdst = convertdst;
+        this.convertresult = convertresult;
+    }
+
+    public synchronized void Blit(SurfaceData src, SurfaceData dst,
+                                  Composite comp, Region clip,
+                                  int sx, int sy, int dx, int dy,
+                                  int w, int h)
+    {
+        if (convertsrc != null) {
+            SurfaceData cachedSrc = null;
+            if (srcTmp != null) {
+                // use cached intermediate surface, if available
+                cachedSrc = srcTmp.get();
+            }
+            // convert source to IntArgbPre
+            src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc,
+                    BufferedImage.TYPE_INT_ARGB_PRE);
+            if (src != cachedSrc) {
+                // cache the intermediate surface
+                srcTmp = new WeakReference<>(src);
+            }
+        }
+
+        SurfaceData cachedDst = null;
+
+        if (dstTmp != null) {
+            // use cached intermediate surface, if available
+            cachedDst = dstTmp.get();
+        }
+
+        // convert destination to IntArgbPre
+        SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,
+                cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);
+        Region bufferClip =
+                clip == null ? null : clip.getTranslatedRegion(-dx, -dy);
+
+        Blit performop = Blit.getFromCache(src.getSurfaceType(),
+                CompositeType.Any, dstBuffer.getSurfaceType());
+        performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h);
+
+        if (dstBuffer != cachedDst) {
+            // cache the intermediate surface
+            dstTmp = new WeakReference<>(dstBuffer);
+        }
+        // now blit the buffer back to the destination
+        convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx,
+                dy, w, h);
+    }
+}*/
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java	Fri Mar 01 18:04:46 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java	Tue Mar 05 16:36:45 2019 +0530
@@ -27,6 +27,7 @@
 
 import java.awt.*;
 
+import sun.awt.image.PixelConverter;
 import sun.java2d.SurfaceData;
 
 import java.awt.Composite;
@@ -65,6 +66,15 @@
     protected static MetalRenderer mtlRenderPipe;
     protected static PixelToParallelogramConverter mtlTxRenderPipe;
 
+    /**
+     * SurfaceTypes
+     */
+    private static final String DESC_METAL_SURFACE = "Metal Surface";
+
+    static final SurfaceType MetalSurface =
+            SurfaceType.Any.deriveSubType(DESC_METAL_SURFACE,
+                    PixelConverter.ArgbPre.instance);
+
     private native int getTextureTarget(long pData);
     private native int getTextureID(long pData);
     protected native boolean initTexture(long pData,
@@ -83,6 +93,7 @@
                 new PixelToParallelogramConverter(mtlRenderPipe,
                                                   mtlRenderPipe,
                                                   1.0, 0.25, true);
+            MetalBlitLoops.register();
         }
     }
 
@@ -95,7 +106,8 @@
                      int width, int height) {
         // TODO : Map the coming type to proper custom type and call super()
         //super(gc, cm, type);
-        super(SurfaceType.Any3Byte, cm );
+        //super(SurfaceType.Any3Byte, cm );
+        super(MetalSurface, cm );
         // TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
         // TODO : We need to set scale factor
         //scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor();
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m	Fri Mar 01 18:04:46 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m	Tue Mar 05 16:36:45 2019 +0530
@@ -344,6 +344,8 @@
         layer.textureWidth = metalsdo->width;
         layer.textureHeight = metalsdo->height;
 
+        VertexDataManager_reset(metalsdo->configInfo->device);
+
         NSLog(@"Validate : Width : %f", layer.textureWidth);
         NSLog(@"Validate : height : %f", layer.textureHeight);
 
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h	Fri Mar 01 18:04:46 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h	Tue Mar 05 16:36:45 2019 +0530
@@ -55,6 +55,7 @@
 unsigned int VertexDataManager_getNoOfPrimitives();
 
 void VertexDataManager_freeAllPrimitives();
+void VertexDataManager_reset(id<MTLDevice> device);
 
 // should be private
 void addVertex(MetalVertex vert);
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m	Fri Mar 01 18:04:46 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m	Tue Mar 05 16:36:45 2019 +0530
@@ -152,5 +152,15 @@
     free(AllPrimitives);
 }
 
+void VertexDataManager_reset(id<MTLDevice> device) {
+    VertexDataManager_freeAllPrimitives();
+    VertexBuffer = NULL;
+    IndexBuffer = NULL;
+    no_of_vertices = 0;
+    no_of_indices = 0;
+    no_of_primitives = 0;
+    AllPrimitives = NULL;
+    VertexDataManager_init(device);
+}
 
 #endif /* !HEADLESS */