Merge metal-prototype-branch
authorjdv
Mon, 11 Mar 2019 14:05:27 +0530
branchmetal-prototype-branch
changeset 57251 86ed45a9dedb
parent 57247 48f2dc62ba77 (diff)
parent 54048 744dc9c33676 (current diff)
child 57357 f3beca8f19fc
Merge
--- a/make/lib/Awt2dLibraries.gmk	Mon Mar 11 02:05:07 2019 -0400
+++ b/make/lib/Awt2dLibraries.gmk	Mon Mar 11 14:05:27 2019 +0530
@@ -925,6 +925,7 @@
           -framework JavaNativeFoundation \
           -framework JavaRuntimeSupport \
           -framework OpenGL \
+          -framework Metal \
           -framework QuartzCore -ljava, \
   ))
 
--- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsConfig.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsConfig.java	Mon Mar 11 14:05:27 2019 +0530
@@ -33,6 +33,7 @@
 
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLLayer;
+import sun.java2d.metal.MetalLayer;
 import sun.lwawt.LWGraphicsConfig;
 import sun.lwawt.macosx.CPlatformView;
 
@@ -89,6 +90,9 @@
      */
     public abstract SurfaceData createSurfaceData(CGLLayer layer);
 
+
+    public abstract SurfaceData createSurfaceData(MetalLayer layer);
+
     @Override
     public final boolean isTranslucencyCapable() {
         //we know for sure we have capable config :)
--- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java	Mon Mar 11 14:05:27 2019 +0530
@@ -37,6 +37,7 @@
 
 import sun.java2d.SunGraphicsEnvironment;
 import sun.java2d.opengl.CGLGraphicsConfig;
+import sun.java2d.metal.MetalGraphicsConfig;
 
 public final class CGraphicsDevice extends GraphicsDevice
         implements DisplayChangedListener {
@@ -60,7 +61,25 @@
 
     public CGraphicsDevice(final int displayID) {
         this.displayID = displayID;
-        config = CGLGraphicsConfig.getConfig(this, displayID, 0);
+
+        if (isMetalSystemProperty()) {
+            config = MetalGraphicsConfig.getConfig(this, displayID, 0);
+            System.out.println("Created MetalGraphicsConfig");
+        } else {
+            config = CGLGraphicsConfig.getConfig(this, displayID, 0);
+        }
+    }
+
+    private boolean isMetalSystemProperty() {
+           String str = System.getProperty("sun.java2d.metal");
+           
+           if (str != null) {
+               System.out.println("Property : sun.java2d.metal=" + str);
+               if (str.equals("true")) {
+                return true;    
+               }
+         }
+         return false;
     }
 
     /**
--- a/src/java.desktop/macosx/classes/sun/java2d/MacosxSurfaceManagerFactory.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/java2d/MacosxSurfaceManagerFactory.java	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -28,6 +28,8 @@
 import sun.awt.image.SunVolatileImage;
 import sun.awt.image.VolatileSurfaceManager;
 import sun.java2d.opengl.CGLVolatileSurfaceManager;
+import sun.java2d.metal.MetalVolatileSurfaceManager;
+
 
 /**
  * This is a factory class with static methods for creating a
@@ -49,6 +51,23 @@
     public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
                                                         Object context)
     {
-        return new CGLVolatileSurfaceManager(vImg, context);
+        if (isMetalSystemProperty()) {
+            return new MetalVolatileSurfaceManager(vImg, context);
+        } else {
+            return new CGLVolatileSurfaceManager(vImg, context);
+        }
+    }
+
+
+    private boolean isMetalSystemProperty() {
+        String str = System.getProperty("sun.java2d.metal");
+
+        if (str != null) {
+            System.out.println("Property : sun.java2d.metal=" + str);
+            if (str.equals("true")) {
+                return true;
+            }
+        }
+        return false;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalBlitLoops.java	Mon Mar 11 14:05:27 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);
+    }
+}*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalContext.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019, 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 sun.java2d.pipe.BufferedContext;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+import sun.java2d.pipe.hw.ContextCapabilities;
+import static sun.java2d.pipe.BufferedOpCodes.*;
+import static sun.java2d.pipe.hw.ContextCapabilities.*;
+
+import java.lang.annotation.Native;
+
+/**
+ * Note that the RenderQueue lock must be acquired before calling any of
+ * the methods in this class.
+ */
+public class MetalContext extends BufferedContext {
+
+    private final MetalGraphicsConfig config;
+
+    MetalContext(RenderQueue rq, MetalGraphicsConfig config) {
+        super(rq);
+        this.config = config;
+    }
+
+    static void setScratchSurface(MetalGraphicsConfig gc) {
+        setScratchSurface(gc.getNativeConfigInfo());
+    }
+ 
+    /**
+     * Makes the given GraphicsConfig's context current to its associated
+     * "scratch surface".  Each GraphicsConfig maintains a native context
+     * (GLXContext on Unix, HGLRC on Windows) as well as a native pbuffer
+     * known as the "scratch surface".  By making the context current to the
+     * scratch surface, we are assured that we have a current context for
+     * the relevant GraphicsConfig, and can therefore perform operations
+     * depending on the capabilities of that GraphicsConfig.  For example,
+     * if the GraphicsConfig supports the GL_ARB_texture_non_power_of_two
+     * extension, then we should be able to make a non-pow2 texture for this
+     * GraphicsConfig once we make the context current to the scratch surface.
+     *
+     * This method should be used for operations with an OpenGL texture
+     * as the destination surface (e.g. a sw->texture blit loop), or in those
+     * situations where we may not otherwise have a current context (e.g.
+     * when disposing a texture-based surface).
+     */
+    static void setScratchSurface(long pConfigInfo) {
+        // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread();
+
+        // invalidate the current context
+        currentContext = null;
+
+        // set the scratch context
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        RenderBuffer buf = rq.getBuffer();
+        rq.ensureCapacityAndAlignment(12, 4);
+        buf.putInt(SET_SCRATCH_SURFACE);
+        buf.putLong(pConfigInfo);
+    }
+
+    /**
+     * Invalidates the currentContext field to ensure that we properly
+     * revalidate the OGLContext (make it current, etc.) next time through
+     * the validate() method.  This is typically invoked from methods
+     * that affect the current context state (e.g. disposing a context or
+     * surface).
+     */
+    static void invalidateCurrentContext() {
+        // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread();
+
+        // invalidate the current Java-level context so that we
+        // revalidate everything the next time around
+        if (currentContext != null) {
+            currentContext.invalidateContext();
+            currentContext = null;
+        }
+
+        // invalidate the context reference at the native level, and
+        // then flush the queue so that we have no pending operations
+        // dependent on the current context
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        rq.ensureCapacity(4);
+        rq.getBuffer().putInt(INVALIDATE_CONTEXT);
+        rq.flushNow();
+    }
+
+    public RenderQueue getRenderQueue() {
+        return MetalRenderQueue.getInstance();
+    }
+
+    /**
+     * Returns a string representing adapter id (vendor, renderer, version).
+     * Must be called on the rendering thread.
+     *
+     * @return an id string for the adapter
+     */
+    //static final native String getOGLIdString();
+
+    @Override
+    public void saveState() {
+        // assert rq.lock.isHeldByCurrentThread();
+
+        // reset all attributes of this and current contexts
+        invalidateContext();
+        invalidateCurrentContext();
+
+        setScratchSurface(config);
+
+        // save the state on the native level
+        rq.ensureCapacity(4);
+        buf.putInt(SAVE_STATE);
+        rq.flushNow();
+    }
+
+    @Override
+    public void restoreState() {
+        // assert rq.lock.isHeldByCurrentThread();
+
+        // reset all attributes of this and current contexts
+        invalidateContext();
+        invalidateCurrentContext();
+
+        setScratchSurface(config);
+
+        // restore the state on the native level
+        rq.ensureCapacity(4);
+        buf.putInt(RESTORE_STATE);
+        rq.flushNow();
+    }
+
+    //static class OGLContextCaps extends ContextCapabilities {
+        /**
+         * Indicates the presence of the GL_EXT_framebuffer_object extension.
+         * This cap will only be set if the fbobject system property has been
+         * enabled and we are able to create an FBO with depth buffer.
+         */
+    //  @Native
+    // static final int CAPS_EXT_FBOBJECT     =
+    //            (CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE);
+        /** Indicates that the context is doublebuffered. */
+    //    @Native
+    //    static final int CAPS_DOUBLEBUFFERED   = (FIRST_PRIVATE_CAP << 0);
+        /**
+         * Indicates the presence of the GL_ARB_fragment_shader extension.
+         * This cap will only be set if the lcdshader system property has been
+         * enabled and the hardware supports the minimum number of texture units
+         */
+    //    @Native
+    //    static final int CAPS_EXT_LCD_SHADER   = (FIRST_PRIVATE_CAP << 1);
+        /**
+         * Indicates the presence of the GL_ARB_fragment_shader extension.
+         * This cap will only be set if the biopshader system property has been
+         * enabled and the hardware meets our minimum requirements.
+         */
+    //    @Native
+    //    static final int CAPS_EXT_BIOP_SHADER  = (FIRST_PRIVATE_CAP << 2);
+        /**
+         * Indicates the presence of the GL_ARB_fragment_shader extension.
+         * This cap will only be set if the gradshader system property has been
+         * enabled and the hardware meets our minimum requirements.
+         */
+    //    @Native
+    //    static final int CAPS_EXT_GRAD_SHADER  = (FIRST_PRIVATE_CAP << 3);
+        /** Indicates the presence of the GL_ARB_texture_rectangle extension. */
+    //    @Native
+    //    static final int CAPS_EXT_TEXRECT      = (FIRST_PRIVATE_CAP << 4);
+        /** Indicates the presence of the GL_NV_texture_barrier extension. */
+    //    @Native
+    //    static final int CAPS_EXT_TEXBARRIER = (FIRST_PRIVATE_CAP << 5);
+
+
+    /*    OGLContextCaps(int caps, String adapterId) {
+            super(caps, adapterId);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(super.toString());
+            if ((caps & CAPS_EXT_FBOBJECT) != 0) {
+                sb.append("CAPS_EXT_FBOBJECT|");
+            }
+            if ((caps & CAPS_DOUBLEBUFFERED) != 0) {
+                sb.append("CAPS_DOUBLEBUFFERED|");
+            }
+            if ((caps & CAPS_EXT_LCD_SHADER) != 0) {
+                sb.append("CAPS_EXT_LCD_SHADER|");
+            }
+            if ((caps & CAPS_EXT_BIOP_SHADER) != 0) {
+                sb.append("CAPS_BIOP_SHADER|");
+            }
+            if ((caps & CAPS_EXT_GRAD_SHADER) != 0) {
+                sb.append("CAPS_EXT_GRAD_SHADER|");
+            }
+            if ((caps & CAPS_EXT_TEXRECT) != 0) {
+                sb.append("CAPS_EXT_TEXRECT|");
+            }
+            if ((caps & CAPS_EXT_TEXBARRIER) != 0) {
+                sb.append("CAPS_EXT_TEXBARRIER|");
+            }
+            return sb.toString();
+        }
+    }*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalGraphicsConfig.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2019, 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 sun.awt.CGraphicsConfig;
+import sun.awt.CGraphicsDevice;
+import sun.java2d.Disposer;
+import sun.java2d.SurfaceData;
+import sun.java2d.pipe.hw.ContextCapabilities;
+import sun.lwawt.LWComponentPeer;
+import sun.lwawt.macosx.CPlatformView;
+import sun.java2d.opengl.CGLLayer;
+import sun.java2d.metal.MetalContext;
+import sun.java2d.metal.MetalRenderQueue;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+
+import java.awt.*;
+
+public final class MetalGraphicsConfig extends CGraphicsConfig {
+
+    private int pixfmt;
+    public long pConfigInfo; //public access is a hack
+    private static native long getMetalConfigInfo(int displayID, int visualnum);
+
+    private MetalContext context;
+    
+    long getNativeConfigInfo() {
+        return pConfigInfo;
+    }
+
+    @Override
+    public int getMaxTextureWidth() {
+        return 16384; 
+        /* Getting Device Caps from Metal Device is required. 
+           There is no API for this. We need to refer manual and populate these values. 
+           Refer https://wiki.se.oracle.com/display/JPGC/Metal+Rendering+Pipeline */
+    }
+
+    @Override
+    public int getMaxTextureHeight() {
+        return 16384;
+    }
+
+    @Override
+    public void assertOperationSupported(int numBuffers, BufferCapabilities caps) throws AWTException {
+
+    }
+
+    @Override
+    public Image createBackBuffer(LWComponentPeer<?, ?> peer) {
+        return null;
+    }
+
+    @Override
+    public void destroyBackBuffer(Image backBuffer) {
+
+    }
+
+    @Override
+    public void flip(LWComponentPeer<?, ?> peer, Image backBuffer, int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) {
+
+    }
+
+    @Override
+    public Image createAcceleratedImage(Component target, int width, int height) {
+        return null;
+    }
+
+    private MetalGraphicsConfig(CGraphicsDevice device, int pixfmt,
+                                long configInfo) {
+        super(device);
+
+        this.pixfmt = pixfmt;
+        this.pConfigInfo = configInfo;
+        //this.oglCaps = oglCaps;
+        //this.maxTextureSize = maxTextureSize;
+        // TODO : We are using MetalContext as of now.
+        // We need to verify its usage in future to keep/remove it.
+        context = new MetalContext(MetalRenderQueue.getInstance(), this);
+
+        // add a record to the Disposer so that we destroy the native
+        // CGLGraphicsConfigInfo data when this object goes away
+        //Disposer.addRecord(disposerReferent,
+                //new CGLGraphicsConfig.CGLGCDisposerRecord(pConfigInfo));
+    }
+
+    public static MetalGraphicsConfig getConfig(CGraphicsDevice device, int displayID,
+                                              int pixfmt)
+    {
+        //if (!cglAvailable) {
+            //return null;
+        //}
+
+        long cfginfo = 0;
+        //int textureSize = 0;
+        //final String ids[] = new String[1];
+        //OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        //rq.lock();
+        //try {
+            // getCGLConfigInfo() creates and destroys temporary
+            // surfaces/contexts, so we should first invalidate the current
+            // Java-level context and flush the queue...
+            //OGLContext.invalidateCurrentContext();
+
+            cfginfo = getMetalConfigInfo(displayID, pixfmt);
+            /*if (cfginfo != 0L) {
+                textureSize = nativeGetMaxTextureSize();
+                // 7160609: GL still fails to create a square texture of this
+                // size. Half should be safe enough.
+                // Explicitly not support a texture more than 2^14, see 8010999.
+                textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
+                OGLContext.setScratchSurface(cfginfo);
+                rq.flushAndInvokeNow(() -> {
+                    ids[0] = OGLContext.getOGLIdString();
+                });
+            }
+        } finally {
+            rq.unlock();
+        }
+        if (cfginfo == 0) {
+            return null;
+        }
+
+        int oglCaps = getOGLCapabilities(cfginfo);
+        ContextCapabilities caps = new OGLContext.OGLContextCaps(oglCaps, ids[0]);*/
+        return new MetalGraphicsConfig(device, pixfmt, cfginfo);
+    }
+
+    @Override
+    public SurfaceData createSurfaceData(CPlatformView pView) {
+        return null;
+    }
+
+    @Override
+    public SurfaceData createSurfaceData(CGLLayer layer) {
+        return null;
+    }
+
+    @Override
+    public SurfaceData createSurfaceData(MetalLayer layer) {
+        return MetalSurfaceData.createData(layer);
+    }
+
+    @Override
+    public ColorModel getColorModel(int transparency) {
+        switch (transparency) {
+        case Transparency.OPAQUE:
+            // REMIND: once the ColorModel spec is changed, this should be
+            //         an opaque premultiplied DCM...
+            return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
+        case Transparency.BITMASK:
+            return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
+        case Transparency.TRANSLUCENT:
+            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+            return new DirectColorModel(cs, 32,
+                                        0xff0000, 0xff00, 0xff, 0xff000000,
+                                        true, DataBuffer.TYPE_INT);
+        default:
+            return null;
+        }
+    }
+
+    public MetalContext getContext() {
+        return context;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalLayer.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019, 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 sun.lwawt.LWWindowPeer;
+import sun.lwawt.macosx.CFRetainedResource;
+import sun.java2d.SurfaceData;
+import sun.java2d.NullSurfaceData;
+
+import java.awt.*;
+
+import sun.awt.CGraphicsConfig;
+import sun.java2d.metal.MetalGraphicsConfig;
+
+public class MetalLayer extends CFRetainedResource {
+
+    private native long nativeCreateLayer();
+    private native long nativeInitLayer(long deviceInfo, long layer);
+    //private native long nativeValidate(long layer, long view);
+    //private native long nativeDraw(long layer);
+    private static native void validate(long layerPtr, MetalSurfaceData msd);
+    private static native void nativeSetScale(long layerPtr, double scale);
+    //private static native void nativeSetScale(long layerPtr, double scale);
+    //private static native void blitTexture(long layerPtr);
+
+    private LWWindowPeer peer;
+    private int scale = 1;
+    private SurfaceData surfaceData; // represents intermediate buffer (texture)
+    private long pNativeLayer;
+
+    public MetalLayer(LWWindowPeer peer) {
+        super(0, true);
+
+        pNativeLayer = nativeCreateLayer();
+        setPtr(pNativeLayer);
+        this.peer = peer;
+
+        // TODO : No need to initialize layer here, it will be done
+        // when we initialize surface in MetalSurfaceData.
+        MetalGraphicsConfig gc = (MetalGraphicsConfig)getGraphicsConfiguration();
+        nativeInitLayer(gc.pConfigInfo, pNativeLayer);
+    }
+
+     public long getPointer() {
+        return ptr;
+    }
+
+
+    public Rectangle getBounds() {
+        return peer.getBounds();
+    }
+
+    public GraphicsConfiguration getGraphicsConfiguration() {
+        return peer.getGraphicsConfiguration();
+    }
+
+    public boolean isOpaque() {
+        return !peer.isTranslucent();
+    }
+
+    public int getTransparency() {
+        return isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT;
+    }
+
+    public Object getDestination() {
+        return peer.getTarget();
+    }
+    
+    public SurfaceData replaceSurfaceData() {
+        if (getBounds().isEmpty()) {
+            surfaceData = NullSurfaceData.theInstance;
+            return surfaceData;
+        }
+
+        // the layer redirects all painting to the buffer's graphics
+        // and blits the buffer to the layer surface (in drawInCGLContext callback)
+        CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration();
+        surfaceData = gc.createSurfaceData(this);
+
+        setScale(gc.getDevice().getScaleFactor());
+
+        // the layer holds a reference to the buffer, which in
+        // turn has a reference back to this layer
+        if (surfaceData instanceof MetalSurfaceData) {
+            validate((MetalSurfaceData)surfaceData);
+        }
+
+        return surfaceData;
+       
+    } 
+
+    public SurfaceData getSurfaceData() {
+        return surfaceData;
+    }
+
+    /*public void validate(long viewPtr) {
+        //OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        //rq.lock();
+        try {
+            execute(ptr -> nativeValidate(ptr, viewPtr));
+        } finally {
+            //   rq.unlock();
+        }
+    }*/
+
+    public void validate(final MetalSurfaceData metalsd) {
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        rq.lock();
+        try {
+            execute(ptr -> validate(ptr, metalsd));
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    @Override
+    public void dispose() {
+        // break the connection between the layer and the buffer
+        validate(null);
+        super.dispose();
+    }
+
+    private void setScale(final int _scale) {
+        if (scale != _scale) {
+            scale = _scale;
+            execute(ptr -> nativeSetScale(ptr, scale));
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // NATIVE CALLBACKS : TODO: check how should this be done in Metal?
+    // ----------------------------------------------------------------------
+
+    public void drawInMetalContext(long viewPtr) {
+        // tell the flusher thread not to update the intermediate buffer
+        // until we are done blitting from it
+        /*OGLRenderQueue rq = OGLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            execute(ptr -> blitTexture(ptr));
+        } finally {
+            rq.unlock();
+        }*/
+        System.out.println("drawInMetalContext method invoked");
+
+        //nativeDraw(pNativeLayer);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderQueue.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2019, 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 sun.awt.util.ThreadGroupUtils;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+
+import static sun.java2d.pipe.BufferedOpCodes.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * OGL-specific implementation of RenderQueue.  This class provides a
+ * single (daemon) thread that is responsible for periodically flushing
+ * the queue, thus ensuring that only one thread communicates with the native
+ * OpenGL libraries for the entire process.
+ */
+public class MetalRenderQueue extends RenderQueue {
+    
+    private static MetalRenderQueue theInstance;
+    private final QueueFlusher flusher;
+    
+    private MetalRenderQueue() {
+        /*
+         * The thread must be a member of a thread group
+         * which will not get GCed before VM exit.
+         */
+        flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) QueueFlusher::new);
+    }
+    
+    /**
+     * Returns the single OGLRenderQueue instance.  If it has not yet been
+     * initialized, this method will first construct the single instance
+     * before returning it.
+     */
+    public static synchronized MetalRenderQueue getInstance() {
+        if (theInstance == null) {
+            theInstance = new MetalRenderQueue();
+        }
+        return theInstance;
+    }
+    
+    /**
+     * Flushes the single OGLRenderQueue instance synchronously.  If an
+     * OGLRenderQueue has not yet been instantiated, this method is a no-op.
+     * This method is useful in the case of Toolkit.sync(), in which we want
+     * to flush the OGL pipeline, but only if the OGL pipeline is currently
+     * enabled.  Since this class has few external dependencies, callers need
+     * not be concerned that calling this method will trigger initialization
+     * of the OGL pipeline and related classes.
+     */
+    public static void sync() {
+        if (theInstance != null) {
+            theInstance.lock();
+            try {
+                theInstance.ensureCapacity(4);
+                theInstance.getBuffer().putInt(SYNC);
+                theInstance.flushNow();
+            } finally {
+                theInstance.unlock();
+            }
+        }
+    }
+    
+    /**
+     * Disposes the native memory associated with the given native
+     * graphics config info pointer on the single queue flushing thread.
+     */
+    public static void disposeGraphicsConfig(long pConfigInfo) {
+        MetalRenderQueue rq = getInstance();
+        rq.lock();
+        try {
+            // make sure we make the context associated with the given
+            // GraphicsConfig current before disposing the native resources
+            MetalContext.setScratchSurface(pConfigInfo);
+            
+            RenderBuffer buf = rq.getBuffer();
+            rq.ensureCapacityAndAlignment(12, 4);
+            buf.putInt(DISPOSE_CONFIG);
+            buf.putLong(pConfigInfo);
+            
+            // this call is expected to complete synchronously, so flush now
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
+    }
+    
+    /**
+     * Returns true if the current thread is the OGL QueueFlusher thread.
+     */
+    public static boolean isQueueFlusherThread() {
+        return (Thread.currentThread() == getInstance().flusher.thread);
+    }
+    
+    public void flushNow() {
+        // assert lock.isHeldByCurrentThread();
+        try {
+            flusher.flushNow();
+        } catch (Exception e) {
+            System.err.println("exception in flushNow:");
+            e.printStackTrace();
+        }
+    }
+    
+    public void flushAndInvokeNow(Runnable r) {
+        // assert lock.isHeldByCurrentThread();
+        try {
+            flusher.flushAndInvokeNow(r);
+        } catch (Exception e) {
+            System.err.println("exception in flushAndInvokeNow:");
+            e.printStackTrace();
+        }
+    }
+    
+    private native long flushBuffer(long buf, int limit);
+    
+    private void flushBuffer() {
+        
+        // assert lock.isHeldByCurrentThread();
+        int limit = buf.position();
+        if (limit > 0) {
+            System.out.println("FlushBuffer ---------- invoking RQ native flushBuffer");
+            
+            // process the queue
+            flushBuffer(buf.getAddress(), limit);
+        }
+        // reset the buffer position
+        buf.clear();
+        // clear the set of references, since we no longer need them
+        refSet.clear();
+    }
+    
+    private class QueueFlusher implements Runnable {
+        private boolean needsFlush;
+        private Runnable task;
+        private Error error;
+        private final Thread thread;
+        
+        public QueueFlusher() {
+            String name = "Java2D Queue Flusher";
+            thread = new Thread(ThreadGroupUtils.getRootThreadGroup(),
+                                this, name, 0, false);
+            thread.setDaemon(true);
+            thread.setPriority(Thread.MAX_PRIORITY);
+            thread.start();
+        }
+        
+        public synchronized void flushNow() {
+            // wake up the flusher
+            needsFlush = true;
+            System.out.println("****** QueueFlusher : about to notify flusher thread");
+            notify();
+            
+            // wait for flush to complete
+            while (needsFlush) {
+                try {
+
+                    System.out.println("****** QueueFlusher : waiting for flush to complete"); 
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+            
+            // re-throw any error that may have occurred during the flush
+            if (error != null) {
+                throw error;
+            }
+        }
+        
+        public synchronized void flushAndInvokeNow(Runnable task) {
+            this.task = task;
+            flushNow();
+        }
+        
+        public synchronized void run() {
+            boolean timedOut = false;
+            while (true) {
+                while (!needsFlush) {
+                    try {
+                        timedOut = false;
+                        /*
+                         * Wait until we're woken up with a flushNow() call,
+                         * or the timeout period elapses (so that we can
+                         * flush the queue periodically).
+                         */
+                        wait(100);
+                        /*
+                         * We will automatically flush the queue if the
+                         * following conditions apply:
+                         *   - the wait() timed out
+                         *   - we can lock the queue (without blocking)
+                         *   - there is something in the queue to flush
+                         * Otherwise, just continue (we'll flush eventually).
+                         */
+                        if (!needsFlush && (timedOut = tryLock())) {
+                            if (buf.position() > 0) {
+                                needsFlush = true;
+                            } else {
+                                unlock();
+                            }
+                        }
+                    } catch (InterruptedException e) {
+                    }
+                }
+                try {
+                    // reset the throwable state
+                    error = null;
+                    // flush the buffer now
+
+                    System.out.println("Thread invoking flushBuffer -------------- ");
+                    flushBuffer();
+                    // if there's a task, invoke that now as well
+                    if (task != null) {
+                        task.run();
+                    }
+                } catch (Error e) {
+                    error = e;
+                } catch (Exception x) {
+                    System.err.println("exception in QueueFlusher:");
+                    x.printStackTrace();
+                } finally {
+                    if (timedOut) {
+                        unlock();
+                    }
+                    task = null;
+                    // allow the waiting thread to continue
+                    needsFlush = false;
+                    notify();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderer.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2019, 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.Transparency;
+import java.awt.geom.Path2D;
+import sun.java2d.InvalidPipeException;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.pipe.BufferedRenderPipe;
+import sun.java2d.pipe.ParallelogramPipe;
+import sun.java2d.pipe.RenderQueue;
+import sun.java2d.pipe.SpanIterator;
+import static sun.java2d.pipe.BufferedOpCodes.*;
+
+class MetalRenderer extends BufferedRenderPipe {
+
+    MetalRenderer(RenderQueue rq) {
+        super(rq);
+    }
+
+    @Override
+    protected void validateContext(SunGraphics2D sg2d) {
+        int ctxflags =
+            sg2d.paint.getTransparency() == Transparency.OPAQUE ?
+                MetalContext.SRC_IS_OPAQUE : MetalContext.NO_CONTEXT_FLAGS;
+        MetalSurfaceData dstData;
+        try {
+            dstData = (MetalSurfaceData)sg2d.surfaceData;
+        } catch (ClassCastException e) {
+            throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+        }
+        MetalContext.validateContext(dstData, dstData,
+                                   sg2d.getCompClip(), sg2d.composite,
+                                   null, sg2d.paint, sg2d, ctxflags);
+    }
+
+    @Override
+    protected void validateContextAA(SunGraphics2D sg2d) {
+        int ctxflags = MetalContext.NO_CONTEXT_FLAGS;
+        MetalSurfaceData dstData;
+        try {
+            dstData = (MetalSurfaceData)sg2d.surfaceData;
+        } catch (ClassCastException e) {
+            throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+        }
+        MetalContext.validateContext(dstData, dstData,
+                                   sg2d.getCompClip(), sg2d.composite,
+                                   null, sg2d.paint, sg2d, ctxflags);
+    }
+
+    void copyArea(SunGraphics2D sg2d,
+                  int x, int y, int w, int h, int dx, int dy)
+    {
+        rq.lock();
+        try {
+            int ctxflags =
+                sg2d.surfaceData.getTransparency() == Transparency.OPAQUE ?
+                    MetalContext.SRC_IS_OPAQUE : MetalContext.NO_CONTEXT_FLAGS;
+            MetalSurfaceData dstData;
+            try {
+                dstData = (MetalSurfaceData)sg2d.surfaceData;
+            } catch (ClassCastException e) {
+                throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+            }
+            MetalContext.validateContext(dstData, dstData,
+                                       sg2d.getCompClip(), sg2d.composite,
+                                       null, null, null, ctxflags);
+
+            rq.ensureCapacity(28);
+            buf.putInt(COPY_AREA);
+            buf.putInt(x).putInt(y).putInt(w).putInt(h);
+            buf.putInt(dx).putInt(dy);
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    @Override
+    protected native void drawPoly(int[] xPoints, int[] yPoints,
+                                   int nPoints, boolean isClosed,
+                                   int transX, int transY);
+
+    MetalRenderer traceWrap() {
+        return new Tracer(this);
+    }
+
+    private class Tracer extends MetalRenderer {
+        private MetalRenderer mtlr;
+        Tracer(MetalRenderer mtlr) {
+            super(mtlr.rq);
+            this.mtlr = mtlr;
+        }
+        public ParallelogramPipe getAAParallelogramPipe() {
+            final ParallelogramPipe realpipe = mtlr.getAAParallelogramPipe();
+            return new ParallelogramPipe() {
+                public void fillParallelogram(SunGraphics2D sg2d,
+                                              double ux1, double uy1,
+                                              double ux2, double uy2,
+                                              double x, double y,
+                                              double dx1, double dy1,
+                                              double dx2, double dy2)
+                {
+                    GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram");
+                    realpipe.fillParallelogram(sg2d,
+                                               ux1, uy1, ux2, uy2,
+                                               x, y, dx1, dy1, dx2, dy2);
+                }
+                public void drawParallelogram(SunGraphics2D sg2d,
+                                              double ux1, double uy1,
+                                              double ux2, double uy2,
+                                              double x, double y,
+                                              double dx1, double dy1,
+                                              double dx2, double dy2,
+                                              double lw1, double lw2)
+                {
+                    GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram");
+                    realpipe.drawParallelogram(sg2d,
+                                               ux1, uy1, ux2, uy2,
+                                               x, y, dx1, dy1, dx2, dy2,
+                                               lw1, lw2);
+                }
+            };
+        }
+        protected void validateContext(SunGraphics2D sg2d) {
+            mtlr.validateContext(sg2d);
+        }
+        public void drawLine(SunGraphics2D sg2d,
+                             int x1, int y1, int x2, int y2)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLDrawLine");
+            mtlr.drawLine(sg2d, x1, y1, x2, y2);
+        }
+        public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
+            GraphicsPrimitive.tracePrimitive("OGLDrawRect");
+            mtlr.drawRect(sg2d, x, y, w, h);
+        }
+        protected void drawPoly(SunGraphics2D sg2d,
+                                int[] xPoints, int[] yPoints,
+                                int nPoints, boolean isClosed)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLDrawPoly");
+            mtlr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed);
+        }
+        public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
+            GraphicsPrimitive.tracePrimitive("OGLFillRect");
+            mtlr.fillRect(sg2d, x, y, w, h);
+        }
+        protected void drawPath(SunGraphics2D sg2d,
+                                Path2D.Float p2df, int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLDrawPath");
+            mtlr.drawPath(sg2d, p2df, transx, transy);
+        }
+        protected void fillPath(SunGraphics2D sg2d,
+                                Path2D.Float p2df, int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLFillPath");
+            mtlr.fillPath(sg2d, p2df, transx, transy);
+        }
+        protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
+                                 int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLFillSpans");
+            mtlr.fillSpans(sg2d, si, transx, transy);
+        }
+        public void fillParallelogram(SunGraphics2D sg2d,
+                                      double ux1, double uy1,
+                                      double ux2, double uy2,
+                                      double x, double y,
+                                      double dx1, double dy1,
+                                      double dx2, double dy2)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLFillParallelogram");
+            mtlr.fillParallelogram(sg2d,
+                                   ux1, uy1, ux2, uy2,
+                                   x, y, dx1, dy1, dx2, dy2);
+        }
+        public void drawParallelogram(SunGraphics2D sg2d,
+                                      double ux1, double uy1,
+                                      double ux2, double uy2,
+                                      double x, double y,
+                                      double dx1, double dy1,
+                                      double dx2, double dy2,
+                                      double lw1, double lw2)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram");
+            mtlr.drawParallelogram(sg2d,
+                                   ux1, uy1, ux2, uy2,
+                                   x, y, dx1, dy1, dx2, dy2, lw1, lw2);
+        }
+        public void copyArea(SunGraphics2D sg2d,
+                             int x, int y, int w, int h, int dx, int dy)
+        {
+            GraphicsPrimitive.tracePrimitive("OGLCopyArea");
+            mtlr.copyArea(sg2d, x, y, w, h, dx, dy);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2019, 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.*;
+
+import sun.awt.image.PixelConverter;
+import sun.java2d.SurfaceData;
+
+import java.awt.Composite;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.loops.GraphicsPrimitive;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.metal.MetalLayer;
+import sun.awt.SunHints;
+import sun.java2d.metal.MetalGraphicsConfig;
+import sun.java2d.opengl.CGLGraphicsConfig;
+import sun.java2d.opengl.CGLLayer;
+import sun.java2d.opengl.CGLSurfaceData;
+import sun.java2d.opengl.OGLRenderQueue;
+import sun.lwawt.macosx.CPlatformView;
+import sun.java2d.pipe.hw.AccelSurface;
+import sun.java2d.metal.MetalRenderer;
+import sun.java2d.metal.MetalRenderQueue;
+import sun.java2d.pipe.PixelToParallelogramConverter;
+import sun.java2d.pipe.ParallelogramPipe;
+import sun.java2d.SunGraphics2D;
+
+public class MetalSurfaceData extends SurfaceData
+    implements AccelSurface {
+    //protected final int scale;
+    protected final int width;
+    protected final int height;
+    protected CPlatformView pView;
+    private MetalGraphicsConfig graphicsConfig;
+
+    //private MetalGraphicsConfig graphicsConfig;
+    private int nativeWidth, nativeHeight;
+    protected int type;
+    protected static ParallelogramPipe mtlAAPgramPipe;
+    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,
+                                         boolean isOpaque,
+                                         int width, int height);
+    protected native void clearWindow();
+
+ static {
+        if (!GraphicsEnvironment.isHeadless()) {
+            MetalRenderQueue rq = MetalRenderQueue.getInstance();
+            mtlRenderPipe = new MetalRenderer(rq);  
+
+            mtlAAPgramPipe = mtlRenderPipe.getAAParallelogramPipe();
+
+            mtlTxRenderPipe =
+                new PixelToParallelogramConverter(mtlRenderPipe,
+                                                  mtlRenderPipe,
+                                                  1.0, 0.25, true);
+            MetalBlitLoops.register();
+        }
+    }
+
+    native void validate(int xoff, int yoff, int width, int height, boolean isOpaque);
+
+    private native void initOps(long pConfigInfo, long pPeerData, long layerPtr,
+                                int xoff, int yoff, boolean isOpaque);
+
+    MetalSurfaceData(MetalGraphicsConfig gc, ColorModel cm, int type,
+                     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(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();
+        this.width = width ;// * scale;
+        this.height = height;// * scale;
+
+        graphicsConfig = gc;
+    }
+
+    protected MetalSurfaceData(CPlatformView pView, MetalGraphicsConfig gc,
+                              ColorModel cm, int type, int width, int height)
+    {
+        this(gc, cm, type, width, height);
+        this.pView = pView;
+        this.graphicsConfig = gc;
+
+        // TODO : Check whether we need native config info here
+        long pConfigInfo = gc.getNativeConfigInfo();
+        long pPeerData = 0L;
+        boolean isOpaque = true;
+        if (pView != null) {
+            pPeerData = pView.getAWTView();
+            isOpaque = pView.isOpaque();
+        }
+        // TODO : check initOps logic it is native is OGL
+        initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque);
+    }
+
+    protected MetalSurfaceData(MetalLayer layer, MetalGraphicsConfig gc,
+                             ColorModel cm, int type, int width, int height)
+    {
+        this(gc, cm, type, width, height);
+        this.graphicsConfig = gc;
+
+        long pConfigInfo = gc.getNativeConfigInfo();
+        long layerPtr = 0L;
+        boolean isOpaque = true;
+        if (layer != null) {
+            layerPtr = layer.getPointer();
+            isOpaque = layer.isOpaque();
+        }
+        initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
+    }
+
+    public  GraphicsConfiguration getDeviceConfiguration() {
+        return graphicsConfig; //dummy
+    }
+
+    public static MetalWindowSurfaceData createData(CPlatformView pView) {
+        MetalGraphicsConfig gc = getGC(pView);
+        return new MetalWindowSurfaceData(pView, gc);
+    }
+
+    public static MetalSurfaceData createData(MetalLayer layer) {
+        MetalGraphicsConfig gc = getGC(layer);
+        Rectangle r = layer.getBounds();
+        //return new MetalSurfaceData( gc, gc.getColorModel(), 1, r.width, r.height);
+        return new MetalLayerSurfaceData(layer, gc, r.width, r.height);
+    }
+
+    public static MetalGraphicsConfig getGC(CPlatformView pView) {
+        if (pView != null) {
+            return (MetalGraphicsConfig)pView.getGraphicsConfiguration();
+        } else {
+            // REMIND: this should rarely (never?) happen, but what if
+            // default config is not CGL?
+            GraphicsEnvironment env = GraphicsEnvironment
+                    .getLocalGraphicsEnvironment();
+            GraphicsDevice gd = env.getDefaultScreenDevice();
+            return (MetalGraphicsConfig) gd.getDefaultConfiguration();
+        }
+    }
+
+    public static MetalGraphicsConfig getGC(MetalLayer layer) {
+        return (MetalGraphicsConfig)layer.getGraphicsConfiguration();
+    }
+
+    public void validate() {
+        // Overridden in MetalWindowSurfaceData below
+    }
+
+    public Rectangle getNativeBounds() {
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        rq.lock();
+        try {
+            return new Rectangle(nativeWidth, nativeHeight);
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    public long getNativeResource(int resType) {
+        if (resType == TEXTURE) {
+            return getTextureID();
+        }
+        return 0L;
+    }
+
+    public  Object getDestination() {
+          return this; //dummy
+    }
+
+
+     //Returns one of the surface type constants defined above.
+     
+    public final int getType() {
+        return type;
+    }
+
+     //
+     // If this surface is backed by a texture object, returns the target
+     // for that texture (either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB).
+     /// Otherwise, this method will return zero.
+    public final int getTextureTarget() {
+        return getTextureTarget(getNativeOps());
+    }
+
+    //
+    // If this surface is backed by a texture object, returns the texture ID
+    // for that texture.
+    //Otherwise, this method will return zero.
+    //
+    public final int getTextureID() {
+        return getTextureID(getNativeOps());
+    }
+
+    // Returns the MetalContext for the GraphicsConfig associated with this
+    //surface.   
+    public final MetalContext getContext() {
+        return graphicsConfig.getContext();
+    }
+
+
+
+
+public void validatePipe(SunGraphics2D sg2d) {
+        //TextPipe textpipe;
+        //boolean validated = false;
+
+        // OGLTextRenderer handles both AA and non-AA text, but
+        // only works with the following modes:
+        // (Note: For LCD text we only enter this code path if
+        // canRenderLCDText() has already validated that the mode is
+        // CompositeType.SrcNoEa (opaque color), which will be subsumed
+        // by the CompositeType.SrcNoEa (any color) test below.)
+
+        // Copy block from OGLSurfaceData
+        //textpipe = sg2d.textpipe; //tmp
+
+        PixelToParallelogramConverter txPipe = null;
+        MetalRenderer nonTxPipe = null;
+
+        if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
+            if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
+                if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
+                    txPipe = mtlTxRenderPipe;
+                    nonTxPipe = mtlRenderPipe;
+                }
+            } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
+                //if (OGLPaints.isValid(sg2d)) {
+                    txPipe = mtlTxRenderPipe;
+                    nonTxPipe = mtlRenderPipe;
+                //}
+                // custom paints handled by super.validatePipe() below
+            }
+        } else {
+            if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
+                if (//graphicsConfig.isCapPresent(CAPS_PS30) &&
+                    (sg2d.imageComp == CompositeType.SrcOverNoEa ||
+                     sg2d.imageComp == CompositeType.SrcOver))
+                {
+                    //if (!validated) {
+                        super.validatePipe(sg2d);
+                        //validated = true;
+                    //}
+                    PixelToParallelogramConverter aaConverter =
+                        new PixelToParallelogramConverter(sg2d.shapepipe,
+                                                          mtlAAPgramPipe,
+                                                          1.0/8.0, 0.499,
+                                                          false);
+                    sg2d.drawpipe = aaConverter;
+                    sg2d.fillpipe = aaConverter;
+                    sg2d.shapepipe = aaConverter;
+                } else if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
+                    // install the solid pipes when AA and XOR are both enabled
+                    txPipe = mtlTxRenderPipe;
+                    nonTxPipe = mtlRenderPipe;
+                }
+            }
+            // other cases handled by super.validatePipe() below
+        }
+
+        if (txPipe != null) {
+            if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
+                sg2d.drawpipe = txPipe;
+                sg2d.fillpipe = txPipe;
+            } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
+                sg2d.drawpipe = txPipe;
+                sg2d.fillpipe = nonTxPipe;
+            } else {
+                sg2d.drawpipe = nonTxPipe;
+                sg2d.fillpipe = nonTxPipe;
+            }
+            // Note that we use the transforming pipe here because it
+            // will examine the shape and possibly perform an optimized
+            // operation if it can be simplified.  The simplifications
+            // will be valid for all STROKE and TRANSFORM types.
+            sg2d.shapepipe = txPipe;
+        } else {
+            
+                super.validatePipe(sg2d);
+            
+        }
+
+        // install the text pipe based on our earlier decision
+        //sg2d.textpipe = textpipe;
+
+        // always override the image pipe with the specialized OGL pipe
+        // TODO : We dont override image pipe with MetalImagePipe.
+        // this needs to be implemented.
+        sg2d.imagepipe = imagepipe;
+    }
+
+    public SurfaceData getReplacement() {
+        return this; //dummy
+    }
+
+    /*
+     * TODO : In case of OpenGL their is no getRaster()
+     * implementation in CGLSurfaceData or OGLSurfaceData.
+     * Needs more verification.
+     */
+    public Raster getRaster(int x, int y, int w, int h) {
+        throw new InternalError("not implemented yet");
+        //System.out.println("MetalSurfaceData -- getRaster() not implemented yet");
+    }
+
+    public Rectangle getBounds() {
+        //Rectangle r = pView.getBounds();
+        return new Rectangle(0, 0, width, height);
+    }
+
+    protected void initSurface(final int width, final int height) {
+        MetalRenderQueue rq = MetalRenderQueue.getInstance();
+        rq.lock();
+        try {
+            rq.flushAndInvokeNow(new Runnable() {
+                public void run() {
+                    initSurfaceNow(width, height);
+                }
+            });
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    private void initSurfaceNow(int width, int height) {
+        boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
+        boolean success = false;
+
+        /*switch (type) {
+            case TEXTURE:
+                success = initTexture(getNativeOps(),
+                        isOpaque, isTexNonPow2Available(),
+                        isTexRectAvailable(),
+                        width, height);
+                break;
+
+            case FBOBJECT:
+                success = initFBObject(getNativeOps(),
+                        isOpaque, isTexNonPow2Available(),
+                        isTexRectAvailable(),
+                        width, height);
+                break;
+
+            case FLIP_BACKBUFFER:
+                success = initFlipBackbuffer(getNativeOps());
+                break;
+
+            default:
+                break;
+        }*/
+
+        success = initTexture(getNativeOps(),
+                              isOpaque,
+                              width, height);
+        if (!success) {
+            throw new OutOfMemoryError("can't create offscreen surface");
+        }
+    }
+
+    /**
+     * Creates a SurfaceData object representing the back buffer of a
+     * double-buffered on-screen Window.
+     */
+    /*public static CGLOffScreenSurfaceData createData(CPlatformView pView,
+                                                     Image image, int type) {
+        CGLGraphicsConfig gc = getGC(pView);
+        Rectangle r = pView.getBounds();
+        if (type == FLIP_BACKBUFFER) {
+            return new CGLOffScreenSurfaceData(pView, gc, r.width, r.height,
+                    image, gc.getColorModel(), FLIP_BACKBUFFER);
+        } else {
+            return new CGLVSyncOffScreenSurfaceData(pView, gc, r.width,
+                    r.height, image, gc.getColorModel(), type);
+        }
+    }*/
+
+    /**
+     * Creates a SurfaceData object representing an off-screen buffer (either a
+     * FBO or Texture).
+     */
+    public static MetalOffScreenSurfaceData createData(MetalGraphicsConfig gc,
+                                                     int width, int height, ColorModel cm, Image image, int type) {
+        return new MetalOffScreenSurfaceData(null, gc, width, height, image, cm,
+                type);
+    }
+
+    public static class MetalWindowSurfaceData extends MetalSurfaceData {
+
+        public MetalWindowSurfaceData(CPlatformView pView,
+                                    MetalGraphicsConfig gc) {
+            super(pView, gc, gc.getColorModel(), WINDOW, 0, 0);
+        }
+
+        @Override
+        public SurfaceData getReplacement() {
+            return pView.getSurfaceData();
+        }
+
+        @Override
+        public Rectangle getBounds() {
+            Rectangle r = pView.getBounds();
+            return new Rectangle(0, 0, r.width, r.height);
+        }
+
+        /**
+         * Returns destination Component associated with this SurfaceData.
+         */
+        @Override
+        public Object getDestination() {
+            return pView.getDestination();
+        }
+
+        @Override
+        public void validate() {
+            MetalRenderQueue rq = MetalRenderQueue.getInstance();
+            rq.lock();
+            try {
+                rq.flushAndInvokeNow(new Runnable() {
+                    public void run() {
+                        Rectangle peerBounds = pView.getBounds();
+                        validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque());
+                    }
+                });
+            } finally {
+                rq.unlock();
+            }
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            clearWindow();
+        }
+    }
+
+    public static class MetalLayerSurfaceData extends MetalSurfaceData {
+
+        private MetalLayer layer;
+
+        public MetalLayerSurfaceData(MetalLayer layer, MetalGraphicsConfig gc,
+                                   int width, int height) {
+            super(layer, gc, gc.getColorModel(), RT_TEXTURE, width, height);
+            this.layer = layer;
+            initSurface(this.width, this.height);
+        }
+
+        @Override
+        public SurfaceData getReplacement() {
+            return layer.getSurfaceData();
+        }
+
+        /*@Override
+        boolean isOnScreen() {
+            return true;
+        }*/
+
+        @Override
+        public Rectangle getBounds() {
+            return new Rectangle(width, height);
+        }
+
+        @Override
+        public Object getDestination() {
+            return layer.getDestination();
+        }
+
+        @Override
+        public int getTransparency() {
+            return layer.getTransparency();
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            clearWindow();
+        }
+    }
+
+    public static class MetalOffScreenSurfaceData extends MetalSurfaceData {
+        private Image offscreenImage;
+
+        public MetalOffScreenSurfaceData(CPlatformView pView,
+                                       MetalGraphicsConfig gc, int width, int height, Image image,
+                                       ColorModel cm, int type) {
+            super(pView, gc, cm, type, width, height);
+            offscreenImage = image;
+            initSurface(this.width, this.height);
+        }
+
+        @Override
+        public SurfaceData getReplacement() {
+            return restoreContents(offscreenImage);
+        }
+
+        @Override
+        public Rectangle getBounds() {
+            if (type == FLIP_BACKBUFFER) {
+                Rectangle r = pView.getBounds();
+                return new Rectangle(0, 0, r.width, r.height);
+            } else {
+                return new Rectangle(width, height);
+            }
+        }
+
+        /**
+         * Returns destination Image associated with this SurfaceData.
+         */
+        @Override
+        public Object getDestination() {
+            return offscreenImage;
+        }
+    }
+    // TODO : We have some OGL Mac specific functions, verify their use case
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MetalVolatileSurfaceManager.java	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2018, 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 sun.awt.AWTAccessor;
+import sun.awt.image.SunVolatileImage;
+import sun.awt.image.VolatileSurfaceManager;
+import sun.java2d.SurfaceData;
+import sun.java2d.opengl.OGLSurfaceData;
+
+import java.awt.*;
+import java.awt.image.ColorModel;
+import java.awt.peer.ComponentPeer;
+
+public class MetalVolatileSurfaceManager extends VolatileSurfaceManager {
+    //private final boolean accelerationEnabled;
+    public MetalVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
+        super(vImg, context);
+        
+        /*
+         * We will attempt to accelerate this image only under the
+         * following conditions:
+         *   - the image is not bitmask AND the GraphicsConfig supports the FBO
+         *     extension
+         */
+        /*int transparency = vImg.getTransparency();
+         MetalGraphicsConfig gc = (MetalGraphicsConfig) vImg.getGraphicsConfig();
+         accelerationEnabled = gc.isCapPresent(CAPS_EXT_FBOBJECT)
+         && transparency != Transparency.BITMASK;*/
+    }
+    
+    protected boolean isAccelerationEnabled() {
+        return true;
+    }
+    
+    /**
+     * Create a FBO-based SurfaceData object (or init the backbuffer
+     * of an existing window if this is a double buffered GraphicsConfig)
+     */
+    protected SurfaceData initAcceleratedSurface() {
+        SurfaceData sData = null;
+        Component comp = vImg.getComponent();
+        final AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor();
+        final ComponentPeer peer = (comp != null) ? acc.getPeer(comp) : null;
+        
+        try {
+            /*boolean createVSynced = false;
+             boolean forceback = false;
+             if (context instanceof Boolean) {
+             forceback = ((Boolean)context).booleanValue();
+             if (forceback && peer instanceof BackBufferCapsProvider) {
+             BackBufferCapsProvider provider =
+             (BackBufferCapsProvider)peer;
+             BufferCapabilities caps = provider.getBackBufferCaps();
+             if (caps instanceof ExtendedBufferCapabilities) {
+             ExtendedBufferCapabilities ebc =
+             (ExtendedBufferCapabilities)caps;
+             if (ebc.getVSync() == VSYNC_ON &&
+             ebc.getFlipContents() == COPIED)
+             {
+             createVSynced = true;
+             forceback = false;
+             }
+             }
+             }
+             }*/
+            
+            /*if (forceback) {
+             // peer must be non-null in this case
+             // TODO: modify parameter to delegate
+             //                sData = CGLSurfaceData.createData(peer, vImg, FLIP_BACKBUFFER);
+             } else {*/
+            MetalGraphicsConfig gc =
+            (MetalGraphicsConfig)vImg.getGraphicsConfig();
+            ColorModel cm = gc.getColorModel(vImg.getTransparency());
+            int type = vImg.getForcedAccelSurfaceType();
+            // if acceleration type is forced (type != UNDEFINED) then
+            // use the forced type, otherwise choose FBOBJECT
+            //if (type == OGLSurfaceData.UNDEFINED) {
+            //type = OGLSurfaceData.FBOBJECT;
+            //}
+            //if (createVSynced) {
+            /*
+             * TODO: modify parameter to delegate, this TODO is
+             * present in OGL also
+             */
+            //                  sData = CGLSurfaceData.createData(peer, vImg, type);
+            //} else {
+            sData = MetalSurfaceData.createData(gc,
+                                                vImg.getWidth(),
+                                                vImg.getHeight(),
+                                                cm, vImg, type);
+            //}
+            //}
+        } catch (NullPointerException ex) {
+            sData = null;
+        } catch (OutOfMemoryError er) {
+            sData = null;
+        }
+        
+        return sData;
+    }
+    
+    @Override
+    public void initContents() {
+        // TODO : Check what is special case of TEXTURE
+        //if (vImg.getForcedAccelSurfaceType() != OGLSurfaceData.TEXTURE) {
+        super.initContents();
+        //}
+    }
+}
--- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Mon Mar 11 14:05:27 2019 +0530
@@ -51,6 +51,7 @@
 import sun.java2d.Surface;
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.OGLContext.OGLContextCaps;
+import sun.java2d.metal.MetalLayer;
 import sun.java2d.pipe.hw.AccelSurface;
 import sun.java2d.pipe.hw.AccelTypedVolatileImage;
 import sun.java2d.pipe.hw.ContextCapabilities;
@@ -269,6 +270,11 @@
     }
 
     @Override
+    public SurfaceData createSurfaceData(MetalLayer layer) {
+        return null;
+    }
+
+    @Override
     public Image createAcceleratedImage(Component target,
                                         int width, int height)
     {
--- a/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -55,6 +55,7 @@
 
 import sun.java2d.SunGraphics2D;
 import sun.java2d.opengl.OGLRenderQueue;
+import sun.java2d.metal.MetalRenderQueue;
 import sun.java2d.pipe.Region;
 
 import sun.util.logging.PlatformLogger;
@@ -1418,15 +1419,39 @@
     }
 
     protected static final void flushOnscreenGraphics(){
-        final OGLRenderQueue rq = OGLRenderQueue.getInstance();
-        rq.lock();
-        try {
-            rq.flushNow();
-        } finally {
-            rq.unlock();
+
+        // Check for metal
+        boolean isMetal = false;
+        String str = System.getProperty("sun.java2d.metal");
+
+        if (str != null) {
+           //System.out.println("Property : sun.java2d.metal=" + str);
+            if (str.equals("true")) {
+                isMetal = true;
+            }
+        }
+
+        if (isMetal) {
+            final MetalRenderQueue rq = MetalRenderQueue.getInstance();
+            rq.lock();
+            try {
+                rq.flushNow();
+            } finally {
+                rq.unlock();
+            }
+        } else {
+
+            final OGLRenderQueue rq = OGLRenderQueue.getInstance();
+            rq.lock();
+            try {
+                rq.flushNow();
+            } finally {
+                rq.unlock();
+            }
         }
     }
 
+
     /**
      * Used by ContainerPeer to skip all the paint events during layout.
      *
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -33,11 +33,15 @@
 
 import sun.awt.CGraphicsConfig;
 import sun.awt.CGraphicsEnvironment;
+import sun.java2d.metal.MetalLayer;
+import sun.java2d.metal.MetalSurfaceData;
 import sun.lwawt.LWWindowPeer;
 
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLLayer;
 import sun.java2d.opengl.CGLSurfaceData;
+import sun.java2d.NullSurfaceData;
+
 
 public class CPlatformView extends CFRetainedResource {
     private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr);
@@ -49,25 +53,54 @@
     private LWWindowPeer peer;
     private SurfaceData surfaceData;
     private CGLLayer windowLayer;
+    private MetalLayer windowMetalLayer; //hack : will be null if opengl is used
+    //private CFRetainedResource windowLayer;
+    //Todo: Have to verify how we can replace CGL layer with more common CFRetaindedResource
     private CPlatformResponder responder;
 
     public CPlatformView() {
         super(0, true);
     }
 
+    
     public void initialize(LWWindowPeer peer, CPlatformResponder responder) {
         initializeBase(peer, responder);
 
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            this.windowLayer = createCGLayer();
+            
+            if (isMetalSystemProperty()) {
+                this.windowMetalLayer = createMetalLayer();
+            } else {
+                this.windowLayer = createCGLayer();
+            }
         }
         setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr()));
+
+        // TODO : We should not simply validate view directly here.
+        //if (isMetalSystemProperty()) {
+            //windowMetalLayer.validate(getAWTView());
+        //}
     }
-
+    
+    private boolean isMetalSystemProperty() {
+        String str = System.getProperty("sun.java2d.metal");
+        
+        if (str != null) {
+            System.out.println("Property : sun.java2d.metal=" + str);
+            if (str.equals("true")) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     public CGLLayer createCGLayer() {
         return new CGLLayer(peer);
     }
 
+    public MetalLayer createMetalLayer() {
+        return new MetalLayer(peer);
+    }
     protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) {
         this.peer = peer;
         this.responder = responder;
@@ -87,6 +120,11 @@
      */
     public void setBounds(int x, int y, int width, int height) {
         execute(ptr->CWrapper.NSView.setFrame(ptr, x, y, width, height));
+
+        // TODO : Check the use case that why below code is added.
+        //if (windowMetalLayer != null) {
+                //windowMetalLayer.validate(getAWTView());
+            //}
     }
 
     // REMIND: CGLSurfaceData expects top-level's size
@@ -107,7 +145,20 @@
     // ----------------------------------------------------------------------
     public SurfaceData replaceSurfaceData() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            surfaceData = windowLayer.replaceSurfaceData();
+            
+            if (isMetalSystemProperty()) {
+                surfaceData = windowMetalLayer.replaceSurfaceData();
+
+                // TODO : Why we are checking about NullSurfaceData here
+                //if (surfaceData != NullSurfaceData.theInstance) {
+                    //validateSurface();
+                    //windowMetalLayer.drawInMetalContext(getAWTView());
+                //}
+        
+            } else {
+                surfaceData = windowLayer.replaceSurfaceData();
+            }
+
         } else {
             if (surfaceData == null) {
                 CGraphicsConfig graphicsConfig = (CGraphicsConfig)getGraphicsConfiguration();
@@ -120,8 +171,16 @@
     }
 
     private void validateSurface() {
+
         if (surfaceData != null) {
-            ((CGLSurfaceData)surfaceData).validate();
+            // TODO : Why we are validating with View here
+            if (isMetalSystemProperty()) {
+                //((MetalSurfaceData)surfaceData).validate();
+                //windowMetalLayer.validate(getAWTView());
+                ((MetalSurfaceData)surfaceData).validate();
+            } else {
+                ((CGLSurfaceData)surfaceData).validate();
+            }
         }
     }
 
@@ -136,14 +195,22 @@
     @Override
     public void dispose() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            windowLayer.dispose();
+            if (isMetalSystemProperty()) {
+                windowMetalLayer.dispose();
+            } else {
+                windowLayer.dispose();
+            }
         }
         super.dispose();
     }
 
     public long getWindowLayerPtr() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            return windowLayer.getPointer();
+            if (isMetalSystemProperty()) {
+                return windowMetalLayer.getPointer();
+            } else {
+                return windowLayer.getPointer();
+            }
         } else {
             return 0;
         }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Mar 11 14:05:27 2019 +0530
@@ -62,6 +62,7 @@
 import sun.awt.AWTAccessor.ComponentAccessor;
 import sun.awt.AWTAccessor.WindowAccessor;
 import sun.java2d.SurfaceData;
+import sun.java2d.metal.MetalSurfaceData;
 import sun.java2d.opengl.CGLSurfaceData;
 import sun.lwawt.LWLightweightFramePeer;
 import sun.lwawt.LWToolkit;
@@ -1056,6 +1057,8 @@
         SurfaceData surfaceData = getSurfaceData();
         if (surfaceData instanceof CGLSurfaceData) {
             ((CGLSurfaceData)surfaceData).validate();
+        } else if (surfaceData instanceof MetalSurfaceData) {
+            ((MetalSurfaceData)surfaceData).validate();
         }
     }
 
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -29,6 +29,7 @@
 
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 #import <QuartzCore/CATransaction.h>
+#import <QuartzCore/CAMetalLayer.h>
 
 @implementation AWTSurfaceLayers
 
@@ -69,8 +70,10 @@
 
 // Updates back buffer size of the layer if it's an OpenGL layer
 // including all OpenGL sublayers
+// TODO : Added check for CAMetalLayer also but this needs to be verified.
 + (void) repaintLayersRecursively:(CALayer*)aLayer {
-    if ([aLayer isKindOfClass:[CAOpenGLLayer class]]) {
+    if ([aLayer isKindOfClass:[CAOpenGLLayer class]] ||
+        [aLayer isKindOfClass:[CAMetalLayer class]]) {
         [aLayer setNeedsDisplay];
     }
     for(CALayer *child in aLayer.sublayers) {
@@ -92,7 +95,7 @@
 
 /*
  * Class:     sun_lwawt_macosx_CPlatformComponent
- * Method:    nativeCreateLayer
+ * Method:    nativeCreateComponent
  * Signature: ()J
  */
 JNIEXPORT jlong JNICALL
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -66,6 +66,13 @@
 @synthesize cglLayer;
 @synthesize mouseIsOver;
 
+/*
+ * TODO : Eventhough the name of variable is cgllayer,
+ * we are setting common CALayer properties, so we might not
+ * to add one more variable for CAMetalLayer. Also have
+ * to verify REMOTE_LAYER use case, if it is need then we
+ * need to add CAMetalLayer specific logic.
+ */
 // Note: Must be called on main (AppKit) thread only
 - (id) initWithRect: (NSRect) rect
        platformView: (jobject) cPlatformView
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef MetalGraphicsConfig_h_Included
+#define MetalGraphicsConfig_h_Included
+
+#import "jni.h"
+//#import "J2D_GL/gl.h"
+#import <Metal/Metal.h>
+//@import Metal;
+//#import "MetalSurfaceData.h"
+//#import "OGLContext.h"
+#import <Cocoa/Cocoa.h>
+
+@interface MetalGraphicsConfigUtil : NSObject {}
++ (void) _getMetalConfigInfo: (NSMutableArray *)argValue;
+@end
+
+// REMIND: Using an NSOpenGLPixelBuffer as the scratch surface has been
+// problematic thus far (seeing garbage and flickering when switching
+// between an NSView and the scratch surface), so the following enables
+// an alternate codepath that uses a hidden NSWindow/NSView as the scratch
+// surface, for the purposes of making a context current in certain
+// situations.  It appears that calling [NSOpenGLContext setView] too
+// frequently contributes to the bad behavior, so we should try to avoid
+// switching to the scratch surface whenever possible.
+
+/* Do we need this if we are using all off-screen drawing ? */
+#define USE_NSVIEW_FOR_SCRATCH 1
+
+/* Uncomment to have an additional CAOGLLayer instance tied to
+ * each instance, which can be used to test remoting the layer
+ * to an out of process window. The additional layer is needed
+ * because a layer can only be attached to one context (view/window).
+ * This is only for testing purposes and can be removed if/when no
+ * longer needed.
+ */
+//#define REMOTELAYER 1
+
+#ifdef REMOTELAYER
+#import <JavaRuntimeSupport/JRSRemoteLayer.h>
+#import <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
+#import <sys/socket.h>
+#import <sys/un.h>
+
+extern mach_port_t JRSRemotePort;
+extern int remoteSocketFD;
+extern void sendLayerID(int layerID);
+
+#endif /* REMOTELAYER */
+
+
+/**
+ * The CGLGraphicsConfigInfo structure contains information specific to a
+ * given CGLGraphicsConfig (pixel format).
+ *
+ *     jint screen;
+ * The screen and PixelFormat for the associated CGLGraphicsConfig.
+ *
+ *     NSOpenGLPixelFormat *pixfmt;
+ * The pixel format of the native NSOpenGL context.
+ *
+ *     OGLContext *context;
+ * The context associated with this CGLGraphicsConfig.
+ */
+typedef struct _MetalGraphicsConfigInfo {
+    jint                 screen;
+    id<MTLDevice>        device;
+    id<MTLCommandQueue>  commandQueue;
+    //MTLLibrary     *defaultLibrary;
+} MetalGraphicsConfigInfo;
+
+/**
+ * The CGLCtxInfo structure contains the native CGLContext information
+ * required by and is encapsulated by the platform-independent OGLContext
+ * structure.
+ *
+ *     NSOpenGLContext *context;
+ * The core native NSOpenGL context.  Rendering commands have no effect until
+ * a context is made current (active).
+ *
+ *     NSOpenGLPixelBuffer *scratchSurface;
+ * The scratch surface id used to make a context current when we do
+ * not otherwise have a reference to an OpenGL surface for the purposes of
+ * making a context current.
+ */
+/*typedef struct _CGLCtxInfo {
+    NSOpenGLContext     *context;
+#if USE_NSVIEW_FOR_SCRATCH
+    NSView              *scratchSurface;
+#else
+    NSOpenGLPixelBuffer *scratchSurface;
+#endif
+} CGLCtxInfo;*/
+
+#endif /* MetalGraphicsConfig_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#import "sun_java2d_metal_MetalGraphicsConfig.h"
+
+#import "MetalGraphicsConfig.h"
+//#import "CGLSurfaceData.h"
+#import "ThreadUtilities.h"
+
+#import <stdlib.h>
+#import <string.h>
+#import <ApplicationServices/ApplicationServices.h>
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+
+#pragma mark -
+#pragma mark "--- Mac OS X specific methods for Metal pipeline ---"
+
+/**
+ * Disposes all memory and resources associated with the given
+ * CGLGraphicsConfigInfo (including its native OGLContext data).
+ */
+/*void
+OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLGC_DestroyOGLGraphicsConfig");
+
+    CGLGraphicsConfigInfo *cglinfo =
+        (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+    if (cglinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "OGLGC_DestroyOGLGraphicsConfig: info is null");
+        return;
+    }
+
+    OGLContext *oglc = (OGLContext*)cglinfo->context;
+    if (oglc != NULL) {
+        OGLContext_DestroyContextResources(oglc);
+
+        CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+        if (ctxinfo != NULL) {
+            NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+            [NSOpenGLContext clearCurrentContext];
+            [ctxinfo->context clearDrawable];
+            [ctxinfo->context release];
+            if (ctxinfo->scratchSurface != 0) {
+                [ctxinfo->scratchSurface release];
+            }
+            [pool drain];
+            free(ctxinfo);
+            oglc->ctxInfo = NULL;
+        }
+        cglinfo->context = NULL;
+    }
+
+    free(cglinfo);
+}*/
+
+#pragma mark -
+#pragma mark "--- MetalGraphicsConfig methods ---"
+
+/*#ifdef REMOTELAYER
+mach_port_t JRSRemotePort;
+int remoteSocketFD = -1;
+
+static void *JRSRemoteThreadFn(void *data) {
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+    // Negotiate a unix domain socket to communicate the
+    // out of band data: to read the mach port server name, and
+    // subsequently write out the layer ID.
+    static char* sock_path = "/tmp/JRSRemoteDemoSocket";
+    struct sockaddr_un address;
+    int  socket_fd, nbytes;
+    int BUFLEN = 256;
+    char buffer[BUFLEN];
+
+    remoteSocketFD = socket(PF_LOCAL, SOCK_STREAM, 0);
+    if (remoteSocketFD < 0) {
+        NSLog(@"socket() failed");
+        return NULL;
+    }
+    memset(&address, 0, sizeof(struct sockaddr_un));
+    address.sun_family = AF_UNIX;
+    memcpy(address.sun_path, sock_path, strlen(sock_path)+1);
+    int tries=0, status=-1;
+    while (status !=0 && tries<600) {
+        status = connect(remoteSocketFD, (struct sockaddr *) &address,
+                         sizeof(struct sockaddr_un));
+        if (status != 0) {
+            tries++;
+            NSLog(@"connection attempt %d failed.", tries);
+            usleep(5000000);
+        }
+    }
+    if (status != 0) {
+        NSLog(@"failed to connect");
+        return NULL;
+    }
+    nbytes = read(remoteSocketFD, buffer, BUFLEN);
+    NSString* serverString = [[NSString alloc] initWithUTF8String:buffer];
+    CFRetain(serverString);
+    NSLog(@"Read server name %@", serverString);
+    JRSRemotePort = [JRSRenderServer recieveRenderServer:serverString];
+    NSLog(@"Read server port %d", JRSRemotePort);
+
+    [pool drain];
+    return NULL;
+}
+
+void sendLayerID(int layerID) {
+    if (JRSRemotePort == 0 || remoteSocketFD < 0) {
+        NSLog(@"No connection to send ID");
+        return;
+    }
+    int BUFLEN = 256;
+    char buffer[BUFLEN];
+    snprintf(buffer, BUFLEN, "%d", layerID);
+    write(remoteSocketFD, buffer, BUFLEN);
+}
+#endif*/  /* REMOTELAYER */
+
+/**
+ * This is a globally shared context used when creating textures.  When any
+ * new contexts are created, they specify this context as the "share list"
+ * context, which means any texture objects created when this shared context
+ * is current will be available to any other context in any other thread.
+ */
+//NSOpenGLContext *sharedContext = NULL;
+//NSOpenGLPixelFormat *sharedPixelFormat = NULL;
+
+/**
+ * Attempts to initialize CGL and the core OpenGL library.
+ */
+/*JNIEXPORT jboolean JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL
+    (JNIEnv *env, jclass cglgc)
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_initCGL");
+
+    if (!OGLFuncs_OpenLibrary()) {
+        return JNI_FALSE;
+    }
+
+    if (!OGLFuncs_InitPlatformFuncs() ||
+        !OGLFuncs_InitBaseFuncs() ||
+        !OGLFuncs_InitExtFuncs())
+    {
+        OGLFuncs_CloseLibrary();
+        return JNI_FALSE;
+    }
+#ifdef REMOTELAYER
+    pthread_t jrsRemoteThread;
+    pthread_create(&jrsRemoteThread, NULL, JRSRemoteThreadFn, NULL);
+#endif
+    return JNI_TRUE;
+}*/
+
+
+/**
+ * Determines whether the CGL pipeline can be used for a given GraphicsConfig
+ * provided its screen number and visual ID.  If the minimum requirements are
+ * met, the native CGLGraphicsConfigInfo structure is initialized for this
+ * GraphicsConfig with the necessary information (pixel format, etc.)
+ * and a pointer to this structure is returned as a jlong.  If
+ * initialization fails at any point, zero is returned, indicating that CGL
+ * cannot be used for this GraphicsConfig (we should fallback on an existing
+ * 2D pipeline).
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MetalGraphicsConfig_getMetalConfigInfo
+    (JNIEnv *env, jclass metalgc,
+     jint displayID, jint pixfmt)
+{
+    //fprintf(stdout, "Jay : MetalGraphicsConfig_getMetalConfigInfo\n");fflush(stdout);
+  jlong ret = 0L;
+  JNF_COCOA_ENTER(env);
+  NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:2];
+  [retArray addObject: [NSNumber numberWithInt: (int)displayID]];
+  [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]];
+  //if ([NSThread isMainThread]) {
+      //[GraphicsConfigUtil _getCGLConfigInfo: retArray];
+  //} else {
+      [MetalGraphicsConfigUtil performSelectorOnMainThread: @selector(_getMetalConfigInfo:) withObject: retArray waitUntilDone: YES];
+  //}
+  NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0];
+  ret = (jlong)[num longValue];
+  JNF_COCOA_EXIT(env);
+  return ret;
+}
+
+@implementation MetalGraphicsConfigUtil
++ (void) _getMetalConfigInfo: (NSMutableArray *)argValue {
+    AWT_ASSERT_APPKIT_THREAD;
+
+    //fprintf(stdout, "Jay : MetalGraphicsConfig_MetalGraphicsConfigUtil\n");fflush(stdout);
+    jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
+    jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue];
+    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
+    [argValue removeAllObjects];
+
+    //J2dRlsTraceLn(J2D_TRACE_INFO, "MetalGraphicsConfig_getMetalConfigInfo");
+
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+    /*CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt;
+    if (sharedContext == NULL) {
+        if (glMask == 0) {
+            glMask = CGDisplayIDToOpenGLDisplayMask(displayID);
+        }
+
+        NSOpenGLPixelFormatAttribute attrs[] = {
+            NSOpenGLPFAAllowOfflineRenderers,
+            NSOpenGLPFAClosestPolicy,
+            NSOpenGLPFAWindow,
+            NSOpenGLPFAPixelBuffer,
+            NSOpenGLPFADoubleBuffer,
+            NSOpenGLPFAColorSize, 32,
+            NSOpenGLPFAAlphaSize, 8,
+            NSOpenGLPFADepthSize, 16,
+            NSOpenGLPFAScreenMask, glMask,
+            0
+        };
+
+        sharedPixelFormat =
+            [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+        if (sharedPixelFormat == nil) {
+            J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLPixelFormat is NULL");
+            [argValue addObject: [NSNumber numberWithLong: 0L]];
+            return;
+        }
+
+        sharedContext =
+            [[NSOpenGLContext alloc]
+                initWithFormat:sharedPixelFormat
+                shareContext: NULL];
+        if (sharedContext == nil) {
+            J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: shared NSOpenGLContext is NULL");
+            [argValue addObject: [NSNumber numberWithLong: 0L]];
+            return;
+        }
+    }*/
+    id<MTLDevice> device = MTLCreateSystemDefaultDevice();
+    
+    id<MTLCommandQueue> commandQueue = [device newCommandQueue];
+    
+    // Jay : Looks like no need to create MetaLayer here and we were creating
+    // scratch surface only to make OGL context current. So no need to create any layer for
+    // Metal. Just create device and commandQueue for Metal.
+    //defaultLibrary = [device newDefaultLibrary];
+    /*CAMetalLayer *metalLayer = [CAMetalLayer layer];
+    metalLayer.device = device;
+    metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;*/
+    
+#if USE_NSVIEW_FOR_SCRATCH
+    /*NSRect contentRect = NSMakeRect(0, 0, 64, 64);
+    NSWindow *window =
+        [[NSWindow alloc]
+            initWithContentRect: contentRect
+            styleMask: NSBorderlessWindowMask
+            backing: NSBackingStoreBuffered
+            defer: false];
+    if (window == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSWindow is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+    NSView *scratchSurface =
+        [[NSView alloc]
+            initWithFrame: contentRect];
+    if (scratchSurface == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: NSView is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    [window setContentView: scratchSurface];*/
+#else
+    /*NSOpenGLPixelBuffer *scratchSurface =
+        [[NSOpenGLPixelBuffer alloc]
+            initWithTextureTarget:GL_TEXTURE_2D
+            textureInternalFormat:GL_RGB
+            textureMaxMipMapLevel:0
+            pixelsWide:64
+            pixelsHigh:64];*/
+#endif
+
+    /*NSOpenGLContext *context =
+        [[NSOpenGLContext alloc]
+            initWithFormat: sharedPixelFormat
+            shareContext: sharedContext];
+    if (context == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: NSOpenGLContext is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+    GLint contextVirtualScreen = [context currentVirtualScreen];*/
+#if USE_NSVIEW_FOR_SCRATCH
+    //[context setView: scratchSurface];
+    // Jay : no need of scratch layer for metal
+    //metalLayer.frame = scratchSurface.layer.frame;
+    //[scratchSurface.layer addSublayer: metalLayer];
+#else
+    /*[context
+        setPixelBuffer: scratchSurface
+        cubeMapFace:0
+        mipMapLevel:0
+        currentVirtualScreen: contextVirtualScreen];*/
+#endif
+    /*[context makeCurrentContext];
+
+    // get version and extension strings
+    const unsigned char *versionstr = j2d_glGetString(GL_VERSION);
+    if (!OGLContext_IsVersionSupported(versionstr)) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL 1.2 is required");
+        [NSOpenGLContext clearCurrentContext];
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr);
+
+    jint caps = CAPS_EMPTY;
+    OGLContext_GetExtensionInfo(env, &caps);
+
+    GLint value = 0;
+    [sharedPixelFormat
+        getValues: &value
+        forAttribute: NSOpenGLPFADoubleBuffer
+        forVirtualScreen: contextVirtualScreen];
+    if (value != 0) {
+        caps |= CAPS_DOUBLEBUFFERED;
+    }
+
+    J2dRlsTraceLn1(J2D_TRACE_INFO,
+                   "CGLGraphicsConfig_getCGLConfigInfo: db=%d",
+                   (caps & CAPS_DOUBLEBUFFERED) != 0);*/
+
+    // remove before shipping (?)
+#if 1
+    /*[sharedPixelFormat
+        getValues: &value
+        forAttribute: NSOpenGLPFAAccelerated
+        forVirtualScreen: contextVirtualScreen];
+    if (value == 0) {
+        [sharedPixelFormat
+            getValues: &value
+            forAttribute: NSOpenGLPFARendererID
+            forVirtualScreen: contextVirtualScreen];
+        fprintf(stderr, "WARNING: GL pipe is running in software mode (Renderer ID=0x%x)\n", (int)value);
+    }*/
+#endif
+
+    // 0: the buffers are swapped with no regard to the vertical refresh rate
+    // 1: the buffers are swapped only during the vertical retrace
+    /*GLint params = swapInterval;
+    [context setValues: &params forParameter: NSOpenGLCPSwapInterval];
+
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)malloc(sizeof(CGLCtxInfo));
+    if (ctxinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for ctxinfo");
+        [NSOpenGLContext clearCurrentContext];
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(ctxinfo, 0, sizeof(CGLCtxInfo));
+    ctxinfo->context = context;
+    ctxinfo->scratchSurface = scratchSurface;
+
+    OGLContext *oglc = (OGLContext *)malloc(sizeof(OGLContext));
+    if (oglc == 0L) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "CGLGC_InitOGLContext: could not allocate memory for oglc");
+        [NSOpenGLContext clearCurrentContext];
+        free(ctxinfo);
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(oglc, 0, sizeof(OGLContext));
+    oglc->ctxInfo = ctxinfo;
+    oglc->caps = caps;*/
+
+    // create the CGLGraphicsConfigInfo record for this config
+    MetalGraphicsConfigInfo *metalinfo = (MetalGraphicsConfigInfo *)malloc(sizeof(MetalGraphicsConfigInfo));
+    if (metalinfo == NULL) {
+        //J2dRlsTraceLn(J2D_TRACE_ERROR, "MetalGraphicsConfig_getMetalConfigInfo: could not allocate memory for cglinfo");
+        //[NSOpenGLContext clearCurrentContext];
+        //free(oglc);
+        //free(ctxinfo);
+        //[argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(metalinfo, 0, sizeof(MetalGraphicsConfigInfo));
+    metalinfo->screen = displayID;
+    metalinfo->device = device;
+    metalinfo->commandQueue = commandQueue;
+
+    //[NSOpenGLContext clearCurrentContext];
+    [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(metalinfo)]];
+    [pool drain];
+}
+@end //GraphicsConfigUtil
+
+/*JNIEXPORT jint JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities
+    (JNIEnv *env, jclass cglgc, jlong configInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getOGLCapabilities");
+
+    CGLGraphicsConfigInfo *cglinfo =
+        (CGLGraphicsConfigInfo *)jlong_to_ptr(configInfo);
+    if ((cglinfo == NULL) || (cglinfo->context == NULL)) {
+        return CAPS_EMPTY;
+    } else {
+        return cglinfo->context->caps;
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize
+    (JNIEnv *env, jclass cglgc)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_nativeGetMaxTextureSize");
+
+    __block int max = 0;
+
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+        [sharedContext makeCurrentContext];
+        j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+        [NSOpenGLContext clearCurrentContext];
+    }];
+
+    return (jint)max;
+}*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef MetalLayer_h_Included
+#define MetalLayer_h_Included
+
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+#import <QuartzCore/CAMetalLayer.h>
+#import <Metal/Metal.h>
+
+
+@interface MetalLayer : CAMetalLayer
+{
+@private
+    JNFWeakJObjectWrapper *javaLayer;
+
+    // intermediate buffer, used the RQ lock to synchronize
+    id<MTLTexture> mtlTexture;
+    //GLenum target;
+    float textureWidth;
+    float textureHeight;
+#ifdef REMOTELAYER
+    //CGLLayer *parentLayer;
+    //CGLLayer *remoteLayer;
+    //NSObject<JRSRemoteLayer> *jrsRemoteLayer;
+#endif /* REMOTELAYER */
+}
+
+@property (nonatomic, retain) JNFWeakJObjectWrapper *javaLayer;
+@property (readwrite, assign) float textureWidth;
+@property (readwrite, assign) float textureHeight;
+@property (readwrite, assign) id<MTLTexture> mtlTexture;
+@property (readwrite, assign) id<MTLLibrary> mtlLibrary;
+@property (readwrite, assign) MTLRenderPipelineDescriptor* mtlRenderPipelineDescriptor;
+@property (readwrite, assign) id<MTLRenderPipelineState> renderPipelineState;
+//@property (readwrite, assign) id<MTLBuffer> LineVertexBuffer;
+//@property (readwrite, assign) id<MTLBuffer> QuadVertexBuffer;
+#ifdef REMOTELAYER
+//@property (nonatomic, retain) CGLLayer *parentLayer;
+//@property (nonatomic, retain) CGLLayer *remoteLayer;
+//@property (nonatomic, retain) NSObject<JRSRemoteLayer> *jrsRemoteLayer;
+#endif
+
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)javaLayer;
+- (void) blitTexture;
+@end
+
+
+// dummy for PoC purpose
+void MetalLayer_drawLine(float x1, float y1, float x2, float y2);
+void MetalLayer_setColor(int color);
+
+#endif /* MetalLayer_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#import "MetalGraphicsConfig.h"
+#import "MetalLayer.h"
+#import "shaders/MetalShaderTypes.h"
+#import "ThreadUtilities.h"
+#import "LWCToolkit.h"
+#import "MetalSurfaceData.h"
+#import "VertexDataManager.h"
+
+
+//extern NSOpenGLPixelFormat *sharedPixelFormat;
+//extern NSOpenGLContext *sharedContext;
+
+@implementation MetalLayer
+
+@synthesize javaLayer;
+@synthesize mtlTexture;
+//@synthesize target;
+@synthesize textureWidth;
+@synthesize textureHeight;
+@synthesize mtlLibrary;
+@synthesize mtlRenderPipelineDescriptor;
+@synthesize renderPipelineState;
+//@synthesize LineVertexBuffer;
+//@synthesize QuadVertexBuffer;
+#ifdef REMOTELAYER
+//@synthesize parentLayer;
+//@synthesize remoteLayer;
+//@synthesize jrsRemoteLayer;
+#endif
+
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer;
+{
+AWT_ASSERT_APPKIT_THREAD;
+    // Initialize ourselves
+    self = [super init];
+    if (self == nil) return self;
+
+    self.javaLayer = layer;
+
+    // NOTE: async=YES means that the layer is re-cached periodically
+    //self.displaySyncEnabled = NO;
+    self.contentsGravity = kCAGravityTopLeft;
+    //Layer backed view
+    //self.needsDisplayOnBoundsChange = YES;
+    //self.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
+
+    //fprintf(stdout, "MetalLayer_initWithJavaLayer\n");fflush(stdout);
+    //Disable CALayer's default animation
+    NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
+                                    [NSNull null], @"anchorPoint",
+                                    [NSNull null], @"bounds",
+                                    [NSNull null], @"contents",
+                                    [NSNull null], @"contentsScale",
+                                    [NSNull null], @"onOrderIn",
+                                    [NSNull null], @"onOrderOut",
+                                    [NSNull null], @"position",
+                                    [NSNull null], @"sublayers",
+                                    nil];
+    self.actions = actions;
+    [actions release];
+
+    //textureID = 0; // texture will be created by rendering pipe
+    mtlTexture = NULL;
+    //target = 0;
+
+    return self;
+}
+
+- (void) dealloc {
+    self.javaLayer = nil;
+    [super dealloc];
+
+    VertexDataManager_freeAllPrimitives();
+}
+
+/*
+- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
+    return CGLRetainPixelFormat(sharedPixelFormat.CGLPixelFormatObj);
+}
+
+- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+    CGLContextObj contextObj = NULL;
+    CGLCreateContext(pixelFormat, sharedContext.CGLContextObj, &contextObj);
+    return contextObj;
+}*/
+
+// use texture (intermediate buffer) as src and blit it to the layer
+/*- (void) blitTexture
+{
+    if (textureID == 0) {
+        return;
+    }
+
+    glEnable(target);
+    glBindTexture(target, textureID);
+
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // srccopy
+
+    float swid = 1.0f, shgt = 1.0f;
+    if (target == GL_TEXTURE_RECTANGLE_ARB) {
+        swid = textureWidth;
+        shgt = textureHeight;
+    }
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
+    glTexCoord2f(swid, 0.0f); glVertex2f( 1.0f, -1.0f);
+    glTexCoord2f(swid, shgt); glVertex2f( 1.0f,  1.0f);
+    glTexCoord2f(0.0f, shgt); glVertex2f(-1.0f,  1.0f);
+    glEnd();
+
+    glBindTexture(target, 0);
+    glDisable(target);
+}*/
+
+/*-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{
+    return textureID == 0 ? NO : YES;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
+{
+    AWT_ASSERT_APPKIT_THREAD;
+
+    JNIEnv *env = [ThreadUtilities getJNIEnv];
+    static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer");
+    static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V");
+
+    jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env];
+    if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {
+        return;
+    }
+
+    // Set the current context to the one given to us.
+    CGLSetCurrentContext(glContext);
+
+    // Should clear the whole CALayer, because it can be larger than our texture.
+    glClearColor(0.0, 0.0, 0.0, 0.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glViewport(0, 0, textureWidth, textureHeight);
+
+    JNFCallVoidMethod(env, javaLayerLocalRef, jm_drawInCGLContext);
+    (*env)->DeleteLocalRef(env, javaLayerLocalRef);
+
+    // Call super to finalize the drawing. By default all it does is call glFlush().
+    [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
+
+    CGLSetCurrentContext(NULL);
+}*/
+
+@end
+
+
+
+static jlong cachedLayer = 0;
+static float drawColor[4] = {0.0, 0.0, 0.0, 0.0};
+/*
+ * Class:     sun_java2d_metal_MetalLayer
+ * Method:    nativeCreateLayer
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MetalLayer_nativeCreateLayer
+(JNIEnv *env, jobject obj)
+{
+    __block MetalLayer *layer = nil;
+
+    //fprintf(stdout, "MetalLayer_nativeCreateLayer\n");fflush(stdout);
+JNF_COCOA_ENTER(env);
+
+    JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
+
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+            AWT_ASSERT_APPKIT_THREAD;
+        
+            layer = [[MetalLayer alloc] initWithJavaLayer: javaLayer];
+
+            //cachedLayer = ptr_to_jlong(layer);
+    }];
+    
+JNF_COCOA_EXIT(env);
+
+    return ptr_to_jlong(layer);
+}
+
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MetalLayer_nativeInitLayer
+(JNIEnv *env, jobject obj, jlong configInfo, jlong layer)
+{
+
+JNF_COCOA_ENTER(env);
+    MetalGraphicsConfigInfo *pInfo =
+        (MetalGraphicsConfigInfo *)jlong_to_ptr(configInfo);
+    if ((pInfo == NULL)) {
+        return -1;
+    }
+
+    MetalLayer *mtlLayer = jlong_to_ptr(layer);
+
+    mtlLayer.device = pInfo->device;
+    mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+
+    //mtlLayer.commandQueue = pInfo->commandQueue;
+
+    // ------------------------------------------------------------------------------------------------
+    // TODO : Currently we manually compile and copy the shader library to /tmp.
+    //        Need to complete build changes - to build it and read from some other location within jdk
+    // ------------------------------------------------------------------------------------------------
+    // Load shader library
+    /*NSError *error = nil;
+    mtlLayer.mtlLibrary = [mtlLayer.device newLibraryWithFile: @"/tmp/BaseShader.metallib" error:&error];
+    if (!mtlLayer.mtlLibrary) {
+        NSLog(@"Failed to load library. error %@", error);
+        //exit(0);
+    }*/
+
+    NSError* error = nil;
+    NSString* content = @"#include <metal_stdlib>\n"
+    "#include <simd/simd.h>\n"
+    "using namespace metal;\n"
+    "struct MetalVertex"
+    "{"
+    "vector_float4 position;"
+    "vector_float4 color;"
+    "};\n"
+    "struct VertexOut {"
+    "float4 color;"
+    "float4 pos [[position]];"
+    "};\n"
+    "vertex VertexOut vertexShader(device MetalVertex *vertices [[buffer(0)]],"
+                              "constant unsigned int *viewportSize [[buffer(1)]],"
+                              "uint vid [[vertex_id]]) {\n"
+    "VertexOut out;"
+    "out.pos = vertices[vid].position;"
+    "\n"
+    "float halfViewWidth = (float)(viewportSize[0] >> 1);"
+    "float halfViewHeight = (float)(viewportSize[1] >> 1);"
+    "\n"
+    "out.pos.x = (out.pos.x - halfViewWidth) / halfViewWidth;"
+    "out.pos.y = (halfViewHeight - out.pos.y) / halfViewHeight;"
+    "\n"
+    "out.color = vertices[vid].color;"
+    "\n"
+    "return out;"
+    "}\n"
+    "fragment float4 fragmentShader(MetalVertex in [[stage_in]]) {"
+    "return in.color;"
+    "}";
+
+    mtlLayer.mtlLibrary = [mtlLayer.device newLibraryWithSource:content options:nil error:&error];
+    if (!mtlLayer.mtlLibrary) {
+        NSLog(@"Failed to create shader library from source. error %@", error);
+        //exit(0);
+    }
+
+    //create a vertex and fragment objects
+    id<MTLFunction> vertexProgram = [mtlLayer.mtlLibrary newFunctionWithName:@"vertexShader"];
+    id<MTLFunction> fragmentProgram = [mtlLayer.mtlLibrary newFunctionWithName:@"fragmentShader"];
+
+    
+    mtlLayer.mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
+    
+    [mtlLayer.mtlRenderPipelineDescriptor setVertexFunction:vertexProgram];
+    [mtlLayer.mtlRenderPipelineDescriptor setFragmentFunction:fragmentProgram];
+    
+    //specify the target-texture pixel format
+    mtlLayer.mtlRenderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
+    
+    //create the Rendering Pipeline Object
+    mtlLayer.renderPipelineState = [mtlLayer.device newRenderPipelineStateWithDescriptor:mtlLayer.mtlRenderPipelineDescriptor error:nil];
+
+    VertexDataManager_init(mtlLayer.device);
+  
+
+JNF_COCOA_EXIT(env);
+
+    return ptr_to_jlong(layer);
+}
+
+
+
+// Must be called under the RQ lock.
+/*JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MetalLayer_nativeValidate
+(JNIEnv *env, jclass cls, jlong layer, jlong view)
+{
+
+JNF_COCOA_ENTER(env);
+
+    MetalLayer *mtlLayer = jlong_to_ptr(layer);
+    NSView *nsView = jlong_to_ptr(view);
+
+    mtlLayer.frame = nsView.bounds;
+    [mtlLayer setDrawableSize: nsView.bounds.size];
+
+    mtlLayer.textureWidth = nsView.bounds.size.width;
+    mtlLayer.textureHeight = nsView.bounds.size.height;
+
+    NSLog(@"Validate : Width : %f", nsView.bounds.size.width);
+    NSLog(@"Validate : Height : %f", nsView.bounds.size.height);
+
+JNF_COCOA_EXIT(env);
+}*/
+
+// Must be called under the RQ lock.
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MetalLayer_validate
+(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)
+{
+    MetalLayer *layer = OBJC(layerPtr);
+    //fprintf(stdout, "MetalLayer_validate\n");fflush(stdout);
+    if (surfaceData != NULL) {
+        MetalSDOps *metalsdo = (MetalSDOps*) SurfaceData_GetOps(env, surfaceData);
+        // TODO : Check whether we have to use pointer or instance variable
+        //fprintf(stdout, "MetalLayer_validate replace mtlTexture\n");fflush(stdout);
+        layer.mtlTexture = metalsdo->mtlTexture;
+        //layer.target = GL_TEXTURE_2D;
+        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);
+
+    } else {
+        //fprintf(stdout, "MetalLayer_validate Null SD \n");fflush(stdout);
+        //layer.textureID = 0;
+    }
+}
+
+
+
+/*
+// Must be called on the AppKit thread and under the RQ lock.
+JNIEXPORT void JNICALL
+Java_sun_java2d_opengl_CGLLayer_blitTexture
+(JNIEnv *env, jclass cls, jlong layerPtr)
+{
+    CGLLayer *layer = jlong_to_ptr(layerPtr);
+
+    [layer blitTexture];
+}*/
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MetalLayer_nativeSetScale
+(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)
+{
+    JNF_COCOA_ENTER(env);
+    MetalLayer *layer = jlong_to_ptr(layerPtr);
+    // We always call all setXX methods asynchronously, exception is only in 
+    // this method where we need to change native texture size and layer's scale
+    // in one call on appkit, otherwise we'll get window's contents blinking, 
+    // during screen-2-screen moving.
+    [ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){
+        layer.contentsScale = scale;
+    }];
+    JNF_COCOA_EXIT(env);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef MetalRenderQueue_h_Included
+#define MetalRenderQueue_h_Included
+
+//#include "MetalContext.h"
+#include "MetalSurfaceData.h"
+
+MetalSDOps *MetalRenderQueue_GetCurrentDestination();
+
+/*
+ * The following macros are used to pick values (of the specified type) off
+ * the queue.
+ */
+#define NEXT_VAL(buf, type) (((type *)((buf) += sizeof(type)))[-1])
+#define NEXT_BYTE(buf)      NEXT_VAL(buf, unsigned char)
+#define NEXT_INT(buf)       NEXT_VAL(buf, jint)
+#define NEXT_FLOAT(buf)     NEXT_VAL(buf, jfloat)
+#define NEXT_BOOLEAN(buf)   (jboolean)NEXT_INT(buf)
+#define NEXT_LONG(buf)      NEXT_VAL(buf, jlong)
+#define NEXT_DOUBLE(buf)    NEXT_VAL(buf, jdouble)
+
+/*
+ * Increments a pointer (buf) by the given number of bytes.
+ */
+#define SKIP_BYTES(buf, numbytes) buf += (numbytes)
+
+/*
+ * Extracts a value at the given offset from the provided packed value.
+ */
+#define EXTRACT_VAL(packedval, offset, mask) \
+    (((packedval) >> (offset)) & (mask))
+#define EXTRACT_BYTE(packedval, offset) \
+    (unsigned char)EXTRACT_VAL(packedval, offset, 0xff)
+#define EXTRACT_BOOLEAN(packedval, offset) \
+    (jboolean)EXTRACT_VAL(packedval, offset, 0x1)
+
+#endif /*MetalRenderQueue_h_Included*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,832 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+#include <Foundation/NSObjCRuntime.h>
+#include "sun_java2d_pipe_BufferedOpCodes.h"
+#include "jlong.h"
+//#include "OGLBlitLoops.h"
+//#include "OGLBufImgOps.h"
+//#include "OGLContext.h"
+//#include "OGLMaskBlit.h"
+//#include "OGLMaskFill.h"
+//#include "OGLPaints.h"
+//#include "OGLRenderQueue.h"
+//#include "OGLRenderer.h"
+//#include "OGLSurfaceData.h"
+//#include "OGLTextRenderer.h"
+//#include "OGLVertexCache.h"
+
+#include "MetalRenderer.h"
+#include "MetalRenderQueue.h"
+#include "Trace.h"
+#include "MetalSurfaceData.h"
+
+/**
+ * Used to track whether we are in a series of a simple primitive operations
+ * or texturing operations.  This variable should be controlled only via
+ * the INIT/CHECK/RESET_PREVIOUS_OP() macros.  See the
+ * OGLRenderQueue_CheckPreviousOp() method below for more information.
+ */
+//jint previousOp;
+
+/**
+ * References to the "current" context and destination surface.
+ */
+//static MetalContext *mtlc = NULL;
+static MetalSDOps *dstOps = NULL;
+static MetalContext *mtlc = NULL;
+
+/**
+ * The following methods are implemented in the windowing system (i.e. GLX
+ * and WGL) source files.
+ */
+//extern OGLContext *OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo);
+//extern void OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo);
+//extern void OGLSD_SwapBuffers(JNIEnv *env, jlong window);
+//extern void OGLSD_Flush(JNIEnv *env);
+
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MetalRenderQueue_flushBuffer(JNIEnv *env, jobject mtlrq, jlong buf, jint limit)
+{
+    jboolean sync = JNI_FALSE;
+    unsigned char *b, *end;
+
+    J2dTraceLn1(J2D_TRACE_INFO,
+                "MetalRenderQueue_flushBuffer: limit=%d", limit);
+
+    NSLog(@"Java_sun_java2d_metal_MetalRenderQueue_flushBuffer :");
+
+    b = (unsigned char *)jlong_to_ptr(buf);
+    if (b == NULL) {
+        /*J2dRlsTraceLn(J2D_TRACE_ERROR,
+            "MetalRenderQueue_flushBuffer: cannot get direct buffer address");*/
+        return 0;
+    }
+
+    //INIT_PREVIOUS_OP();
+    end = b + limit;
+
+    while (b < end) {
+        jint opcode = NEXT_INT(b);
+
+        fprintf(stdout, "MetalRenderQueue_flushBuffer_opcode : %d\n", opcode);fflush(stdout);
+        switch (opcode) {
+
+        // draw ops
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
+            {
+                jint x1 = NEXT_INT(b);
+                jint y1 = NEXT_INT(b);
+                jint x2 = NEXT_INT(b);
+                jint y2 = NEXT_INT(b);
+                MetalRenderer_DrawLine(mtlc, x1, y1, x2, y2);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
+            {
+                jint x = NEXT_INT(b);
+                jint y = NEXT_INT(b);
+                jint w = NEXT_INT(b);
+                jint h = NEXT_INT(b);
+                MetalRenderer_DrawRect(mtlc, x, y, w, h);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY:
+            {
+                jint nPoints      = NEXT_INT(b);
+                jboolean isClosed = NEXT_BOOLEAN(b);
+                jint transX       = NEXT_INT(b);
+                jint transY       = NEXT_INT(b);
+                /*jint *xPoints = (jint *)b;
+                jint *yPoints = ((jint *)b) + nPoints;
+                OGLRenderer_DrawPoly(oglc, nPoints, isClosed,
+                                     transX, transY,
+                                     xPoints, yPoints);*/
+                SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL:
+            {
+                jint x = NEXT_INT(b);
+                jint y = NEXT_INT(b);
+                // Note that we could use GL_POINTS here, but the common
+                // use case for DRAW_PIXEL is when rendering a Path2D,
+                // which will consist of a mix of DRAW_PIXEL and DRAW_LINE
+                // calls.  So to improve batching we use GL_LINES here,
+                // even though it requires an extra vertex per pixel.
+                /*CONTINUE_IF_NULL(oglc);
+                CHECK_PREVIOUS_OP(GL_LINES);
+                j2d_glVertex2i(x, y);
+                j2d_glVertex2i(x+1, y+1);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
+            {
+                jint count = NEXT_INT(b);
+                //OGLRenderer_DrawScanlines(oglc, count, (jint *)b);
+                SKIP_BYTES(b, count * BYTES_PER_SCANLINE);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                jfloat lwr21 = NEXT_FLOAT(b);
+                jfloat lwr12 = NEXT_FLOAT(b);
+                MetalRenderer_DrawParallelogram(mtlc,
+                                              x11, y11,
+                                              dx21, dy21,
+                                              dx12, dy12,
+                                              lwr21, lwr12);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                jfloat lwr21 = NEXT_FLOAT(b);
+                jfloat lwr12 = NEXT_FLOAT(b);
+                /*OGLRenderer_DrawAAParallelogram(oglc, dstOps,
+                                                x11, y11,
+                                                dx21, dy21,
+                                                dx12, dy12,
+                                                lwr21, lwr12);*/
+            }
+            break;
+
+        // fill ops
+        case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
+            {
+                jint x = NEXT_INT(b);
+                jint y = NEXT_INT(b);
+                jint w = NEXT_INT(b);
+                jint h = NEXT_INT(b);
+                MetalRenderer_FillRect(mtlc, x, y, w, h);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
+            {
+                jint count = NEXT_INT(b);
+                //OGLRenderer_FillSpans(oglc, count, (jint *)b);
+                SKIP_BYTES(b, count * BYTES_PER_SPAN);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                MetalRenderer_FillParallelogram(mtlc,
+                                              x11, y11,
+                                              dx21, dy21,
+                                              dx12, dy12);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                /*OGLRenderer_FillAAParallelogram(oglc, dstOps,
+                                                x11, y11,
+                                                dx21, dy21,
+                                                dx12, dy12);*/
+            }
+            break;
+
+        // text-related ops
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST:
+            {
+                jint numGlyphs        = NEXT_INT(b);
+                jint packedParams     = NEXT_INT(b);
+                jfloat glyphListOrigX = NEXT_FLOAT(b);
+                jfloat glyphListOrigY = NEXT_FLOAT(b);
+                /*jboolean usePositions = EXTRACT_BOOLEAN(packedParams,
+                                                        OFFSET_POSITIONS);
+                jboolean subPixPos    = EXTRACT_BOOLEAN(packedParams,
+                                                        OFFSET_SUBPIXPOS);
+                jboolean rgbOrder     = EXTRACT_BOOLEAN(packedParams,
+                                                        OFFSET_RGBORDER);
+                jint lcdContrast      = EXTRACT_BYTE(packedParams,
+                                                     OFFSET_CONTRAST);
+                unsigned char *images = b;
+                unsigned char *positions;
+                jint bytesPerGlyph;
+                if (usePositions) {
+                    positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE);
+                    bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH;
+                } else {
+                    positions = NULL;
+                    bytesPerGlyph = BYTES_PER_GLYPH_IMAGE;
+                }
+                OGLTR_DrawGlyphList(env, oglc, dstOps,
+                                    numGlyphs, usePositions,
+                                    subPixPos, rgbOrder, lcdContrast,
+                                    glyphListOrigX, glyphListOrigY,
+                                    images, positions);
+                SKIP_BYTES(b, numGlyphs * bytesPerGlyph);*/
+            }
+            break;
+
+        // copy-related ops
+        case sun_java2d_pipe_BufferedOpCodes_COPY_AREA:
+            {
+                jint x  = NEXT_INT(b);
+                jint y  = NEXT_INT(b);
+                jint w  = NEXT_INT(b);
+                jint h  = NEXT_INT(b);
+                jint dx = NEXT_INT(b);
+                jint dy = NEXT_INT(b);
+                /*OGLBlitLoops_CopyArea(env, oglc, dstOps,
+                                      x, y, w, h, dx, dy);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_BLIT:
+            {
+                jint packedParams = NEXT_INT(b);
+                jint sx1          = NEXT_INT(b);
+                jint sy1          = NEXT_INT(b);
+                jint sx2          = NEXT_INT(b);
+                jint sy2          = NEXT_INT(b);
+                jdouble dx1       = NEXT_DOUBLE(b);
+                jdouble dy1       = NEXT_DOUBLE(b);
+                jdouble dx2       = NEXT_DOUBLE(b);
+                jdouble dy2       = NEXT_DOUBLE(b);
+                jlong pSrc        = NEXT_LONG(b);
+                jlong pDst        = NEXT_LONG(b);
+                /*jint hint         = EXTRACT_BYTE(packedParams, OFFSET_HINT);
+                jboolean texture  = EXTRACT_BOOLEAN(packedParams,
+                                                    OFFSET_TEXTURE);
+                jboolean rtt      = EXTRACT_BOOLEAN(packedParams,
+                                                    OFFSET_RTT);
+                jboolean xform    = EXTRACT_BOOLEAN(packedParams,
+                                                    OFFSET_XFORM);
+                jboolean isoblit  = EXTRACT_BOOLEAN(packedParams,
+                                                    OFFSET_ISOBLIT);
+                if (isoblit) {
+                    OGLBlitLoops_IsoBlit(env, oglc, pSrc, pDst,
+                                         xform, hint, texture, rtt,
+                                         sx1, sy1, sx2, sy2,
+                                         dx1, dy1, dx2, dy2);
+                } else {
+                    jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
+                    OGLBlitLoops_Blit(env, oglc, pSrc, pDst,
+                                      xform, hint, srctype, texture,
+                                      sx1, sy1, sx2, sy2,
+                                      dx1, dy1, dx2, dy2);
+                }*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT:
+            {
+                jint sx      = NEXT_INT(b);
+                jint sy      = NEXT_INT(b);
+                jint dx      = NEXT_INT(b);
+                jint dy      = NEXT_INT(b);
+                jint w       = NEXT_INT(b);
+                jint h       = NEXT_INT(b);
+                jint dsttype = NEXT_INT(b);
+                jlong pSrc   = NEXT_LONG(b);
+                jlong pDst   = NEXT_LONG(b);
+                /*OGLBlitLoops_SurfaceToSwBlit(env, oglc,
+                                             pSrc, pDst, dsttype,
+                                             sx, sy, dx, dy, w, h);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_MASK_FILL:
+            {
+                jint x        = NEXT_INT(b);
+                jint y        = NEXT_INT(b);
+                jint w        = NEXT_INT(b);
+                jint h        = NEXT_INT(b);
+                jint maskoff  = NEXT_INT(b);
+                jint maskscan = NEXT_INT(b);
+                jint masklen  = NEXT_INT(b);
+                unsigned char *pMask = (masklen > 0) ? b : NULL;
+                /*OGLMaskFill_MaskFill(oglc, x, y, w, h,
+                                     maskoff, maskscan, masklen, pMask);*/
+                SKIP_BYTES(b, masklen);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT:
+            {
+                jint dstx     = NEXT_INT(b);
+                jint dsty     = NEXT_INT(b);
+                jint width    = NEXT_INT(b);
+                jint height   = NEXT_INT(b);
+                jint masklen  = width * height * sizeof(jint);
+                /*OGLMaskBlit_MaskBlit(env, oglc,
+                                     dstx, dsty, width, height, b);*/
+                SKIP_BYTES(b, masklen);
+            }
+            break;
+
+        // state-related ops
+        case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP:
+            {
+                jint x1 = NEXT_INT(b);
+                jint y1 = NEXT_INT(b);
+                jint x2 = NEXT_INT(b);
+                jint y2 = NEXT_INT(b);
+                //OGLContext_SetRectClip(oglc, dstOps, x1, y1, x2, y2);
+                MetalRenderer_SetRectClip(mtlc, x1, y1, x2, y2);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
+            {
+                //OGLContext_BeginShapeClip(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
+            {
+                jint count = NEXT_INT(b);
+                //OGLRenderer_FillSpans(oglc, count, (jint *)b);
+                SKIP_BYTES(b, count * BYTES_PER_SPAN);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
+            {
+                //OGLContext_EndShapeClip(oglc, dstOps);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
+            {
+                //OGLContext_ResetClip(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
+            {
+                jint rule         = NEXT_INT(b);
+                jfloat extraAlpha = NEXT_FLOAT(b);
+                jint flags        = NEXT_INT(b);
+                //OGLContext_SetAlphaComposite(oglc, rule, extraAlpha, flags);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
+            {
+                jint xorPixel = NEXT_INT(b);
+                //OGLContext_SetXorComposite(oglc, xorPixel);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
+            {
+                //OGLContext_ResetComposite(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
+            {
+                jdouble m00 = NEXT_DOUBLE(b);
+                jdouble m10 = NEXT_DOUBLE(b);
+                jdouble m01 = NEXT_DOUBLE(b);
+                jdouble m11 = NEXT_DOUBLE(b);
+                jdouble m02 = NEXT_DOUBLE(b);
+                jdouble m12 = NEXT_DOUBLE(b);
+                //OGLContext_SetTransform(oglc, m00, m10, m01, m11, m02, m12);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
+            {
+                //OGLContext_ResetTransform(oglc);
+            }
+            break;
+
+        // context-related ops
+        case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
+            {
+                //fprintf(stdout, "MetalRenderQueue_flushBuffer_SetSurfaces\n");fflush(stdout);
+                jlong pSrc = NEXT_LONG(b);
+                jlong pDst = NEXT_LONG(b);
+                /*if (oglc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                oglc = OGLContext_SetSurfaces(env, pSrc, pDst);*/
+                dstOps = (MetalSDOps *)jlong_to_ptr(pDst);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
+            {
+                jlong pConfigInfo = NEXT_LONG(b);
+                /*if (oglc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                oglc = OGLSD_SetScratchSurface(env, pConfigInfo);
+                dstOps = NULL;*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
+            {
+                jlong pData = NEXT_LONG(b);
+                /*OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
+                if (oglsdo != NULL) {
+                    CONTINUE_IF_NULL(oglc);
+                    RESET_PREVIOUS_OP();
+                    OGLSD_Delete(env, oglsdo);
+                }*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
+            {
+                jlong pData = NEXT_LONG(b);
+                /*OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
+                if (oglsdo != NULL) {
+                    CONTINUE_IF_NULL(oglc);
+                    RESET_PREVIOUS_OP();
+                    OGLSD_Delete(env, oglsdo);
+                    if (oglsdo->privOps != NULL) {
+                        free(oglsdo->privOps);
+                    }
+                }*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
+            {
+                jlong pConfigInfo = NEXT_LONG(b);
+                /*CONTINUE_IF_NULL(oglc);
+                RESET_PREVIOUS_OP();
+                OGLGC_DestroyOGLGraphicsConfig(pConfigInfo);
+
+                // the previous method will call glX/wglMakeCurrent(None),
+                // so we should nullify the current oglc and dstOps to avoid
+                // calling glFlush() (or similar) while no context is current
+                oglc = NULL;
+                dstOps = NULL;*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
+            {
+                // flush just in case there are any pending operations in
+                // the hardware pipe
+                /*if (oglc != NULL) {
+                    RESET_PREVIOUS_OP();
+                    j2d_glFlush();
+                }
+
+                // invalidate the references to the current context and
+                // destination surface that are maintained at the native level
+                oglc = NULL;
+                dstOps = NULL;*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE:
+            {
+                /*j2d_glPushAttrib(GL_ALL_ATTRIB_BITS);
+                j2d_glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
+                j2d_glMatrixMode(GL_MODELVIEW);
+                j2d_glPushMatrix();
+                j2d_glMatrixMode(GL_PROJECTION);
+                j2d_glPushMatrix();
+                j2d_glMatrixMode(GL_TEXTURE);
+                j2d_glPushMatrix();*/
+            }
+            break;
+
+        case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE:
+            {
+                /*j2d_glPopAttrib();
+                j2d_glPopClientAttrib();
+                j2d_glMatrixMode(GL_MODELVIEW);
+                j2d_glPopMatrix();
+                j2d_glMatrixMode(GL_PROJECTION);
+                j2d_glPopMatrix();
+                j2d_glMatrixMode(GL_TEXTURE);
+                j2d_glPopMatrix();*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SYNC:
+            {
+                //sync = JNI_TRUE;
+            }
+            break;
+
+        // multibuffering ops
+        case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS:
+            {
+                jlong window = NEXT_LONG(b);
+                /*if (oglc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                OGLSD_SwapBuffers(env, window);*/
+            }
+            break;
+
+        // special no-op (mainly used for achieving 8-byte alignment)
+        case sun_java2d_pipe_BufferedOpCodes_NOOP:
+            break;
+
+        // paint-related ops
+        case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT:
+            {
+                //OGLPaints_ResetPaint(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
+            {
+                fprintf(stdout, "MetalRenderQueue_flushBuffer_SetColor\n");fflush(stdout);
+                jint color = NEXT_INT(b);       
+                MetalRenderer_SetColor(mtlc, color);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
+            {
+                jboolean useMask= NEXT_BOOLEAN(b);
+                jboolean cyclic = NEXT_BOOLEAN(b);
+                jdouble p0      = NEXT_DOUBLE(b);
+                jdouble p1      = NEXT_DOUBLE(b);
+                jdouble p3      = NEXT_DOUBLE(b);
+                jint pixel1     = NEXT_INT(b);
+                jint pixel2     = NEXT_INT(b);
+                /*OGLPaints_SetGradientPaint(oglc, useMask, cyclic,
+                                           p0, p1, p3,
+                                           pixel1, pixel2);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
+            {
+                jboolean useMask = NEXT_BOOLEAN(b);
+                jboolean linear  = NEXT_BOOLEAN(b);
+                jint cycleMethod = NEXT_INT(b);
+                jint numStops    = NEXT_INT(b);
+                jfloat p0        = NEXT_FLOAT(b);
+                jfloat p1        = NEXT_FLOAT(b);
+                jfloat p3        = NEXT_FLOAT(b);
+                void *fractions, *pixels;
+                fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
+                pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
+                /*OGLPaints_SetLinearGradientPaint(oglc, dstOps,
+                                                 useMask, linear,
+                                                 cycleMethod, numStops,
+                                                 p0, p1, p3,
+                                                 fractions, pixels);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT:
+            {
+                jboolean useMask = NEXT_BOOLEAN(b);
+                jboolean linear  = NEXT_BOOLEAN(b);
+                jint numStops    = NEXT_INT(b);
+                jint cycleMethod = NEXT_INT(b);
+                jfloat m00       = NEXT_FLOAT(b);
+                jfloat m01       = NEXT_FLOAT(b);
+                jfloat m02       = NEXT_FLOAT(b);
+                jfloat m10       = NEXT_FLOAT(b);
+                jfloat m11       = NEXT_FLOAT(b);
+                jfloat m12       = NEXT_FLOAT(b);
+                jfloat focusX    = NEXT_FLOAT(b);
+                void *fractions, *pixels;
+                fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
+                pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
+                /*OGLPaints_SetRadialGradientPaint(oglc, dstOps,
+                                                 useMask, linear,
+                                                 cycleMethod, numStops,
+                                                 m00, m01, m02,
+                                                 m10, m11, m12,
+                                                 focusX,
+                                                 fractions, pixels);*/
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT:
+            {
+                jboolean useMask= NEXT_BOOLEAN(b);
+                jboolean filter = NEXT_BOOLEAN(b);
+                jlong pSrc      = NEXT_LONG(b);
+                jdouble xp0     = NEXT_DOUBLE(b);
+                jdouble xp1     = NEXT_DOUBLE(b);
+                jdouble xp3     = NEXT_DOUBLE(b);
+                jdouble yp0     = NEXT_DOUBLE(b);
+                jdouble yp1     = NEXT_DOUBLE(b);
+                jdouble yp3     = NEXT_DOUBLE(b);
+                /*OGLPaints_SetTexturePaint(oglc, useMask, pSrc, filter,
+                                          xp0, xp1, xp3,
+                                          yp0, yp1, yp3);*/
+            }
+            break;
+
+        // BufferedImageOp-related ops
+        case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP:
+            {
+                jlong pSrc        = NEXT_LONG(b);
+                jboolean edgeZero = NEXT_BOOLEAN(b);
+                jint kernelWidth  = NEXT_INT(b);
+                jint kernelHeight = NEXT_INT(b);
+                /*OGLBufImgOps_EnableConvolveOp(oglc, pSrc, edgeZero,
+                                              kernelWidth, kernelHeight, b);*/
+                SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
+            {
+                //OGLBufImgOps_DisableConvolveOp(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP:
+            {
+                jlong pSrc          = NEXT_LONG(b);
+                jboolean nonPremult = NEXT_BOOLEAN(b);
+                jint numFactors     = 4;
+                unsigned char *scaleFactors = b;
+                unsigned char *offsets = (b + numFactors * sizeof(jfloat));
+                /*OGLBufImgOps_EnableRescaleOp(oglc, pSrc, nonPremult,
+                                             scaleFactors, offsets);*/
+                SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
+            {
+                //OGLBufImgOps_DisableRescaleOp(oglc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP:
+            {
+                jlong pSrc          = NEXT_LONG(b);
+                jboolean nonPremult = NEXT_BOOLEAN(b);
+                jboolean shortData  = NEXT_BOOLEAN(b);
+                jint numBands       = NEXT_INT(b);
+                jint bandLength     = NEXT_INT(b);
+                jint offset         = NEXT_INT(b);
+                jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte);
+                void *tableValues = b;
+                /*OGLBufImgOps_EnableLookupOp(oglc, pSrc, nonPremult, shortData,
+                                            numBands, bandLength, offset,
+                                            tableValues);*/
+                SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
+            {
+                //OGLBufImgOps_DisableLookupOp(oglc);
+            }
+            break;
+
+        default:
+            J2dRlsTraceLn1(J2D_TRACE_ERROR,
+                "OGLRenderQueue_flushBuffer: invalid opcode=%d", opcode);
+            /*if (oglc != NULL) {
+                RESET_PREVIOUS_OP();
+            }*/
+            return 0;
+        }
+        // TODO : Below logic need to be refined more if any more opcodes
+        // we need to consider
+        /*if ((opcode != sun_java2d_pipe_BufferedOpCodes_DRAW_LINE) && 
+            (opcode != sun_java2d_pipe_BufferedOpCodes_SET_COLOR) &&
+            //(opcode != sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM) &&
+            //(opcode != sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM) &&
+            (opcode != sun_java2d_pipe_BufferedOpCodes_SET_SURFACES)) {
+            // We should not read int as it can cause under/overflow if
+            // coming data is not int
+            //jint x = NEXT_INT(b);
+            continue;
+        }*/
+
+        /*J2dTraceLn2(J2D_TRACE_VERBOSE,
+                    "MetalRenderQueue_flushBuffer: opcode=%d, rem=%d",
+                    opcode, (end-b));*/
+
+        /*switch (opcode) {
+
+        // draw ops
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
+            {
+                //fprintf(stdout, "MetalRenderQueue_flushBuffer_DrawLine\n");fflush(stdout);
+                jint x1 = NEXT_INT(b);
+                jint y1 = NEXT_INT(b);
+                jint x2 = NEXT_INT(b);
+                jint y2 = NEXT_INT(b);
+                MetalRenderer_DrawLine(mtlc, x1, y1, x2, y2);
+            }
+            break;
+
+        case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
+            {
+                //fprintf(stdout, "MetalRenderQueue_flushBuffer_SetColor\n");fflush(stdout);
+                jint color = NEXT_INT(b);       
+                MetalRenderer_SetColor(mtlc, color);
+            }
+            break;
+
+
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                jfloat lwr21 = NEXT_FLOAT(b);
+                jfloat lwr12 = NEXT_FLOAT(b);
+                MetalRenderer_DrawParallelogram(mtlc,
+                                              x11, y11,
+                                              dx21, dy21,
+                                              dx12, dy12,
+                                              lwr21, lwr12);
+            }
+            break;
+
+        case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
+            {
+                jfloat x11 = NEXT_FLOAT(b);
+                jfloat y11 = NEXT_FLOAT(b);
+                jfloat dx21 = NEXT_FLOAT(b);
+                jfloat dy21 = NEXT_FLOAT(b);
+                jfloat dx12 = NEXT_FLOAT(b);
+                jfloat dy12 = NEXT_FLOAT(b);
+                MetalRenderer_FillParallelogram(mtlc,
+                                              x11, y11,
+                                              dx21, dy21,
+                                              dx12, dy12);
+            }
+            break;
+
+        case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
+            {
+                //fprintf(stdout, "MetalRenderQueue_flushBuffer_SetSurfaces\n");fflush(stdout);
+                jlong pSrc = NEXT_LONG(b);
+                jlong pDst = NEXT_LONG(b);
+                if (oglc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                oglc = OGLContext_SetSurfaces(env, pSrc, pDst);
+                dstOps = (MetalSDOps *)jlong_to_ptr(pDst);
+            }
+            break;
+        
+        default:
+            J2dRlsTraceLn1(J2D_TRACE_ERROR,
+                "MetalRenderQueue_flushBuffer: invalid opcode=%d", opcode);
+            if (oglc != NULL) {
+                RESET_PREVIOUS_OP();
+            }
+            return 0;
+        }*/
+    }
+
+    // Render everything to offscreen surface data
+    MetalRenderer_Flush();
+
+    // Render to on-screen
+    MetalRenderer_blitToScreenDrawable();
+
+    return 1;
+}
+
+/**
+ * Returns a pointer to the "current" context, as set by the last SET_SURFACES
+ * or SET_SCRATCH_SURFACE operation.
+ */
+/*MetalContext *
+MetalRenderQueue_GetCurrentContext()
+{
+    return mtlc;
+}*/
+
+/**
+ * Returns a pointer to the "current" destination surface, as set by the last
+ * SET_SURFACES operation.
+ */
+MetalSDOps*
+MetalRenderQueue_GetCurrentDestination()
+{
+    return dstOps;
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef MetalRenderer_h_Included
+#define MetalRenderer_h_Included
+
+#include "sun_java2d_pipe_BufferedRenderPipe.h"
+#import <Metal/Metal.h>
+//#include "MetalContext.h"
+
+// define this in MetalContext
+typedef struct
+{
+    int info;
+} MetalContext;
+
+#define BYTES_PER_POLY_POINT \
+    sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_POLY_POINT
+#define BYTES_PER_SCANLINE \
+    sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_SCANLINE
+#define BYTES_PER_SPAN \
+    sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_SPAN
+// TODO : We might not need MetalContext itself in our case,
+// just having SDOps for destination can suffice
+void MetalRenderer_DrawLine(MetalContext *mtlc,
+                          jint x1, jint y1, jint x2, jint y2);
+
+
+void MetalRenderer_DrawRect(MetalContext *mtlc,
+                          jint x, jint y, jint w, jint h);
+
+void MetalRenderer_FillRect(MetalContext *mtlc,
+                          jint x, jint y, jint w, jint h);
+
+void MetalRenderer_SetColor(MetalContext *mtlc, jint color);
+
+
+void
+MetalRenderer_DrawParallelogram(MetalContext *mtlc,
+                              jfloat fx11, jfloat fy11,
+                              jfloat dx21, jfloat dy21,
+                              jfloat dx12, jfloat dy12,
+                              jfloat lwr21, jfloat lwr12);
+void
+MetalRenderer_FillParallelogram(MetalContext *mtlc,
+                              jfloat fx11, jfloat fy11,
+                              jfloat dx21, jfloat dy21,
+                              jfloat dx12, jfloat dy12);
+void FILL_PGRAM(float fx11, float fy11, float dx21, float dy21, float dx12, float dy12);
+void MetalRenderer_DrawQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+
+void MetalRenderer_Flush();
+void MetalRenderer_blitToScreenDrawable();
+
+void MetalRenderer_SetRectClip(MetalContext *mtlc, jint x1, jint y1, jint x2, jint y2);
+
+/*void OGLRenderer_DrawRect(OGLContext *oglc,
+                          jint x, jint y, jint w, jint h);
+void OGLRenderer_DrawPoly(OGLContext *oglc,
+                          jint nPoints, jint isClosed,
+                          jint transX, jint transY,
+                          jint *xPoints, jint *yPoints);
+void OGLRenderer_DrawScanlines(OGLContext *oglc,
+                               jint count, jint *scanlines);
+void OGLRenderer_DrawParallelogram(OGLContext *oglc,
+                                   jfloat fx11, jfloat fy11,
+                                   jfloat dx21, jfloat dy21,
+                                   jfloat dx12, jfloat dy12,
+                                   jfloat lw21, jfloat lw12);
+void OGLRenderer_DrawAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps,
+                                     jfloat fx11, jfloat fy11,
+                                     jfloat dx21, jfloat dy21,
+                                     jfloat dx12, jfloat dy12,
+                                     jfloat lw21, jfloat lw12);
+
+void OGLRenderer_FillRect(OGLContext *oglc,
+                          jint x, jint y, jint w, jint h);
+void OGLRenderer_FillSpans(OGLContext *oglc,
+                           jint count, jint *spans);
+void OGLRenderer_FillParallelogram(OGLContext *oglc,
+                                   jfloat fx11, jfloat fy11,
+                                   jfloat dx21, jfloat dy21,
+                                   jfloat dx12, jfloat dy12);
+void OGLRenderer_FillAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps,
+                                     jfloat fx11, jfloat fy11,
+                                     jfloat dx21, jfloat dy21,
+                                     jfloat dx12, jfloat dy12);
+
+void OGLRenderer_EnableAAParallelogramProgram();
+void OGLRenderer_DisableAAParallelogramProgram();*/
+
+#endif /* MetalRenderer_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef HEADLESS
+
+#include <jlong.h>
+#include <jni_util.h>
+#include <math.h>
+#include <Foundation/NSObjCRuntime.h>
+
+#include "sun_java2d_metal_MetalRenderer.h"
+
+#include "MetalRenderer.h"
+#include "MetalRenderQueue.h"
+#include "MetalSurfaceData.h"
+#import "shaders/MetalShaderTypes.h"
+#include "Trace.h"
+#include "MetalLayer.h"
+#import "VertexDataManager.h"
+
+
+// TODO : Current Color, Gradient etc should have its own class
+static float drawColor[4] = {0.0, 0.0, 0.0, 0.0};
+static int ClipRectangle[4] = {0, 0, 0, 0};
+// The current size of our view so we can use this in our render pipeline
+// static unsigned int viewportSize[2] = {0, 0};
+
+void
+MetalRenderer_DrawLine(MetalContext *mtlc, jint x1, jint y1, jint x2, jint y2)
+{
+    //J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawLine");
+
+    //RETURN_IF_NULL(mtlc);
+
+    //CHECK_PREVIOUS_OP(GL_LINES);
+  
+    float P1_X, P1_Y;
+    float P2_X, P2_Y;
+     
+    if (y1 == y2) {
+        // horizontal
+        float fx1 = (float)x1;
+        float fx2 = (float)x2;
+        float fy  = ((float)y1) + 0.2f;
+
+        if (x1 > x2) {
+            float t = fx1; fx1 = fx2; fx2 = t;
+        }
+
+        P1_X = fx1+0.2f;
+        P1_Y = fy;
+        P2_X = fx2+1.2f;
+        P2_Y = fy;
+    } else if (x1 == x2) {
+        // vertical
+        float fx  = ((float)x1) + 0.2f;
+        float fy1 = (float)y1;
+        float fy2 = (float)y2;
+
+        if (y1 > y2) {
+            float t = fy1; fy1 = fy2; fy2 = t;
+        }
+
+        P1_X = fx;
+        P1_Y = fy1+0.2f;
+        P2_X = fx; 
+        P2_Y = fy2+1.2f;
+    } else {
+        // diagonal
+        float fx1 = (float)x1;
+        float fy1 = (float)y1;
+        float fx2 = (float)x2;
+        float fy2 = (float)y2;
+
+        if (x1 < x2) {
+            fx1 += 0.2f;
+            fx2 += 1.0f;
+        } else {
+            fx1 += 0.8f;
+            fx2 -= 0.2f;
+        }
+
+        if (y1 < y2) {
+            fy1 += 0.2f;
+            fy2 += 1.0f;
+        } else {
+            fy1 += 0.8f;
+            fy2 -= 0.2f;
+        }
+
+        P1_X = fx1;
+        P1_Y = fy1;
+        P2_X = fx2;
+        P2_Y = fy2;
+    }
+    
+    // The (x1, y1) & (x2, y2) are in coordinate system :
+    //     Top Left (0, 0) : Bottom Right (width and height)
+    //
+    // Metal rendering coordinate system is :
+    //     Top Left (-1.0, 1.0) : Bottom Right (1.0, -1.0)
+    //
+    // This coordinate transformation happens in shader code.
+       
+    MetalVertex lineVertexData[] =
+    {
+        { {P1_X, P1_Y, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} },
+        { {P2_X, P2_Y, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }
+    };
+    
+    //NSLog(@"Drawline ----- x1 : %f, y1 : %f------ x2 : %f, y2 = %f", x1/halfWidth, y1/halfHeight,  x2/halfWidth, y2/halfHeight); 
+
+    VertexDataManager_addLineVertexData(lineVertexData[0], lineVertexData[1]);
+}
+
+
+
+void
+MetalRenderer_DrawParallelogram(MetalContext *mtlc,
+                              jfloat fx11, jfloat fy11,
+                              jfloat dx21, jfloat dy21,
+                              jfloat dx12, jfloat dy12,
+                              jfloat lwr21, jfloat lwr12)
+{
+    // dx,dy for line width in the "21" and "12" directions.
+    jfloat ldx21 = dx21 * lwr21;
+    jfloat ldy21 = dy21 * lwr21;
+    jfloat ldx12 = dx12 * lwr12;
+    jfloat ldy12 = dy12 * lwr12;
+
+    // calculate origin of the outer parallelogram
+    jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f;
+    jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f;
+
+    /*J2dTraceLn8(J2D_TRACE_INFO,
+                "OGLRenderer_DrawParallelogram "
+                "(x=%6.2f y=%6.2f "
+                "dx1=%6.2f dy1=%6.2f lwr1=%6.2f "
+                "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)",
+                fx11, fy11,
+                dx21, dy21, lwr21,
+                dx12, dy12, lwr12);*/
+
+    // RETURN_IF_NULL(oglc);
+
+    // CHECK_PREVIOUS_OP(GL_QUADS);
+
+    // Only need to generate 4 quads if the interior still
+    // has a hole in it (i.e. if the line width ratio was
+    // less than 1.0)
+    if (lwr21 < 1.0f && lwr12 < 1.0f) {
+
+        // Note: "TOP", "BOTTOM", "LEFT" and "RIGHT" here are
+        // relative to whether the dxNN variables are positive
+        // and negative.  The math works fine regardless of
+        // their signs, but for conceptual simplicity the
+        // comments will refer to the sides as if the dxNN
+        // were all positive.  "TOP" and "BOTTOM" segments
+        // are defined by the dxy21 deltas.  "LEFT" and "RIGHT"
+        // segments are defined by the dxy12 deltas.
+
+        // Each segment includes its starting corner and comes
+        // to just short of the following corner.  Thus, each
+        // corner is included just once and the only lengths
+        // needed are the original parallelogram delta lengths
+        // and the "line width deltas".  The sides will cover
+        // the following relative territories:
+        //
+        //     T T T T T R
+        //      L         R
+        //       L         R
+        //        L         R
+        //         L         R
+        //          L B B B B B
+
+        // TOP segment, to left side of RIGHT edge
+        // "width" of original pgram, "height" of hor. line size
+        fx11 = ox11;
+        fy11 = oy11;
+        FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12);
+
+        // RIGHT segment, to top of BOTTOM edge
+        // "width" of vert. line size , "height" of original pgram
+        fx11 = ox11 + dx21;
+        fy11 = oy11 + dy21;
+        FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12);
+
+        // BOTTOM segment, from right side of LEFT edge
+        // "width" of original pgram, "height" of hor. line size
+        fx11 = ox11 + dx12 + ldx21;
+        fy11 = oy11 + dy12 + ldy21;
+        FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12);
+
+        // LEFT segment, from bottom of TOP edge
+        // "width" of vert. line size , "height" of inner pgram
+        fx11 = ox11 + ldx12;
+        fy11 = oy11 + ldy12;
+        FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12);
+    } else {
+        // The line width ratios were large enough to consume
+        // the entire hole in the middle of the parallelogram
+        // so we can just issue one large quad for the outer
+        // parallelogram.
+        dx21 += ldx21;
+        dy21 += ldy21;
+        dx12 += ldx12;
+        dy12 += ldy12;
+        FILL_PGRAM(ox11, oy11, dx21, dy21, dx12, dy12);
+    }
+}
+
+
+void
+MetalRenderer_FillParallelogram(MetalContext *mtlc,
+                              jfloat fx11, jfloat fy11,
+                              jfloat dx21, jfloat dy21,
+                              jfloat dx12, jfloat dy12)
+{
+    /*J2dTraceLn6(J2D_TRACE_INFO,
+                "OGLRenderer_FillParallelogram "
+                "(x=%6.2f y=%6.2f "
+                "dx1=%6.2f dy1=%6.2f "
+                "dx2=%6.2f dy2=%6.2f)",
+                fx11, fy11,
+                dx21, dy21,
+                dx12, dy12);
+
+    RETURN_IF_NULL(oglc);
+
+    CHECK_PREVIOUS_OP(GL_QUADS);*/
+
+    FILL_PGRAM(fx11, fy11, dx21, dy21, dx12, dy12);
+}
+
+
+void FILL_PGRAM(float fx11, float fy11, float dx21, float dy21, float dx12, float dy12) {
+
+    MetalRenderer_DrawQuad(fx11, fy11, 
+                            fx11 + dx21, fy11 + dy21,
+                            fx11 + dx21 + dx12, fy11 + dy21 + dy12,
+                            fx11 + dx12, fy11 + dy12);
+} 
+
+
+
+void MetalRenderer_DrawQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
+   
+    // Draw two triangles with given 4 vertices
+  
+    // The (x1, y1) & (x2, y2) are in coordinate system : 
+    //     Top Left (0, 0) : Bottom Right (width and height)
+    //
+    // Metal rendering coordinate system is :
+    //     Top Left (-1.0, 1.0) : Bottom Right (1.0, -1.0)
+    //
+    // This coordinate transformation happens in shader code. 
+
+    MetalVertex QuadVertexData[] =
+    {
+        { {x1, y1, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} },
+        { {x2, y2, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} },
+        { {x3, y3, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} },
+        { {x4, y4, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} },
+    };
+
+    VertexDataManager_addQuadVertexData(QuadVertexData[0], QuadVertexData[1], QuadVertexData[2], QuadVertexData[3]);
+}
+
+
+void MetalRenderer_SetColor(MetalContext *mtlc, jint color) {
+    //J2dTraceLn(J2D_TRACE_INFO, "MetalRenderer_SetColor");
+    unsigned char r = (unsigned char)(color >> 16);
+    unsigned char g = (unsigned char)(color >>  8);
+    unsigned char b = (unsigned char)(color >>  0);
+    unsigned char a = 0xff;
+    
+    drawColor[0] = r/255.0;
+    drawColor[1] = g/255.0;
+    drawColor[2] = b/255.0;
+    drawColor[3] = 1.0;
+    
+    NSLog(@"MetalRenderer SetColor  ----- (%d, %d, %d, %d)", r, g, b, a);
+}
+
+
+void MetalRenderer_DrawRect(MetalContext *mtlc,
+                          jint x, jint y, jint w, jint h) {
+    //J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawRect");
+
+    if (w < 0 || h < 0) {
+        return;
+    }
+
+    //RETURN_IF_NULL(oglc);
+
+    if (w < 2 || h < 2) {
+        // If one dimension is less than 2 then there is no
+        // gap in the middle - draw a solid filled rectangle.
+        //CHECK_PREVIOUS_OP(GL_QUADS);
+        //GLRECT_BODY_XYWH(x, y, w+1, h+1);
+        MetalRenderer_FillRect(mtlc, x, y, w+1, h+1);
+    } else {
+        jint fx1 = (jint) (((float)x) + 0.2f);
+        jint fy1 = (jint) (((float)y) + 0.2f);
+        jint fx2 = fx1 + w;
+        jint fy2 = fy1 + h;
+
+        // Avoid drawing the endpoints twice.
+        // Also prefer including the endpoints in the
+        // horizontal sections which draw pixels faster.
+
+        // top
+        MetalRenderer_DrawLine(mtlc, fx1, fy1, fx2+1, fy1);
+        
+        // right
+        MetalRenderer_DrawLine(mtlc, fx2, fy1+1, fx2, fy2);
+
+        // bottom
+        MetalRenderer_DrawLine(mtlc, fx1, fy2, fx2+1, fy2);
+
+
+        // left
+        MetalRenderer_DrawLine(mtlc, fx1, fy1+1, fx1, fy2);
+    }
+}
+
+
+void
+MetalRenderer_FillRect(MetalContext *mtlc, jint x, jint y, jint w, jint h)
+{
+    //J2dTraceLn(J2D_TRACE_INFO, "MetalRenderer_FillRect");
+
+    if (w <= 0 || h <= 0) {
+        return;
+    }
+
+    //RETURN_IF_NULL(oglc);
+
+    //CHECK_PREVIOUS_OP(GL_QUADS);
+    //GLRECT_BODY_XYWH(x, y, w, h);
+
+    
+    MetalRenderer_DrawQuad(x, y, x, y+h, x+w, y+h, x+w, y);
+
+    //NSLog(@"MetalRenderer_FillRect: X, Y(%f, %f) with width, height(%f, %f)", (float)x, (float)y, (float)w, (float)h);
+}
+
+// TODO : I think, this should go to metal context
+void MetalRenderer_SetRectClip(MetalContext *mtlc, jint x1, jint y1, jint x2, jint y2) {
+
+    jint width = x2 - x1;
+    jint height = y2 - y1;
+
+    J2dTraceLn4(J2D_TRACE_INFO,
+                "MetalRenderer_SetRectClip: x=%d y=%d w=%d h=%d",
+                x1, y1, width, height);
+
+    //RETURN_IF_NULL(dstOps);
+    //RETURN_IF_NULL(oglc);
+    //CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);
+
+    if ((width < 0) || (height < 0)) {
+        // use an empty scissor rectangle when the region is empty
+        width = 0;
+        height = 0;
+    }
+
+    //j2d_glDisable(GL_DEPTH_TEST);
+    //j2d_glEnable(GL_SCISSOR_TEST);
+
+    // the scissor rectangle is specified using the lower-left
+    // origin of the clip region (in the framebuffer's coordinate
+    // space), so we must account for the x/y offsets of the
+    // destination surface
+    /*j2d_glScissor(dstOps->xOffset + x1,
+                  dstOps->yOffset + dstOps->height - (y1 + height),
+                  width, height);*/
+
+    MetalSDOps *dstOps = MetalRenderQueue_GetCurrentDestination();  
+
+    ClipRectangle[0] = x1;//dstOps->xOffset + x1;
+    ClipRectangle[1] = y1;//dstOps->yOffset + dstOps->height - (y1 + height);
+    ClipRectangle[2] = width;
+    ClipRectangle[3] = height; 
+
+}
+
+void MetalRenderer_Flush() {
+
+    MetalSDOps* dstOps = MetalRenderQueue_GetCurrentDestination();  
+    MetalLayer* mtlLayer = dstOps->layer;
+
+    unsigned int viewportSize[2] = {mtlLayer.textureWidth, mtlLayer.textureHeight};
+
+    //Create a render pass descriptor
+    MTLRenderPassDescriptor* mtlRenderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
+        
+    //Set the SurfaceData offscreen texture as target texture for the rendering pipeline
+    mtlRenderPassDescriptor.colorAttachments[0].texture = dstOps->mtlTexture;
+
+    mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
+    mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.8, 0.8, 0.8, 1.0);
+    mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
+
+    id<MTLCommandBuffer> mtlCommandBuffer = [dstOps->configInfo->commandQueue commandBuffer];
+    id<MTLRenderCommandEncoder> renderEncoder = [mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlRenderPassDescriptor];
+
+    // Configure render enconder with the pipeline state
+    [renderEncoder setRenderPipelineState:mtlLayer.renderPipelineState];
+
+    // Whatever outside this rectangle won't be drawn
+    // TODO : ClipRectangle should be part of MetalContext or some state maintaining class
+    NSLog(@"Setting Rect Clip : %d, %d, %d, %d", ClipRectangle[0], ClipRectangle[1], ClipRectangle[2], ClipRectangle[3]);
+    MTLScissorRect clip = {ClipRectangle[0], ClipRectangle[1], ClipRectangle[2], ClipRectangle[3]};
+    [renderEncoder setScissorRect:clip];
+
+    // ---------------------------------------------------------
+    // DRAW primitives from VertexDataManager
+    // ---------------------------------------------------------    
+    [renderEncoder setVertexBuffer:VertexDataManager_getVertexBuffer() offset:0 atIndex:0]; // 0th index 
+    
+    [renderEncoder setVertexBytes: &viewportSize
+                           length: sizeof(viewportSize)
+                          atIndex: 1]; // 1st index
+
+    MetalPrimitiveData** allPrimitives = VertexDataManager_getAllPrimitives();
+
+    int totalPrimitives = VertexDataManager_getNoOfPrimitives();
+    for (int i = 0; i < totalPrimitives; i++ ) {
+        MetalPrimitiveData* p = allPrimitives[i];
+
+        NSLog(@"----------------------------------------------");
+        NSLog(@"Encoding primitive %d", i);
+        NSLog(@"indexCount %d", p->no_of_indices);
+        NSLog(@"indexBufferOffset %d", p->offset_in_index_buffer);
+        NSLog(@"primitiveInstances %d", p->primitiveInstances);    
+        NSLog(@"----------------------------------------------");
+
+
+        [renderEncoder drawIndexedPrimitives: p->type
+                                  indexCount: (NSUInteger)p->no_of_indices 
+                                   indexType: (MTLIndexType)MTLIndexTypeUInt16
+                                 indexBuffer: (id<MTLBuffer>)VertexDataManager_getIndexBuffer() 
+                           indexBufferOffset: (NSUInteger)p->offset_in_index_buffer 
+                               instanceCount: (NSUInteger)p->primitiveInstances];
+    }
+
+    //--------------------------------------------------  
+
+    [renderEncoder endEncoding];
+   
+    [mtlCommandBuffer commit];
+
+    [mtlCommandBuffer waitUntilCompleted];
+}
+
+
+void MetalRenderer_blitToScreenDrawable() {
+ 
+    MetalSDOps* dstOps = MetalRenderQueue_GetCurrentDestination();  
+    MetalLayer* mtlLayer = dstOps->layer;
+    
+    @autoreleasepool {
+        id <CAMetalDrawable> frameDrawable = [mtlLayer nextDrawable];
+
+        id<MTLCommandBuffer> commandBuffer = [dstOps->configInfo->commandQueue commandBuffer];
+    
+        id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
+   
+        //[blitEncoder synchronizeResource:_texture];
+
+        [blitEncoder copyFromTexture:dstOps->mtlTexture
+                     sourceSlice:0
+                     sourceLevel:0
+                     sourceOrigin:MTLOriginMake(ClipRectangle[0], ClipRectangle[1], 0)
+                     sourceSize:MTLSizeMake(dstOps->mtlTexture.width - ClipRectangle[0], dstOps->mtlTexture.height - ClipRectangle[1], 1)
+                     toTexture:frameDrawable.texture
+                     destinationSlice:0
+                     destinationLevel:0
+                     destinationOrigin:MTLOriginMake(0, 0, 0)];
+       
+        [blitEncoder endEncoding];
+    
+        [commandBuffer presentDrawable:frameDrawable];
+    
+        [commandBuffer commit];
+    
+        [commandBuffer waitUntilCompleted];
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef MetalSurfaceData_h_Included
+#define MetalSurfaceData_h_Included
+
+#import "SurfaceData.h"
+#import "MetalGraphicsConfig.h"
+#import "AWTWindow.h"
+#import "MetalLayer.h"
+
+/**
+ * The MetalSDOps structure contains the Metal-specific information for
+ * given MetalSurfaceData.
+ */
+typedef struct _MetalSDOps {
+    SurfaceDataOps           sdOps;
+    AWTView                  *peerData;
+    MetalLayer               *layer;
+    //GLclampf              argb[4]; // background clear color
+    MetalGraphicsConfigInfo  *configInfo;
+    jint                     xOffset;
+    jint                     yOffset;
+    jboolean                 isOpaque;
+    id<MTLTexture>           mtlTexture;
+    //id<MTLRenderPipelineState> renderPipelineState;
+    jint                  width;
+    jint                  height;
+} MetalSDOps;
+
+#endif /* MetalSurfaceData_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#import <stdlib.h>
+
+#import "sun_java2d_metal_MetalSurfaceData.h"
+
+#import "jni_util.h"
+#import "MetalRenderQueue.h"
+#import "MetalGraphicsConfig.h"
+#import "MetalSurfaceData.h"
+#import "ThreadUtilities.h"
+
+/* JDK's glext.h is already included and will prevent the Apple glext.h
+ * being included, so define the externs directly
+ */
+/*extern void glBindFramebufferEXT(GLenum target, GLuint framebuffer);
+extern CGLError CGLTexImageIOSurface2D(
+        CGLContextObj ctx, GLenum target, GLenum internal_format,
+        GLsizei width, GLsizei height, GLenum format, GLenum type,
+        IOSurfaceRef ioSurface, GLuint plane);*/
+
+/**
+ * The methods in this file implement the native windowing system specific
+ * layer (CGL) for the OpenGL-based Java 2D pipeline.
+ */
+
+#pragma mark -
+#pragma mark "--- Mac OS X specific methods for GL pipeline ---"
+
+// TODO: hack that's called from OGLRenderQueue to test out unlockFocus behavior
+/*#if 0
+void
+OGLSD_UnlockFocus(OGLContext *oglc, OGLSDOps *dstOps)
+{
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+    CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps;
+    fprintf(stderr, "about to unlock focus: %p %p\n",
+            cglsdo->peerData, ctxinfo->context);
+
+    NSOpenGLView *nsView = cglsdo->peerData;
+    if (nsView != NULL) {
+JNF_COCOA_ENTER(env);
+        [nsView unlockFocus];
+JNF_COCOA_EXIT(env);
+    }
+}
+#endif*/
+
+/**
+ * Makes the given context current to its associated "scratch" surface.  If
+ * the operation is successful, this method will return JNI_TRUE; otherwise,
+ * returns JNI_FALSE.
+ */
+/*static jboolean
+CGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLSD_MakeCurrentToScratch");
+
+    if (oglc == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "CGLSD_MakeCurrentToScratch: context is null");
+        return JNI_FALSE;
+    }
+
+JNF_COCOA_ENTER(env);
+
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+#if USE_NSVIEW_FOR_SCRATCH
+    [ctxinfo->context makeCurrentContext];
+    [ctxinfo->context setView: ctxinfo->scratchSurface];
+#else
+    [ctxinfo->context clearDrawable];
+    [ctxinfo->context makeCurrentContext];
+    [ctxinfo->context setPixelBuffer: ctxinfo->scratchSurface
+            cubeMapFace: 0
+            mipMapLevel: 0
+            currentVirtualScreen: [ctxinfo->context currentVirtualScreen]];
+#endif
+
+JNF_COCOA_EXIT(env);
+
+    return JNI_TRUE;
+}*/
+
+/**
+ * This function disposes of any native windowing system resources associated
+ * with this surface.
+ */
+/*void
+OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
+
+JNF_COCOA_ENTER(env);
+
+    CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
+    if (oglsdo->drawableType == OGLSD_WINDOW) {
+        // detach the NSView from the NSOpenGLContext
+        CGLGraphicsConfigInfo *cglInfo = cglsdo->configInfo;
+        OGLContext *oglc = cglInfo->context;
+        CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+        [ctxinfo->context clearDrawable];
+    }
+
+    oglsdo->drawableType = OGLSD_UNDEFINED;
+
+JNF_COCOA_EXIT(env);
+}*/
+
+/**
+ * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo
+ * associated with the given OGLSDOps.  This method can be called from
+ * shared code to retrieve the native GraphicsConfig data in a platform-
+ * independent manner.
+ */
+/*jlong
+OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo");
+
+    if (oglsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: ops are null");
+        return 0L;
+    }
+
+    CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
+    if (cglsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: cgl ops are null");
+        return 0L;
+    }
+
+    return ptr_to_jlong(cglsdo->configInfo);
+}*/
+
+/**
+ * Makes the given GraphicsConfig's context current to its associated
+ * "scratch" surface.  If there is a problem making the context current,
+ * this method will return NULL; otherwise, returns a pointer to the
+ * OGLContext that is associated with the given GraphicsConfig.
+ */
+/*OGLContext *
+OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
+
+    CGLGraphicsConfigInfo *cglInfo = (CGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+    if (cglInfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: cgl config info is null");
+        return NULL;
+    }
+
+    OGLContext *oglc = cglInfo->context;
+    if (oglc == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: ogl context is null");
+        return NULL;
+    }
+
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+
+JNF_COCOA_ENTER(env);
+
+    // avoid changing the context's target view whenever possible, since
+    // calling setView causes flickering; as long as our context is current
+    // to some view, it's not necessary to switch to the scratch surface
+    if ([ctxinfo->context view] == nil) {
+        // it seems to be necessary to explicitly flush between context changes
+        OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
+        if (currentContext != NULL) {
+            j2d_glFlush();
+        }
+
+        if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
+            return NULL;
+        }
+    // make sure our context is current
+    } else if ([NSOpenGLContext currentContext] != ctxinfo->context) {
+        [ctxinfo->context makeCurrentContext];
+    }
+
+    if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
+        // the GL_EXT_framebuffer_object extension is present, so this call
+        // will ensure that we are bound to the scratch surface (and not
+        // some other framebuffer object)
+        j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+    }
+
+JNF_COCOA_EXIT(env);
+
+    return oglc;
+}*/
+
+/**
+ * Makes a context current to the given source and destination
+ * surfaces.  If there is a problem making the context current, this method
+ * will return NULL; otherwise, returns a pointer to the OGLContext that is
+ * associated with the destination surface.
+ */
+/*OGLContext *
+OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
+
+    CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps;
+
+    J2dTraceLn4(J2D_TRACE_VERBOSE, "  src: %d %p dst: %d %p", srcOps->drawableType, srcOps, dstOps->drawableType, dstOps);
+
+    OGLContext *oglc = dstCGLOps->configInfo->context;
+    if (oglc == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_MakeOGLContextCurrent: context is null");
+        return NULL;
+    }
+
+    CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+
+    // it seems to be necessary to explicitly flush between context changes
+    OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
+    if (currentContext != NULL) {
+        j2d_glFlush();
+    }
+
+    if (dstOps->drawableType == OGLSD_FBOBJECT) {
+        // first make sure we have a current context (if the context isn't
+        // already current to some drawable, we will make it current to
+        // its scratch surface)
+        if (oglc != currentContext) {
+            if (!CGLSD_MakeCurrentToScratch(env, oglc)) {
+                return NULL;
+            }
+        }
+
+        // now bind to the fbobject associated with the destination surface;
+        // this means that all rendering will go into the fbobject destination
+        // (note that we unbind the currently bound texture first; this is
+        // recommended procedure when binding an fbobject)
+        j2d_glBindTexture(GL_TEXTURE_2D, 0);
+        j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
+
+        return oglc;
+    }
+
+JNF_COCOA_ENTER(env);
+
+    CGLSDOps *cglsdo = (CGLSDOps *)dstOps->privOps;
+    NSView *nsView = (NSView *)cglsdo->peerData;
+
+    if ([ctxinfo->context view] != nsView) {
+        [ctxinfo->context makeCurrentContext];
+        [ctxinfo->context setView: nsView];
+    }
+
+    if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
+        // the GL_EXT_framebuffer_object extension is present, so we
+        // must bind to the default (windowing system provided)
+        // framebuffer
+        j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+    }
+
+JNF_COCOA_EXIT(env);
+
+    return oglc;
+}*/
+
+/**
+ * This function initializes a native window surface and caches the window
+ * bounds in the given OGLSDOps.  Returns JNI_TRUE if the operation was
+ * successful; JNI_FALSE otherwise.
+ */
+/*jboolean
+OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
+
+    if (oglsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null");
+        return JNI_FALSE;
+    }
+
+    CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
+    if (cglsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: cgl ops are null");
+        return JNI_FALSE;
+    }
+
+    AWTView *v = cglsdo->peerData;
+    if (v == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: view is invalid");
+        return JNI_FALSE;
+    }
+
+JNF_COCOA_ENTER(env);
+    NSRect surfaceBounds = [v bounds];
+    oglsdo->drawableType = OGLSD_WINDOW;
+    oglsdo->isOpaque = JNI_TRUE;
+    oglsdo->width = surfaceBounds.size.width;
+    oglsdo->height = surfaceBounds.size.height;
+JNF_COCOA_EXIT(env);
+
+    J2dTraceLn2(J2D_TRACE_VERBOSE, "  created window: w=%d h=%d", oglsdo->width, oglsdo->height);
+
+    return JNI_TRUE;
+}
+
+void
+OGLSD_SwapBuffers(JNIEnv *env, jlong pPeerData)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
+
+JNF_COCOA_ENTER(env);
+    [[NSOpenGLContext currentContext] flushBuffer];
+JNF_COCOA_EXIT(env);
+}*/
+
+/*void
+OGLSD_Flush(JNIEnv *env)
+{
+    OGLSDOps *dstOps = OGLRenderQueue_GetCurrentDestination();
+    if (dstOps != NULL) {
+        CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps;
+        CGLLayer *layer = (CGLLayer*)dstCGLOps->layer;
+        if (layer != NULL) {
+            [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+                AWT_ASSERT_APPKIT_THREAD;
+                [layer setNeedsDisplay];
+
+#ifdef REMOTELAYER*/
+                /* If there's a remote layer (being used for testing)
+                 * then we want to have that also receive the texture.
+                 * First sync. up its dimensions with that of the layer
+                 * we have attached to the local window and tell it that
+                 * it also needs to copy the texture.
+                 */
+                /*if (layer.remoteLayer != nil) {
+                    CGLLayer* remoteLayer = layer.remoteLayer;
+                    remoteLayer.target = GL_TEXTURE_2D;
+                    remoteLayer.textureID = layer.textureID;
+                    remoteLayer.textureWidth = layer.textureWidth;
+                    remoteLayer.textureHeight = layer.textureHeight;
+                    [remoteLayer setNeedsDisplay];
+                }
+#endif*/ /* REMOTELAYER */
+            //}];
+        //}
+    //}
+//}
+
+#pragma mark -
+#pragma mark "--- MetalSurfaceData methods ---"
+
+//extern LockFunc        OGLSD_Lock;
+//extern GetRasInfoFunc  OGLSD_GetRasInfo;
+//extern UnlockFunc      OGLSD_Unlock;
+//extern DisposeFunc     OGLSD_Dispose;
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MetalSurfaceData_initOps
+    (JNIEnv* env, jobject metalsd,
+     jlong pConfigInfo, jlong pPeerData, jlong layerPtr,
+     jint xoff, jint yoff, jboolean isOpaque)
+{
+    //J2dTraceLn(J2D_TRACE_INFO, "MetalSurfaceData_initOps");
+    //J2dTraceLn1(J2D_TRACE_INFO, "  pPeerData=%p", jlong_to_ptr(pPeerData));
+    //J2dTraceLn2(J2D_TRACE_INFO, "  xoff=%d, yoff=%d", (int)xoff, (int)yoff);
+
+    //fprintf(stdout, "MetalSurfaceData_initOps\n");fflush(stdout);
+    MetalSDOps* metalsdo = (MetalSDOps*)
+        SurfaceData_InitOps(env, metalsd, sizeof(MetalSDOps));
+    if (metalsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "creating native metal ops");
+        return;
+    }
+
+    // TODO : Check use case of below parameters and use them
+    /*metalsdo->sdOps.Lock               = OGLSD_Lock;
+    metalsdo->sdOps.GetRasInfo         = OGLSD_GetRasInfo;
+    metalsdo->sdOps.Unlock             = OGLSD_Unlock;
+    metalsdo->sdOps.Dispose            = OGLSD_Dispose;*/
+
+    metalsdo->xOffset = xoff;
+    metalsdo->yOffset = yoff;
+    metalsdo->isOpaque = isOpaque;
+
+    metalsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData);
+    metalsdo->layer = (MetalLayer *)jlong_to_ptr(layerPtr);
+    metalsdo->configInfo = (MetalGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+
+    if (metalsdo->configInfo == NULL) {
+        free(metalsdo);
+        JNU_ThrowNullPointerException(env, "Config info is null in initOps");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_opengl_MetalSurfaceData_clearWindow
+(JNIEnv *env, jobject metalsd)
+{
+    //J2dTraceLn(J2D_TRACE_INFO, "MetalSurfaceData_clearWindow");
+
+    MetalSDOps* metalsdo = (MetalSDOps*) SurfaceData_GetOps(env, metalsd);
+
+    metalsdo->peerData = NULL;
+    metalsdo->layer = NULL;
+    metalsdo->mtlTexture = NULL;
+}
+
+#pragma mark -
+#pragma mark "--- CGLSurfaceData methods - Mac OS X specific ---"
+
+// Must be called on the QFT...
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MetalSurfaceData_validate
+    (JNIEnv *env, jobject jsurfacedata,
+     jint xoff, jint yoff, jint width, jint height, jboolean isOpaque)
+{
+    //J2dTraceLn2(J2D_TRACE_INFO, "CGLSurfaceData_validate: w=%d h=%d", width, height);
+
+    MetalSDOps* metalsdo = (MetalSDOps*)SurfaceData_GetOps(env, jsurfacedata);
+    //oglsdo->needsInit = JNI_TRUE;
+    metalsdo->xOffset = xoff;
+    metalsdo->yOffset = yoff;
+
+    metalsdo->width = width;
+    metalsdo->height = height;
+    metalsdo->isOpaque = isOpaque;
+
+    // TODO : We need to have similar logic for Metal
+    /*if (oglsdo->drawableType == OGLSD_WINDOW) {
+        OGLContext_SetSurfaces(env, ptr_to_jlong(oglsdo), ptr_to_jlong(oglsdo));
+
+        // we have to explicitly tell the NSOpenGLContext that its target
+        // drawable has changed size
+        CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps;
+        OGLContext *oglc = cglsdo->configInfo->context;
+        CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo;
+
+JNF_COCOA_ENTER(env);
+        [ctxinfo->context update];
+JNF_COCOA_EXIT(env);
+    }*/
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_metal_MetalSurfaceData_initTexture
+(JNIEnv *env, jobject oglsd,
+ jlong pData, jboolean isOpaque,
+ jint width, jint height)
+{
+    MetalSDOps* metalsdo = (MetalSDOps *)jlong_to_ptr(pData);
+    //fprintf(stdout, "MetalSurfaceData_initTexture\n");fflush(stdout);
+    // OFFLINE TEXTURE
+    MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
+    
+    // Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is
+    // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0)
+    textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
+    textureDescriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
+    
+    // Set the pixel dimensions of the texture
+    textureDescriptor.width = width;
+    textureDescriptor.height = height;
+    
+    // Create the texture from the device by using the descriptor
+    metalsdo->mtlTexture = [metalsdo->configInfo->device newTextureWithDescriptor:textureDescriptor];
+    
+    metalsdo->width = width;
+    metalsdo->height = height;
+    metalsdo->isOpaque = isOpaque;
+    
+    // TODO : We may need to refactor the code related shader initialization
+    MetalGraphicsConfigInfo* pInfo =
+    (MetalGraphicsConfigInfo*)jlong_to_ptr(metalsdo->configInfo);
+    if ((pInfo == NULL)) {
+        return -1;
+    }
+    
+    MetalLayer* mtlLayer = jlong_to_ptr(metalsdo->layer);
+    
+    //mtlLayer.device = pInfo->device;
+    mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+    
+    //mtlLayer.commandQueue = pInfo->commandQueue;
+    
+   /* 
+    // Load shaders.
+    NSError *error = nil;
+    id<MTLLibrary> mtlLibrary = [metalsdo->configInfo->device newLibraryWithFile: @"/tmp/MyShader.metallib" error:&error];
+    if (!mtlLibrary) {
+        NSLog(@"Failed to load library. error %@", error);
+        //exit(0);
+    }
+    
+    //create a vertex and fragment function object
+    id<MTLFunction> vertexProgram = [mtlLibrary newFunctionWithName:@"vertexShader"];
+    id<MTLFunction> fragmentProgram = [mtlLibrary newFunctionWithName:@"fragmentShader"];
+    
+    MTLRenderPipelineDescriptor* mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
+    
+    //assign the vertex and fragment functions to the descriptor
+    [mtlRenderPipelineDescriptor setVertexFunction:vertexProgram];
+    [mtlRenderPipelineDescriptor setFragmentFunction:fragmentProgram];
+    
+    //specify the target-texture pixel format
+
+    mtlRenderPipelineDescriptor.colorAttachments[0].pixelFormat=MTLPixelFormatBGRA8Unorm;
+    
+    //create the Rendering Pipeline Object
+    metalsdo->renderPipelineState = [mtlLayer.device newRenderPipelineStateWithDescriptor:mtlRenderPipelineDescriptor error:nil];*/
+    
+    return JNI_TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef VertexDataManager_h_Included
+#define VertexDataManager_h_Included
+
+#import <Metal/Metal.h>
+#import "shaders/MetalShaderTypes.h"
+
+// ---------------------------------------------------------------------
+//TODO : This implementation should be redesigned as a singleton class
+//TODO : Drawing optimization can be done - if current primitive-type to be 
+//       drawn is equal to previous primitive-type in the list/array 
+//       (Similar to previous-op in OGL)
+// ---------------------------------------------------------------------
+
+typedef struct 
+{
+    MTLPrimitiveType type;
+    unsigned int offset_in_index_buffer;
+    unsigned int no_of_indices;
+    unsigned int primitiveInstances;
+} MetalPrimitiveData;
+
+void VertexDataManager_init(id<MTLDevice> device);
+
+void VertexDataManager_addLineVertexData(MetalVertex v1, MetalVertex v2);
+void VertexDataManager_addQuadVertexData(MetalVertex v1, MetalVertex v2, MetalVertex v3, MetalVertex v4);
+
+id<MTLBuffer> VertexDataManager_getVertexBuffer();
+id<MTLBuffer> VertexDataManager_getIndexBuffer();
+MetalPrimitiveData** VertexDataManager_getAllPrimitives();
+unsigned int VertexDataManager_getNoOfPrimitives();
+
+void VertexDataManager_freeAllPrimitives();
+void VertexDataManager_reset(id<MTLDevice> device);
+
+// should be private
+void addVertex(MetalVertex vert);
+void addIndex(unsigned short vertexNum);
+
+#endif //VertexDataManager_h_Included
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef HEADLESS
+
+#import "VertexDataManager.h"
+#import <Metal/Metal.h>
+
+
+
+static int MAX_PRIMITIVES = 100; //TODO : this needs to be changed to dynamic array of structures to support any number of primitives
+
+// TODO : all static members should be class members when singleton is implemented
+static id<MTLBuffer> VertexBuffer;
+static id<MTLBuffer> IndexBuffer;
+static unsigned int no_of_vertices = 0;
+static unsigned int no_of_indices = 0;
+static unsigned int no_of_primitives = 0;
+MetalPrimitiveData** AllPrimitives = NULL;
+
+
+void VertexDataManager_init(id<MTLDevice> device) {
+    // This limited buffer size allocation is for PoC purpose. 
+    // TODO : Need to implement a logic where we allocate more chunks if needed
+
+    VertexBuffer = [device newBufferWithLength:1024 * 32 options:MTLResourceOptionCPUCacheModeDefault];
+    IndexBuffer  = [device newBufferWithLength:1024 * 8 options:MTLResourceOptionCPUCacheModeDefault];
+
+    AllPrimitives = (MetalPrimitiveData**) malloc(sizeof(MetalPrimitiveData*) * MAX_PRIMITIVES); //[[NSMutableArray<MetalPrimitiveData*> alloc] init];
+}
+
+void VertexDataManager_addLineVertexData(MetalVertex v1, MetalVertex v2) {
+
+	  // Create a structure of MetalPrimitiveData (populate it) and it to the array
+	  MetalPrimitiveData* data = (MetalPrimitiveData*) malloc(sizeof(MetalPrimitiveData));//[[MetalPrimitiveData alloc] init];
+	  data->type = MTLPrimitiveTypeLine;
+	  data->offset_in_index_buffer = (no_of_indices) * sizeof(unsigned short);
+	  data->no_of_indices = 2;
+	  data->primitiveInstances = 1;
+    
+    AllPrimitives[no_of_primitives] = data;  
+	  no_of_primitives++;
+
+	  // Add v1, v2 to VertexBuffer
+	  addIndex(no_of_vertices);
+
+    addVertex(v1);
+    
+    addIndex(no_of_vertices);
+
+    addVertex(v2);
+}
+
+void VertexDataManager_addQuadVertexData(MetalVertex v1, MetalVertex v2, MetalVertex v3, MetalVertex v4) {
+	
+    MetalPrimitiveData* data = (MetalPrimitiveData*) malloc(sizeof(MetalPrimitiveData));//[[MetalPrimitiveData alloc] init];
+	  data->type = MTLPrimitiveTypeTriangle;
+	  data->offset_in_index_buffer = (no_of_indices) * sizeof(unsigned short);
+	  data->no_of_indices = 6;
+	  data->primitiveInstances = 2;
+
+	  AllPrimitives[no_of_primitives] = data;
+    no_of_primitives++;
+
+	  // Add all 4 vertices to the Vertexbuffer
+	  unsigned int firstVertexNumber = no_of_vertices;
+
+    addVertex(v1);
+    addVertex(v2);
+    addVertex(v3);
+    addVertex(v4);
+
+    /*
+       v1-------v4
+       | \      |
+       |  \     |
+       |   \    |
+       |    \   |
+       |     \  |
+       |      \ |
+       |       \|
+       v2-------v3
+    */
+    
+    // A quad is made up of two triangles
+    // Order of vertices is important - it is counter-clockwise
+	  // Specify 2 set of triangles using 3 indices each
+    addIndex(firstVertexNumber);     // v1
+    addIndex(firstVertexNumber + 1); // v2
+    addIndex(firstVertexNumber + 2); // v3
+
+    addIndex(firstVertexNumber + 2); // v3
+    addIndex(firstVertexNumber + 3); // v4
+    addIndex(firstVertexNumber);     // v1
+}
+
+void addVertex(MetalVertex vert) {
+    memcpy(VertexBuffer.contents + (no_of_vertices * sizeof(MetalVertex)), &vert, sizeof(MetalVertex));
+    no_of_vertices++;
+}
+
+void addIndex(unsigned short vertexNum) {
+	memcpy(IndexBuffer.contents + no_of_indices * sizeof(unsigned short), &vertexNum,  sizeof(unsigned short));
+	no_of_indices++;
+}
+
+
+id<MTLBuffer> VertexDataManager_getVertexBuffer() {
+	return VertexBuffer;
+}
+
+id<MTLBuffer> VertexDataManager_getIndexBuffer() {
+	return IndexBuffer;
+}
+
+MetalPrimitiveData** VertexDataManager_getAllPrimitives() {
+    return AllPrimitives;
+}
+
+unsigned int VertexDataManager_getNoOfPrimitives() {
+	return no_of_primitives;
+}
+
+void VertexDataManager_freeAllPrimitives() {
+ 
+    for (int i = 0; i < no_of_primitives; i++) {
+    	free(AllPrimitives[i]);
+    }
+
+    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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/BaseShader.metal	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+ 
+#include <metal_stdlib>
+using namespace metal;
+
+#import "MetalShaderTypes.h"
+
+
+struct VertexOut {
+    float4 color;
+    float4 pos [[position]];
+};
+
+
+/*
+    Java2D coordinate system : Top Left (0, 0) : Bottom Right (width and height)
+    Metal coordinate system is : 
+    Center is (0.0, 0.0)
+    Bottom Left (-1.0, -1.0) : Top Right (1.0, 1.0)
+    Top Left (-1.0, 1.0) : Bottom Right (1.0, -1.0)
+*/
+
+vertex VertexOut vertexShader(device MetalVertex *vertices [[buffer(0)]], 
+                              constant unsigned int *viewportSize [[buffer(1)]],
+                              uint vid [[vertex_id]]) {
+    VertexOut out;
+    out.pos = vertices[vid].position;
+
+    float halfViewWidth = (float)(viewportSize[0] >> 1);
+    float halfViewHeight = (float)(viewportSize[1] >> 1);
+
+    out.pos.x = (out.pos.x - halfViewWidth) / halfViewWidth;
+    out.pos.y = (halfViewHeight - out.pos.y) / halfViewHeight;
+   
+    out.color = vertices[vid].color;
+
+    return out;
+}
+
+
+fragment float4 fragmentShader(MetalVertex in [[stage_in]]) {
+    return in.color;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/MetalShaderTypes.h	Mon Mar 11 14:05:27 2019 +0530
@@ -0,0 +1,24 @@
+// Header for types and enum constants shared between Metal shaders and Objective C source
+
+#ifndef MetalShaderTypes_h
+#define MetalShaderTypes_h
+
+//#import <metal_stdlib>
+//using namespace metal;
+
+
+#import <simd/simd.h>
+//#import <Metal/Metal.h>
+
+
+typedef struct
+{
+    // Positions in pixel space
+    vector_float4 position;
+
+    // Floating-point RGBA colors
+    vector_float4 color;
+} MetalVertex;
+
+
+#endif /* MetalShaderTypes_h */
--- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -129,7 +129,13 @@
     private static final Object repaintManagerKey = RepaintManager.class;
 
     // Whether or not a VolatileImage should be used for double-buffered painting
-    static boolean volatileImageBufferEnabled = true;
+    // TODO : We have not yet implemented MetalBlitLoops logic.
+    // Because once we draw into offline buffer we need blitloops
+    // logic to blit the content into destination buffer.
+    // When we have blitloops logic for Metal we can enable usage
+    // of offscreen volatile image
+    //static boolean volatileImageBufferEnabled = true;
+    static boolean volatileImageBufferEnabled = false;
     /**
      * Type of VolatileImage which should be used for double-buffered
      * painting.
@@ -211,13 +217,14 @@
             }
         });
 
-        volatileImageBufferEnabled = "true".equals(AccessController.
+        // TODO : Revert this change after we implement MetalBlitLoops
+        /*volatileImageBufferEnabled = "true".equals(AccessController.
                 doPrivileged(new GetPropertyAction(
-                "swing.volatileImageBufferEnabled", "true")));
+                "swing.volatileImageBufferEnabled", "true")));*/
         boolean headless = GraphicsEnvironment.isHeadless();
-        if (volatileImageBufferEnabled && headless) {
+        /*if (volatileImageBufferEnabled && headless) {
             volatileImageBufferEnabled = false;
-        }
+        }*/
         nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
                     new GetPropertyAction("awt.nativeDoubleBuffering")));
         String bs = AccessController.doPrivileged(
--- a/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -115,6 +115,8 @@
     }
 
     public final void clear() {
+
+        System.out.println("RenderBuffer : clear()");
         curAddress = baseAddress;
     }
 
@@ -190,6 +192,9 @@
     public final RenderBuffer putInt(int pos, int x) {
         // assert (baseAddress + pos % SIZEOF_INT == 0);
         unsafe.putInt(baseAddress + pos, x);
+
+        System.out.println("RenderBuffer : putInt() --- added :"+x);
+
         return this;
     }
 
@@ -197,6 +202,9 @@
         // assert (position() % SIZEOF_INT == 0);
         unsafe.putInt(curAddress, x);
         curAddress += SIZEOF_INT;
+
+        System.out.println("RenderBuffer : putInt() --- added :"+x);
+
         return this;
     }
 
--- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.c	Mon Mar 11 02:05:07 2019 -0400
+++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.c	Mon Mar 11 14:05:27 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -30,6 +30,7 @@
 
 #include "stdlib.h"
 #include "string.h"
+#include "Trace.h"
 
 /**
  * This include file contains information on how to use a SurfaceData
@@ -80,12 +81,14 @@
 {
     jclass pICMClass;
 
+    J2dTraceLn(J2D_TRACE_INFO, "Java_sun_java2d_SurfaceData_initIDs --- invoked ");
+
     InitGlobalClassRef(pInvalidPipeClass, env,
                        "sun/java2d/InvalidPipeException");
 
     InitGlobalClassRef(pNullSurfaceDataClass, env,
                        "sun/java2d/NullSurfaceData");
-
+            
     InitField(pDataID, env, sd, "pData", "J");
     InitField(validID, env, sd, "valid", "Z");
 
@@ -235,6 +238,9 @@
 SurfaceData_InitOps(JNIEnv *env, jobject sData, int opsSize)
 {
     SurfaceDataOps *ops = malloc(opsSize);
+
+    J2dTraceLn(J2D_TRACE_INFO, "SurfaceData_InitOps --- invoked ");
+
     SurfaceData_SetOps(env, sData, ops);
     if (ops != NULL) {
         memset(ops, 0, opsSize);