Merge JDK-8220154 initial metal implementation patch to the jdk sandbox branch metal-prototype-branch
authorjdv
Fri, 21 Jun 2019 12:08:37 +0530
branchmetal-prototype-branch
changeset 57416 e153174dba06
parent 57400 978ffc56771f
child 57417 28582d575a98
Merge JDK-8220154 initial metal implementation patch to the jdk sandbox branch Reviewed-by: avu, prr, kcr Contributed-by: avu(Jetbrains), aghaisas, jdv
make/lib/Awt2dLibraries.gmk
src/java.desktop/macosx/classes/sun/awt/CGraphicsConfig.java
src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java
src/java.desktop/macosx/classes/sun/java2d/MacosxSurfaceManagerFactory.java
src/java.desktop/macosx/classes/sun/java2d/macos/MacOSFlags.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLBufImgOps.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLDrawImage.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderer.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceData.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLUtilities.java
src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalBlitLoops.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalContext.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalGraphicsConfig.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalLayer.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderQueue.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderer.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java
src/java.desktop/macosx/classes/sun/java2d/metal/MetalVolatileSurfaceManager.java
src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java
src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java
src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java
src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java
src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
src/java.desktop/macosx/native/libawt_lwawt/awt/common.h
src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLFuncs.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLFuncs.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGraphicsConfig.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGraphicsConfig.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskBlit.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskBlit.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceDataBase.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexturePool.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLUtils.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLUtils.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/BaseShader.metal
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/MetalShaderTypes.h
--- a/make/lib/Awt2dLibraries.gmk	Mon Jun 10 14:13:09 2019 +0530
+++ b/make/lib/Awt2dLibraries.gmk	Fri Jun 21 12:08:37 2019 +0530
@@ -246,6 +246,7 @@
     LIBS_macosx := -lmlib_image \
         -framework Cocoa \
         -framework OpenGL \
+        -framework Metal \
         -framework JavaNativeFoundation \
         -framework JavaRuntimeSupport \
         -framework ApplicationServices \
@@ -825,6 +826,7 @@
         -framework Foundation \
         -framework Security \
         -framework Cocoa \
+        -framework Metal \
         -framework JavaNativeFoundation
   else ifeq ($(call isTargetOs, windows), true)
     LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib
@@ -887,6 +889,7 @@
       libawt_lwawt/awt \
       libawt_lwawt/font \
       libawt_lwawt/java2d/opengl \
+      libawt_lwawt/java2d/metal \
       include \
       common/awt/debug \
       common/java2d/opengl \
@@ -922,12 +925,12 @@
           -framework AudioToolbox \
           -framework Carbon \
           -framework Cocoa \
+          -framework Metal \
           -framework Security \
           -framework ExceptionHandling \
           -framework JavaNativeFoundation \
           -framework JavaRuntimeSupport \
           -framework OpenGL \
-          -framework Metal \
           -framework QuartzCore -ljava, \
   ))
 
@@ -946,6 +949,11 @@
 ################################################################################
 
 ifeq ($(call isTargetOs, macosx), true)
+  XCODE_PATH := $(shell /usr/bin/xcode-select -p)
+  CompileMetalShaders :
+	$(XCODE_PATH)/Platforms/MacOSX.platform/usr/bin/metal -O2 -std=osx-metal1.1 -o $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxui/shaders.air $(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal
+	$(XCODE_PATH)/Platforms/MacOSX.platform/usr/bin/metal-ar r $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxui/shaders.metal-ar $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxui/shaders.air
+	$(XCODE_PATH)/Platforms/MacOSX.platform/usr/bin/metallib -o $(INSTALL_LIBRARIES_HERE)/shaders.metallib $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxui/shaders.metal-ar
 
   $(eval $(call SetupJdkLibrary, BUILD_LIBOSXUI, \
       NAME := osxui, \
@@ -961,6 +969,7 @@
           -L$(INSTALL_LIBRARIES_HERE), \
       LIBS := -lawt -losxapp -lawt_lwawt \
           -framework Cocoa \
+          -framework Metal \
           -framework Carbon \
           -framework ApplicationServices \
           -framework JavaNativeFoundation \
@@ -969,6 +978,7 @@
   ))
 
   TARGETS += $(BUILD_LIBOSXUI)
+  $(BUILD_LIBOSXUI): CompileMetalShaders
 
   $(BUILD_LIBOSXUI): $(BUILD_LIBAWT)
 
--- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsConfig.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsConfig.java	Fri Jun 21 12:08:37 2019 +0530
@@ -33,8 +33,8 @@
 
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLLayer;
-import sun.java2d.metal.MetalLayer;
 import sun.lwawt.LWGraphicsConfig;
+import sun.lwawt.macosx.CFRetainedResource;
 import sun.lwawt.macosx.CPlatformView;
 
 public abstract class CGraphicsConfig extends GraphicsConfiguration
@@ -88,10 +88,7 @@
      * Creates a new SurfaceData that will be associated with the given
      * CGLLayer.
      */
-    public abstract SurfaceData createSurfaceData(CGLLayer layer);
-
-
-    public abstract SurfaceData createSurfaceData(MetalLayer layer);
+    public abstract SurfaceData createSurfaceData(CFRetainedResource layer);
 
     @Override
     public final boolean isTranslucencyCapable() {
--- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java	Fri Jun 21 12:08:37 2019 +0530
@@ -36,8 +36,9 @@
 import java.util.Objects;
 
 import sun.java2d.SunGraphicsEnvironment;
+import sun.java2d.macos.MacOSFlags;
+import sun.java2d.metal.MTLGraphicsConfig;
 import sun.java2d.opengl.CGLGraphicsConfig;
-import sun.java2d.metal.MetalGraphicsConfig;
 
 public final class CGraphicsDevice extends GraphicsDevice
         implements DisplayChangedListener {
@@ -61,25 +62,9 @@
 
     public CGraphicsDevice(final int displayID) {
         this.displayID = displayID;
-
-        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;
+        config = MacOSFlags.isMetalEnabled() ?
+                MTLGraphicsConfig.getConfig(this, displayID, 0) :
+                CGLGraphicsConfig.getConfig(this, displayID, 0);
     }
 
     /**
--- a/src/java.desktop/macosx/classes/sun/java2d/MacosxSurfaceManagerFactory.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/java2d/MacosxSurfaceManagerFactory.java	Fri Jun 21 12:08:37 2019 +0530
@@ -27,9 +27,9 @@
 
 import sun.awt.image.SunVolatileImage;
 import sun.awt.image.VolatileSurfaceManager;
+import sun.java2d.macos.MacOSFlags;
+import sun.java2d.metal.MTLVolatileSurfaceManager;
 import sun.java2d.opengl.CGLVolatileSurfaceManager;
-import sun.java2d.metal.MetalVolatileSurfaceManager;
-
 
 /**
  * This is a factory class with static methods for creating a
@@ -51,23 +51,7 @@
     public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
                                                         Object 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;
+        return MacOSFlags.isMetalEnabled() ? new MTLVolatileSurfaceManager(vImg, context) :
+                new CGLVolatileSurfaceManager(vImg, context);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/macos/MacOSFlags.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,86 @@
+/*
+ * 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.macos;
+
+import java.security.PrivilegedAction;
+
+public class MacOSFlags {
+
+    /**
+     * Description of command-line flags.  All flags with [true|false]
+     * values
+     *      metalEnabled: usage: "-Dsun.java2d.metal=[true|false]"
+     */
+
+    private static boolean metalEnabled;
+
+    static {
+        initJavaFlags();
+        initNativeFlags();
+    }
+
+    private static native boolean initNativeFlags();
+
+    private static boolean getBooleanProp(String p, boolean defaultVal) {
+        String propString = System.getProperty(p);
+        boolean returnVal = defaultVal;
+        if (propString != null) {
+            if (propString.equals("true") ||
+                propString.equals("t") ||
+                propString.equals("True") ||
+                propString.equals("T") ||
+                propString.equals("")) // having the prop name alone
+            {                          // is equivalent to true
+                returnVal = true;
+            } else if (propString.equals("false") ||
+                       propString.equals("f") ||
+                       propString.equals("False") ||
+                       propString.equals("F"))
+            {
+                returnVal = false;
+            }
+        }
+        return returnVal;
+    }
+
+
+    private static boolean getPropertySet(String p) {
+        String propString = System.getProperty(p);
+        return (propString != null) ? true : false;
+    }
+
+    private static void initJavaFlags() {
+        java.security.AccessController.doPrivileged(
+                (PrivilegedAction<Object>) () -> {
+                    metalEnabled = getBooleanProp("sun.java2d.metal", false);
+                    return null;
+                });
+    }
+
+    public static boolean isMetalEnabled() {
+        return metalEnabled;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLBlitLoops.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,945 @@
+/*
+ * 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 sun.java2d.SurfaceData;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.Region;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+import sun.java2d.pipe.hw.AccelSurface;
+
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.lang.annotation.Native;
+import java.lang.ref.WeakReference;
+
+import static sun.java2d.pipe.BufferedOpCodes.BLIT;
+import static sun.java2d.pipe.BufferedOpCodes.SURFACE_TO_SW_BLIT;
+
+final class MTLBlitLoops {
+
+    static void register() {
+        Blit blitIntArgbPreToSurface =
+                new MTLSwToSurfaceBlit(SurfaceType.IntArgbPre,
+                        MTLSurfaceData.PF_INT_ARGB_PRE);
+        Blit blitIntArgbPreToTexture =
+                new MTLSwToTextureBlit(SurfaceType.IntArgbPre,
+                        MTLSurfaceData.PF_INT_ARGB_PRE);
+        TransformBlit transformBlitIntArgbPreToSurface =
+                new MTLSwToSurfaceTransform(SurfaceType.IntArgbPre,
+                        MTLSurfaceData.PF_INT_ARGB_PRE);
+        MTLSurfaceToSwBlit blitSurfaceToIntArgbPre =
+                new MTLSurfaceToSwBlit(SurfaceType.IntArgbPre,
+                        MTLSurfaceData.PF_INT_ARGB_PRE);
+
+        GraphicsPrimitive[] primitives = {
+                // surface->surface ops
+                new MTLSurfaceToSurfaceBlit(),
+                new MTLSurfaceToSurfaceScale(),
+                new MTLSurfaceToSurfaceTransform(),
+
+                // render-to-texture surface->surface ops
+                new MTLRTTSurfaceToSurfaceBlit(),
+                new MTLRTTSurfaceToSurfaceScale(),
+                new MTLRTTSurfaceToSurfaceTransform(),
+
+                // surface->sw ops
+                new MTLSurfaceToSwBlit(SurfaceType.IntArgb,
+                        MTLSurfaceData.PF_INT_ARGB),
+                blitSurfaceToIntArgbPre,
+
+                // sw->surface ops
+                blitIntArgbPreToSurface,
+                new MTLSwToSurfaceBlit(SurfaceType.IntRgb,
+                        MTLSurfaceData.PF_INT_RGB),
+                new MTLSwToSurfaceBlit(SurfaceType.IntRgbx,
+                        MTLSurfaceData.PF_INT_RGBX),
+                new MTLSwToSurfaceBlit(SurfaceType.IntBgr,
+                        MTLSurfaceData.PF_INT_BGR),
+                new MTLSwToSurfaceBlit(SurfaceType.IntBgrx,
+                        MTLSurfaceData.PF_INT_BGRX),
+                new MTLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
+                        MTLSurfaceData.PF_3BYTE_BGR),
+                new MTLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
+                        MTLSurfaceData.PF_USHORT_565_RGB),
+                new MTLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
+                        MTLSurfaceData.PF_USHORT_555_RGB),
+                new MTLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx,
+                        MTLSurfaceData.PF_USHORT_555_RGBX),
+                new MTLSwToSurfaceBlit(SurfaceType.ByteGray,
+                        MTLSurfaceData.PF_BYTE_GRAY),
+                new MTLSwToSurfaceBlit(SurfaceType.UshortGray,
+                        MTLSurfaceData.PF_USHORT_GRAY),
+                new MTLGeneralBlit(MTLSurfaceData.MTLSurface,
+                        CompositeType.AnyAlpha,
+                        blitIntArgbPreToSurface),
+
+                new MTLAnyCompositeBlit(MTLSurfaceData.MTLSurface,
+                        blitSurfaceToIntArgbPre,
+                        blitSurfaceToIntArgbPre,
+                        blitIntArgbPreToSurface),
+                new MTLAnyCompositeBlit(SurfaceType.Any,
+                        null,
+                        blitSurfaceToIntArgbPre,
+                        blitIntArgbPreToSurface),
+
+                new MTLSwToSurfaceScale(SurfaceType.IntRgb,
+                        MTLSurfaceData.PF_INT_RGB),
+                new MTLSwToSurfaceScale(SurfaceType.IntRgbx,
+                        MTLSurfaceData.PF_INT_RGBX),
+                new MTLSwToSurfaceScale(SurfaceType.IntBgr,
+                        MTLSurfaceData.PF_INT_BGR),
+                new MTLSwToSurfaceScale(SurfaceType.IntBgrx,
+                        MTLSurfaceData.PF_INT_BGRX),
+                new MTLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
+                        MTLSurfaceData.PF_3BYTE_BGR),
+                new MTLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
+                        MTLSurfaceData.PF_USHORT_565_RGB),
+                new MTLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
+                        MTLSurfaceData.PF_USHORT_555_RGB),
+                new MTLSwToSurfaceScale(SurfaceType.Ushort555Rgbx,
+                        MTLSurfaceData.PF_USHORT_555_RGBX),
+                new MTLSwToSurfaceScale(SurfaceType.ByteGray,
+                        MTLSurfaceData.PF_BYTE_GRAY),
+                new MTLSwToSurfaceScale(SurfaceType.UshortGray,
+                        MTLSurfaceData.PF_USHORT_GRAY),
+                new MTLSwToSurfaceScale(SurfaceType.IntArgbPre,
+                        MTLSurfaceData.PF_INT_ARGB_PRE),
+
+                new MTLSwToSurfaceTransform(SurfaceType.IntRgb,
+                        MTLSurfaceData.PF_INT_RGB),
+                new MTLSwToSurfaceTransform(SurfaceType.IntRgbx,
+                        MTLSurfaceData.PF_INT_RGBX),
+                new MTLSwToSurfaceTransform(SurfaceType.IntBgr,
+                        MTLSurfaceData.PF_INT_BGR),
+                new MTLSwToSurfaceTransform(SurfaceType.IntBgrx,
+                        MTLSurfaceData.PF_INT_BGRX),
+                new MTLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
+                        MTLSurfaceData.PF_3BYTE_BGR),
+                new MTLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
+                        MTLSurfaceData.PF_USHORT_565_RGB),
+                new MTLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
+                        MTLSurfaceData.PF_USHORT_555_RGB),
+                new MTLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx,
+                        MTLSurfaceData.PF_USHORT_555_RGBX),
+                new MTLSwToSurfaceTransform(SurfaceType.ByteGray,
+                        MTLSurfaceData.PF_BYTE_GRAY),
+                new MTLSwToSurfaceTransform(SurfaceType.UshortGray,
+                        MTLSurfaceData.PF_USHORT_GRAY),
+                transformBlitIntArgbPreToSurface,
+
+                new MTLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
+
+                // texture->surface ops
+                new MTLTextureToSurfaceBlit(),
+                new MTLTextureToSurfaceScale(),
+                new MTLTextureToSurfaceTransform(),
+
+                // sw->texture ops
+                blitIntArgbPreToTexture,
+                new MTLSwToTextureBlit(SurfaceType.IntRgb,
+                        MTLSurfaceData.PF_INT_RGB),
+                new MTLSwToTextureBlit(SurfaceType.IntRgbx,
+                        MTLSurfaceData.PF_INT_RGBX),
+                new MTLSwToTextureBlit(SurfaceType.IntBgr,
+                        MTLSurfaceData.PF_INT_BGR),
+                new MTLSwToTextureBlit(SurfaceType.IntBgrx,
+                        MTLSurfaceData.PF_INT_BGRX),
+                new MTLSwToTextureBlit(SurfaceType.ThreeByteBgr,
+                        MTLSurfaceData.PF_3BYTE_BGR),
+                new MTLSwToTextureBlit(SurfaceType.Ushort565Rgb,
+                        MTLSurfaceData.PF_USHORT_565_RGB),
+                new MTLSwToTextureBlit(SurfaceType.Ushort555Rgb,
+                        MTLSurfaceData.PF_USHORT_555_RGB),
+                new MTLSwToTextureBlit(SurfaceType.Ushort555Rgbx,
+                        MTLSurfaceData.PF_USHORT_555_RGBX),
+                new MTLSwToTextureBlit(SurfaceType.ByteGray,
+                        MTLSurfaceData.PF_BYTE_GRAY),
+                new MTLSwToTextureBlit(SurfaceType.UshortGray,
+                        MTLSurfaceData.PF_USHORT_GRAY),
+                new MTLGeneralBlit(MTLSurfaceData.MTLTexture,
+                        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 |= MTLContext.SRC_IS_OPAQUE;
+        }
+
+        MTLRenderQueue rq = MTLRenderQueue.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);
+
+            MTLSurfaceData oglDst = (MTLSurfaceData)dstData;
+            if (texture) {
+                // make sure we have a current context before uploading
+                // the sysmem data to the texture object
+                MTLGraphicsConfig gc = oglDst.getMTLGraphicsConfig();
+                MTLContext.setScratchSurface(gc);
+            } else {
+                MTLContext.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 MTLBufImgOps.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 |= MTLContext.SRC_IS_OPAQUE;
+        }
+
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            MTLSurfaceData oglSrc = (MTLSurfaceData)srcData;
+            MTLSurfaceData oglDst = (MTLSurfaceData)dstData;
+            int srctype = oglSrc.getType();
+            boolean rtt;
+            MTLSurfaceData srcCtxData;
+            if (srctype == MTLSurfaceData.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 == AccelSurface.RT_TEXTURE) {
+                    srcCtxData = oglDst;
+                } else {
+                    srcCtxData = oglSrc;
+                }
+            }
+
+            MTLContext.validateContext(srcCtxData, oglDst,
+                    clip, comp, xform, null, null,
+                    ctxflags);
+
+            if (biop != null) {
+                MTLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop);
+            }
+
+            int packedParams = createPackedParams(true, texture,
+                    rtt, xform != null,
+                    hint, 0 /*unused*/);
+            enqueueBlit(rq, srcData, dstData,
+                    packedParams,
+                    sx1, sy1, sx2, sy2,
+                    dx1, dy1, dx2, dy2);
+
+            if (biop != null) {
+                MTLBufImgOps.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 MTLSurfaceToSurfaceBlit extends Blit {
+
+    MTLSurfaceToSurfaceBlit() {
+        super(MTLSurfaceData.MTLSurface,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        MTLBlitLoops.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 MTLSurfaceToSurfaceScale extends ScaledBlit {
+
+    MTLSurfaceToSurfaceScale() {
+        super(MTLSurfaceData.MTLSurface,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                false);
+    }
+}
+
+class MTLSurfaceToSurfaceTransform extends TransformBlit {
+
+    MTLSurfaceToSurfaceTransform() {
+        super(MTLSurfaceData.MTLSurface,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                false);
+    }
+}
+
+class MTLRTTSurfaceToSurfaceBlit extends Blit {
+
+    MTLRTTSurfaceToSurfaceBlit() {
+        super(MTLSurfaceData.MTLSurfaceRTT,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        MTLBlitLoops.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 MTLRTTSurfaceToSurfaceScale extends ScaledBlit {
+
+    MTLRTTSurfaceToSurfaceScale() {
+        super(MTLSurfaceData.MTLSurfaceRTT,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                true);
+    }
+}
+
+class MTLRTTSurfaceToSurfaceTransform extends TransformBlit {
+
+    MTLRTTSurfaceToSurfaceTransform() {
+        super(MTLSurfaceData.MTLSurfaceRTT,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                true);
+    }
+}
+
+final class MTLSurfaceToSwBlit extends Blit {
+
+    private final int typeval;
+    private WeakReference<SurfaceData> srcTmp;
+
+    // destination will actually be ArgbPre or Argb
+    MTLSurfaceToSwBlit(final SurfaceType dstType, final int typeval) {
+        super(MTLSurfaceData.MTLSurface,
+                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 MTL surface in two places:
+        // - During MTL surface -> SW blit
+        // - During SW -> SW blit
+        // The first one is faster when we use opaque MTL 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 == MTLSurfaceData.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;
+            }
+        }
+
+        MTLRenderQueue rq = MTLRenderQueue.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();
+            MTLContext.validateContext((MTLSurfaceData)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 MTLSwToSurfaceBlit extends Blit {
+
+    private int typeval;
+
+    MTLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+        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)
+    {
+        MTLBlitLoops.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 MTLSwToSurfaceScale extends ScaledBlit {
+
+    private int typeval;
+
+    MTLSwToSurfaceScale(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+        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)
+    {
+        MTLBlitLoops.Blit(src, dst,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                typeval, false);
+    }
+}
+
+class MTLSwToSurfaceTransform extends TransformBlit {
+
+    private int typeval;
+
+    MTLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+        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)
+    {
+        MTLBlitLoops.Blit(src, dst,
+                comp, clip, at, hint,
+                sx, sy, sx+w, sy+h,
+                dx, dy, dx+w, dy+h,
+                typeval, false);
+    }
+}
+
+class MTLSwToTextureBlit extends Blit {
+
+    private int typeval;
+
+    MTLSwToTextureBlit(SurfaceType srcType, int typeval) {
+        super(srcType,
+                CompositeType.SrcNoEa,
+                MTLSurfaceData.MTLTexture);
+        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)
+    {
+        MTLBlitLoops.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 MTLTextureToSurfaceBlit extends Blit {
+
+    MTLTextureToSurfaceBlit() {
+        super(MTLSurfaceData.MTLTexture,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst,
+                     Composite comp, Region clip,
+                     int sx, int sy, int dx, int dy, int w, int h)
+    {
+        MTLBlitLoops.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 MTLTextureToSurfaceScale extends ScaledBlit {
+
+    MTLTextureToSurfaceScale() {
+        super(MTLSurfaceData.MTLTexture,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.IsoBlit(src, dst,
+                null, null,
+                comp, clip, null,
+                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
+                sx1, sy1, sx2, sy2,
+                dx1, dy1, dx2, dy2,
+                true);
+    }
+}
+
+class MTLTextureToSurfaceTransform extends TransformBlit {
+
+    MTLTextureToSurfaceTransform() {
+        super(MTLSurfaceData.MTLTexture,
+                CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+    }
+
+    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)
+    {
+        MTLBlitLoops.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->MTLSurface/Texture loop to get the intermediate
+ * (premultiplied) surface down to OpenGL using simple blit.
+ */
+class MTLGeneralBlit extends Blit {
+
+    private final Blit performop;
+    private WeakReference<SurfaceData> srcTmp;
+
+    MTLGeneralBlit(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->MTLSurface/Texture loop to get the intermediate
+ * (premultiplied) surface down to OpenGL using simple transformBlit.
+ */
+final class MTLGeneralTransformedBlit extends TransformBlit {
+
+    private final TransformBlit performop;
+    private WeakReference<SurfaceData> srcTmp;
+
+    MTLGeneralTransformedBlit(final TransformBlit performop) {
+        super(SurfaceType.Any, CompositeType.AnyAlpha,
+                MTLSurfaceData.MTLSurface);
+        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 MTLAnyCompositeBlit 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 MTLAnyCompositeBlit extends Blit {
+
+    private WeakReference<SurfaceData> dstTmp;
+    private WeakReference<SurfaceData> srcTmp;
+    private final Blit convertsrc;
+    private final Blit convertdst;
+    private final Blit convertresult;
+
+    MTLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,
+                        Blit convertresult) {
+        super(srctype, CompositeType.Any, MTLSurfaceData.MTLSurface);
+        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/MTLBufImgOps.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,112 @@
+/*
+ * 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 sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.pipe.BufferedBufImgOps;
+
+import java.awt.image.*;
+
+import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER;
+
+class MTLBufImgOps extends BufferedBufImgOps {
+
+    /**
+     * This method is called from MTLDrawImage.transformImage() only.  It
+     * validates the provided BufferedImageOp to determine whether the op
+     * is one that can be accelerated by the MTL pipeline.  If the operation
+     * cannot be completed for any reason, this method returns false;
+     * otherwise, the given BufferedImage is rendered to the destination
+     * using the provided BufferedImageOp and this method returns true.
+     */
+    static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img,
+                                     BufferedImageOp biop, int x, int y)
+    {
+        // Validate the provided BufferedImage (make sure it is one that
+        // is supported, and that its properties are acceleratable)
+        if (biop instanceof ConvolveOp) {
+            if (!isConvolveOpValid((ConvolveOp)biop)) {
+                return false;
+            }
+        } else if (biop instanceof RescaleOp) {
+            if (!isRescaleOpValid((RescaleOp)biop, img)) {
+                return false;
+            }
+        } else if (biop instanceof LookupOp) {
+            if (!isLookupOpValid((LookupOp)biop, img)) {
+                return false;
+            }
+        } else {
+            // No acceleration for other BufferedImageOps (yet)
+            return false;
+        }
+
+        SurfaceData dstData = sg.surfaceData;
+        if (!(dstData instanceof MTLSurfaceData) ||
+                (sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
+                (sg.compositeState > SunGraphics2D.COMP_ALPHA))
+        {
+            return false;
+        }
+
+        SurfaceData srcData =
+                dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
+                        CompositeType.SrcOver, null);
+        if (!(srcData instanceof MTLSurfaceData)) {
+            // REMIND: this hack tries to ensure that we have a cached texture
+            srcData =
+                    dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
+                            CompositeType.SrcOver, null);
+            if (!(srcData instanceof MTLSurfaceData)) {
+                return false;
+            }
+        }
+
+        // Verify that the source surface is actually a texture and
+        // that the operation is supported
+        MTLSurfaceData mtlSrc = (MTLSurfaceData)srcData;
+        MTLGraphicsConfig gc = mtlSrc.getMTLGraphicsConfig();
+        if (mtlSrc.getType() != MTLSurfaceData.TEXTURE ||
+                !gc.isCapPresent(CAPS_EXT_BIOP_SHADER))
+        {
+            return false;
+        }
+
+        int sw = img.getWidth();
+        int sh = img.getHeight();
+        MTLBlitLoops.IsoBlit(srcData, dstData,
+                img, biop,
+                sg.composite, sg.getCompClip(),
+                sg.transform, sg.interpolationType,
+                0, 0, sw, sh,
+                x, y, x+sw, y+sh,
+                true);
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,222 @@
+/*
+ * 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 sun.java2d.pipe.BufferedContext;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+import sun.java2d.pipe.hw.ContextCapabilities;
+
+import java.lang.annotation.Native;
+
+import static sun.java2d.pipe.BufferedOpCodes.*;
+
+/**
+ * Note that the RenderQueue lock must be acquired before calling any of
+ * the methods in this class.
+ */
+public class MTLContext extends BufferedContext {
+
+    private final MTLGraphicsConfig config;
+
+    public MTLContext(RenderQueue rq, MTLGraphicsConfig config) {
+        super(rq);
+        this.config = config;
+    }
+
+    /**
+     * Convenience method that delegates to setScratchSurface() below.
+     */
+    static void setScratchSurface(MTLGraphicsConfig gc) {
+        setScratchSurface(gc.getNativeConfigInfo());
+    }
+
+    /**
+     * Makes the given GraphicsConfig's context current to its associated
+     * "scratch surface".  Each GraphicsConfig maintains a native context
+     * (MTLDevice) 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.
+     * This method should be used for operations with an MTL 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).
+     */
+    public static void setScratchSurface(long pConfigInfo) {
+        // assert MTLRenderQueue.getInstance().lock.isHeldByCurrentThread();
+
+        // invalidate the current context
+        currentContext = null;
+
+        // set the scratch context
+        MTLRenderQueue rq = MTLRenderQueue.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 MTLContext (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).
+     */
+    public static void invalidateCurrentContext() {
+        // assert MTLRenderQueue.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
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.ensureCapacity(4);
+        rq.getBuffer().putInt(INVALIDATE_CONTEXT);
+        rq.flushNow();
+    }
+
+    public RenderQueue getRenderQueue() {
+        return MTLRenderQueue.getInstance();
+    }
+
+    /**
+     * Returns a string representing adapter id (vendor, renderer, version).
+     * Must be called on the rendering thread.
+     *
+     * @return an id string for the adapter
+     */
+    public static final native String getMTLIdString();
+
+    @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();
+    }
+
+    public static class MTLContextCaps extends ContextCapabilities {
+        /**
+         * 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
+        public static final int CAPS_EXT_FBOBJECT     =
+                (CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE);
+        /** Indicates that the context is doublebuffered. */
+        @Native
+        public static final int CAPS_DOUBLEBUFFERED   = (FIRST_PRIVATE_CAP << 0);
+        /**
+         * 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);
+        /**
+         * 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);
+        /**
+         * 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);
+
+
+        public MTLContextCaps(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/MTLDrawImage.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,113 @@
+/*
+ * 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 sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.loops.TransformBlit;
+import sun.java2d.pipe.DrawImage;
+
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+
+public class MTLDrawImage extends DrawImage {
+
+    @Override
+    protected void renderImageXform(SunGraphics2D sg, Image img,
+                                    AffineTransform tx, int interpType,
+                                    int sx1, int sy1, int sx2, int sy2,
+                                    Color bgColor)
+    {
+        // punt to the MediaLib-based transformImage() in the superclass if:
+        //     - bicubic interpolation is specified
+        //     - a background color is specified and will be used
+        //     - the source surface is neither a texture nor render-to-texture
+        //       surface, and a non-default interpolation hint is specified
+        //       (we can only control the filtering for texture->surface
+        //       copies)
+        //         REMIND: we should tweak the sw->texture->surface
+        //         transform case to handle filtering appropriately
+        //         (see 4841762)...
+        //     - an appropriate TransformBlit primitive could not be found
+        if (interpType != AffineTransformOp.TYPE_BICUBIC) {
+            SurfaceData dstData = sg.surfaceData;
+            SurfaceData srcData =
+                    dstData.getSourceSurfaceData(img,
+                            SunGraphics2D.TRANSFORM_GENERIC,
+                            sg.imageComp,
+                            bgColor);
+
+            if (srcData != null &&
+                    !isBgOperation(srcData, bgColor) &&
+                    (srcData.getSurfaceType() == MTLSurfaceData.MTLTexture ||
+                            srcData.getSurfaceType() == MTLSurfaceData.MTLSurfaceRTT ||
+                            interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR))
+            {
+                SurfaceType srcType = srcData.getSurfaceType();
+                SurfaceType dstType = dstData.getSurfaceType();
+                TransformBlit blit = TransformBlit.getFromCache(srcType,
+                        sg.imageComp,
+                        dstType);
+
+                if (blit != null) {
+                    blit.Transform(srcData, dstData,
+                            sg.composite, sg.getCompClip(),
+                            tx, interpType,
+                            sx1, sy1, 0, 0, sx2-sx1, sy2-sy1);
+                    return;
+                }
+            }
+        }
+
+        super.renderImageXform(sg, img, tx, interpType,
+                sx1, sy1, sx2, sy2, bgColor);
+    }
+
+    @Override
+    public void transformImage(SunGraphics2D sg, BufferedImage img,
+                               BufferedImageOp op, int x, int y)
+    {
+        if (op != null) {
+            if (op instanceof AffineTransformOp) {
+                AffineTransformOp atop = (AffineTransformOp) op;
+                transformImage(sg, img, x, y,
+                        atop.getTransform(),
+                        atop.getInterpolationType());
+                return;
+            } else {
+                if (MTLBufImgOps.renderImageWithOp(sg, img, op, x, y)) {
+                    return;
+                }
+            }
+            img = op.filter(img, null);
+        }
+        copyImage(sg, img, x, y, null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLGraphicsConfig.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,439 @@
+/*
+ * 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 sun.awt.CGraphicsConfig;
+import sun.awt.CGraphicsDevice;
+import sun.awt.image.OffScreenImage;
+import sun.awt.image.SunVolatileImage;
+import sun.awt.image.SurfaceManager;
+import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
+import sun.java2d.Surface;
+import sun.java2d.SurfaceData;
+import sun.java2d.pipe.hw.AccelGraphicsConfig;
+import sun.java2d.pipe.hw.AccelSurface;
+import sun.java2d.pipe.hw.AccelTypedVolatileImage;
+import sun.java2d.pipe.hw.ContextCapabilities;
+import sun.lwawt.LWComponentPeer;
+import sun.lwawt.macosx.CFRetainedResource;
+import sun.lwawt.macosx.CPlatformView;
+
+import java.awt.*;
+import java.awt.color.ColorSpace;
+import java.awt.image.*;
+import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+
+import static sun.java2d.opengl.OGLSurfaceData.TEXTURE;
+import static sun.java2d.pipe.hw.AccelSurface.RT_TEXTURE;
+import static sun.java2d.pipe.hw.ContextCapabilities.*;
+
+public final class MTLGraphicsConfig extends CGraphicsConfig
+        implements AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig
+{
+    //private static final int kOpenGLSwapInterval =
+    // RuntimeOptions.getCurrentOptions().OpenGLSwapInterval;
+    private static final int kOpenGLSwapInterval = 0; // TODO
+    private static boolean mtlAvailable;
+    private static ImageCapabilities imageCaps = new MTLImageCaps();
+
+    private static final String mtlShadersLib = AccessController.doPrivileged(
+            (PrivilegedAction<String>) () ->
+                    System.getProperty("java.home", "") + File.separator +
+                            "lib" + File.separator + "shaders.metallib");
+
+
+    private int pixfmt;
+    private BufferCapabilities bufferCaps;
+    private long pConfigInfo;
+    private ContextCapabilities mtlCaps;
+    private MTLContext context;
+    private final Object disposerReferent = new Object();
+    private final int maxTextureSize;
+
+    private static native boolean initMTL();
+    private static native long getMTLConfigInfo(int displayID, String mtlShadersLib);
+
+    /**
+     * Returns GL_MAX_TEXTURE_SIZE from the shared opengl context. Must be
+     * called under OGLRQ lock, because this method change current context.
+     *
+     * @return GL_MAX_TEXTURE_SIZE
+     */
+    private static native int nativeGetMaxTextureSize();
+
+    private static final HashMap<Long, Integer> pGCRefCounts = new HashMap<>();
+
+    static {
+        mtlAvailable = initMTL();
+    }
+
+    private MTLGraphicsConfig(CGraphicsDevice device, int pixfmt,
+                              long configInfo, int maxTextureSize,
+                              ContextCapabilities mtlCaps) {
+        super(device);
+
+        this.pixfmt = pixfmt;
+        this.pConfigInfo = configInfo;
+        this.mtlCaps = mtlCaps;
+        this.maxTextureSize = maxTextureSize;
+        context = new MTLContext(MTLRenderQueue.getInstance(), this);
+        refPConfigInfo(pConfigInfo);
+        // add a record to the Disposer so that we destroy the native
+        // MTLGraphicsConfigInfo data when this object goes away
+        Disposer.addRecord(disposerReferent,
+                new MTLGCDisposerRecord(pConfigInfo));
+    }
+
+    @Override
+    public Object getProxyKey() {
+        return this;
+    }
+
+    public SurfaceData createManagedSurface(int w, int h, int transparency) {
+        return MTLSurfaceData.createData(this, w, h,
+                getColorModel(transparency),
+                null,
+                MTLSurfaceData.TEXTURE);
+    }
+
+    public static MTLGraphicsConfig getConfig(CGraphicsDevice device,
+                                              int displayID, int pixfmt)
+    {
+        if (!mtlAvailable) {
+            return null;
+        }
+
+        long cfginfo = 0;
+        int textureSize = 0;
+        final String[] ids = new String[1];
+        MTLRenderQueue rq = MTLRenderQueue.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...
+            MTLContext.invalidateCurrentContext();
+            cfginfo = getMTLConfigInfo(displayID, mtlShadersLib);
+            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;
+                MTLContext.setScratchSurface(cfginfo);
+                rq.flushAndInvokeNow(() -> {
+                    ids[0] = MTLContext.getMTLIdString();
+                });
+            }
+        } finally {
+            rq.unlock();
+        }
+        if (cfginfo == 0) {
+            return null;
+        }
+
+        ContextCapabilities caps = new MTLContext.MTLContextCaps(
+                CAPS_PS30 | CAPS_PS20 | CAPS_RT_PLAIN_ALPHA |
+                        CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE |
+                        CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 | CAPS_TEXNONSQUARE,
+                ids[0]);
+        return new MTLGraphicsConfig(device, pixfmt, cfginfo, textureSize, caps);
+    }
+
+    static void refPConfigInfo(long pConfigInfo) {
+        synchronized (pGCRefCounts) {
+            Integer count = pGCRefCounts.get(pConfigInfo);
+            if (count == null) {
+                count = 1;
+            }
+            else {
+                count++;
+            }
+            pGCRefCounts.put(pConfigInfo, count);
+        }
+    }
+
+    static void deRefPConfigInfo(long pConfigInfo) {
+        synchronized (pGCRefCounts) {
+            Integer count = pGCRefCounts.get(pConfigInfo);
+            if (count != null) {
+                count--;
+                pGCRefCounts.put(pConfigInfo, count);
+                if (count == 0) {
+                    MTLRenderQueue.disposeGraphicsConfig(pConfigInfo);
+                    pGCRefCounts.remove(pConfigInfo);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns true if the provided capability bit is present for this config.
+     * See MTLContext.java for a list of supported capabilities.
+     */
+    public boolean isCapPresent(int cap) {
+        return ((mtlCaps.getCaps() & cap) != 0);
+    }
+
+    public long getNativeConfigInfo() {
+        return pConfigInfo;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
+     */
+    @Override
+    public MTLContext getContext() {
+        return context;
+    }
+
+    @Override
+    public BufferedImage createCompatibleImage(int width, int height) {
+        ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
+        WritableRaster
+                raster = model.createCompatibleWritableRaster(width, height);
+        return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
+                null);
+    }
+
+    @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 boolean isDoubleBuffered() {
+        return true;
+    }
+
+    private static class MTLGCDisposerRecord implements DisposerRecord {
+        private long pCfgInfo;
+        public MTLGCDisposerRecord(long pCfgInfo) {
+            this.pCfgInfo = pCfgInfo;
+        }
+        public void dispose() {
+            if (pCfgInfo != 0) {
+                deRefPConfigInfo(pCfgInfo);
+                pCfgInfo = 0;
+            }
+        }
+    }
+
+    // TODO: CGraphicsConfig doesn't implement displayChanged() yet
+    //@Override
+    public synchronized void displayChanged() {
+        //super.displayChanged();
+
+        // the context could hold a reference to a MTLSurfaceData, which in
+        // turn has a reference back to this MTLGraphicsConfig, so in order
+        // for this instance to be disposed we need to break the connection
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            MTLContext.invalidateCurrentContext();
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return ("MTLGraphicsConfig[" + getDevice().getIDstring() +
+                ",pixfmt="+pixfmt+"]");
+    }
+
+    @Override
+    public SurfaceData createSurfaceData(CPlatformView pView) {
+        return MTLSurfaceData.createData(pView);
+    }
+
+    @Override
+    public SurfaceData createSurfaceData(CFRetainedResource layer) {
+        return MTLSurfaceData.createData((MTLLayer) layer);
+    }
+
+    @Override
+    public Image createAcceleratedImage(Component target,
+                                        int width, int height)
+    {
+        ColorModel model = getColorModel(Transparency.OPAQUE);
+        WritableRaster wr = model.createCompatibleWritableRaster(width, height);
+        return new OffScreenImage(target, model, wr,
+                model.isAlphaPremultiplied());
+    }
+
+    @Override
+    public void assertOperationSupported(final int numBuffers,
+                                         final BufferCapabilities caps)
+            throws AWTException {
+        // Assume this method is never called with numBuffers != 2, as 0 is
+        // unsupported, and 1 corresponds to a SingleBufferStrategy which
+        // doesn't depend on the peer. Screen is considered as a separate
+        // "buffer".
+        if (numBuffers != 2) {
+            throw new AWTException("Only double buffering is supported");
+        }
+        final BufferCapabilities configCaps = getBufferCapabilities();
+        if (!configCaps.isPageFlipping()) {
+            throw new AWTException("Page flipping is not supported");
+        }
+        if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
+            throw new AWTException("FlipContents.PRIOR is not supported");
+        }
+    }
+
+    @Override
+    public Image createBackBuffer(final LWComponentPeer<?, ?> peer) {
+        final Rectangle r = peer.getBounds();
+        // It is possible for the component to have size 0x0, adjust it to
+        // be at least 1x1 to avoid IAE
+        final int w = Math.max(1, r.width);
+        final int h = Math.max(1, r.height);
+        final int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT
+                : Transparency.OPAQUE;
+        return new SunVolatileImage(this, w, h, transparency, null);
+    }
+
+    @Override
+    public void destroyBackBuffer(final Image backBuffer) {
+        if (backBuffer != null) {
+            backBuffer.flush();
+        }
+    }
+
+    @Override
+    public void flip(final LWComponentPeer<?, ?> peer, final Image backBuffer,
+                     final int x1, final int y1, final int x2, final int y2,
+                     final BufferCapabilities.FlipContents flipAction) {
+        final Graphics g = peer.getGraphics();
+        try {
+            g.drawImage(backBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null);
+        } finally {
+            g.dispose();
+        }
+        if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
+            final Graphics2D bg = (Graphics2D) backBuffer.getGraphics();
+            try {
+                bg.setBackground(peer.getBackground());
+                bg.clearRect(0, 0, backBuffer.getWidth(null),
+                        backBuffer.getHeight(null));
+            } finally {
+                bg.dispose();
+            }
+        }
+    }
+
+    private static class MTLBufferCaps extends BufferCapabilities {
+        public MTLBufferCaps(boolean dblBuf) {
+            super(imageCaps, imageCaps,
+                    dblBuf ? FlipContents.UNDEFINED : null);
+        }
+    }
+
+    @Override
+    public BufferCapabilities getBufferCapabilities() {
+        if (bufferCaps == null) {
+            bufferCaps = new MTLBufferCaps(isDoubleBuffered());
+        }
+        return bufferCaps;
+    }
+
+    private static class MTLImageCaps extends ImageCapabilities {
+        private MTLImageCaps() {
+            super(true);
+        }
+        public boolean isTrueVolatile() {
+            return true;
+        }
+    }
+
+    @Override
+    public ImageCapabilities getImageCapabilities() {
+        return imageCaps;
+    }
+
+    @Override
+    public VolatileImage createCompatibleVolatileImage(int width, int height,
+                                                       int transparency,
+                                                       int type) {
+        if (type != RT_TEXTURE && type != TEXTURE) {
+            return null;
+        }
+
+        SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
+                transparency, type);
+        Surface sd = vi.getDestSurface();
+        if (!(sd instanceof AccelSurface) ||
+                ((AccelSurface)sd).getType() != type)
+        {
+            vi.flush();
+            vi = null;
+        }
+
+        return vi;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
+     */
+    @Override
+    public ContextCapabilities getContextCapabilities() {
+        return mtlCaps;
+    }
+
+    @Override
+    public int getMaxTextureWidth() {
+        return Math.max(maxTextureSize / getDevice().getScaleFactor(),
+                getBounds().width);
+    }
+
+    @Override
+    public int getMaxTextureHeight() {
+        return Math.max(maxTextureSize / getDevice().getScaleFactor(),
+                getBounds().height);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,124 @@
+/*
+ * 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 sun.java2d.NullSurfaceData;
+import sun.java2d.SurfaceData;
+import sun.lwawt.LWWindowPeer;
+import sun.lwawt.macosx.CFRetainedResource;
+
+import java.awt.*;
+
+public class MTLLayer extends CFRetainedResource {
+
+    private native long nativeCreateLayer();
+    private static native void nativeSetScale(long layerPtr, double scale);
+    private static native void validate(long layerPtr, MTLSurfaceData cglsd);
+
+    private LWWindowPeer peer;
+    private int scale = 1;
+
+    private SurfaceData surfaceData; // represents intermediate buffer (texture)
+
+    public MTLLayer(LWWindowPeer peer) {
+        super(0, true);
+
+        setPtr(nativeCreateLayer());
+        this.peer = peer;
+    }
+
+    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)
+        MTLGraphicsConfig gc = (MTLGraphicsConfig)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 MTLSurfaceData) {
+            validate((MTLSurfaceData)surfaceData);
+        }
+
+        return surfaceData;
+    }
+
+    public SurfaceData getSurfaceData() {
+        return surfaceData;
+    }
+
+    public void validate(final MTLSurfaceData cglsd) {
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            execute(ptr -> validate(ptr, cglsd));
+        } 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));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskBlit.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,72 @@
+/*
+ * 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 sun.java2d.SurfaceData;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.loops.GraphicsPrimitiveMgr;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.pipe.BufferedMaskBlit;
+import sun.java2d.pipe.Region;
+
+import java.awt.*;
+
+import static sun.java2d.loops.CompositeType.SrcNoEa;
+import static sun.java2d.loops.CompositeType.SrcOver;
+import static sun.java2d.loops.SurfaceType.*;
+
+class MTLMaskBlit extends BufferedMaskBlit {
+
+    static void register() {
+        GraphicsPrimitive[] primitives = {
+                new MTLMaskBlit(IntArgb,    SrcOver),
+                new MTLMaskBlit(IntArgbPre, SrcOver),
+                new MTLMaskBlit(IntRgb,     SrcOver),
+                new MTLMaskBlit(IntRgb,     SrcNoEa),
+                new MTLMaskBlit(IntBgr,     SrcOver),
+                new MTLMaskBlit(IntBgr,     SrcNoEa),
+        };
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    private MTLMaskBlit(SurfaceType srcType,
+                        CompositeType compType)
+    {
+        super(MTLRenderQueue.getInstance(),
+                srcType, compType, MTLSurfaceData.MTLSurface);
+    }
+
+    @Override
+    protected void validateContext(SurfaceData dstData,
+                                   Composite comp, Region clip)
+    {
+        MTLSurfaceData oglDst = (MTLSurfaceData)dstData;
+        MTLContext.validateContext(oglDst, oglDst,
+                clip, comp, null, null, null,
+                MTLContext.NO_CONTEXT_FLAGS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLMaskFill.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,85 @@
+/*
+ * 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 sun.java2d.InvalidPipeException;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.loops.GraphicsPrimitiveMgr;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.pipe.BufferedMaskFill;
+
+import java.awt.*;
+
+import static sun.java2d.loops.CompositeType.SrcNoEa;
+import static sun.java2d.loops.CompositeType.SrcOver;
+import static sun.java2d.loops.SurfaceType.*;
+
+class MTLMaskFill extends BufferedMaskFill {
+
+    static void register() {
+        GraphicsPrimitive[] primitives = {
+                new MTLMaskFill(AnyColor,                  SrcOver),
+                new MTLMaskFill(OpaqueColor,               SrcNoEa),
+                new MTLMaskFill(GradientPaint,             SrcOver),
+                new MTLMaskFill(OpaqueGradientPaint,       SrcNoEa),
+                new MTLMaskFill(LinearGradientPaint,       SrcOver),
+                new MTLMaskFill(OpaqueLinearGradientPaint, SrcNoEa),
+                new MTLMaskFill(RadialGradientPaint,       SrcOver),
+                new MTLMaskFill(OpaqueRadialGradientPaint, SrcNoEa),
+                new MTLMaskFill(TexturePaint,              SrcOver),
+                new MTLMaskFill(OpaqueTexturePaint,        SrcNoEa),
+        };
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    protected MTLMaskFill(SurfaceType srcType, CompositeType compType) {
+        super(MTLRenderQueue.getInstance(),
+                srcType, compType, MTLSurfaceData.MTLSurface);
+    }
+
+    @Override
+    protected native void maskFill(int x, int y, int w, int h,
+                                   int maskoff, int maskscan, int masklen,
+                                   byte[] mask);
+
+    @Override
+    protected void validateContext(SunGraphics2D sg2d,
+                                   Composite comp, int ctxflags)
+    {
+        MTLSurfaceData dstData;
+        try {
+            dstData = (MTLSurfaceData) sg2d.surfaceData;
+        } catch (ClassCastException e) {
+            throw new InvalidPipeException("wrong surface data type: " +
+                    sg2d.surfaceData);
+        }
+
+        MTLContext.validateContext(dstData, dstData,
+                sg2d.getCompClip(), comp,
+                null, sg2d.paint, sg2d, ctxflags);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,208 @@
+/*
+ * 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 sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.loops.CompositeType;
+
+import java.awt.*;
+import java.awt.MultipleGradientPaint.ColorSpaceType;
+import java.awt.MultipleGradientPaint.CycleMethod;
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+import java.util.Map;
+
+import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER;
+import static sun.java2d.pipe.BufferedPaints.MULTI_MAX_FRACTIONS;
+
+abstract class MTLPaints {
+
+    /**
+     * Holds all registered implementations, using the corresponding
+     * SunGraphics2D.PAINT_* constant as the hash key.
+     */
+    private static Map<Integer, MTLPaints> impls =
+            new HashMap<Integer, MTLPaints>(4, 1.0f);
+
+    static {
+        impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
+        impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
+        impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
+        impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
+    }
+
+    /**
+     * Attempts to locate an implementation corresponding to the paint state
+     * of the provided SunGraphics2D object.  If no implementation can be
+     * found, or if the paint cannot be accelerated under the conditions
+     * of the SunGraphics2D, this method returns false; otherwise, returns
+     * true.
+     */
+    static boolean isValid(SunGraphics2D sg2d) {
+        MTLPaints impl = impls.get(sg2d.paintState);
+        return (impl != null && impl.isPaintValid(sg2d));
+    }
+
+    /**
+     * Returns true if this implementation is able to accelerate the
+     * Paint object associated with, and under the conditions of, the
+     * provided SunGraphics2D instance; otherwise returns false.
+     */
+    abstract boolean isPaintValid(SunGraphics2D sg2d);
+
+    /************************* GradientPaint support ****************************/
+
+    private static class Gradient extends MTLPaints {
+        private Gradient() {}
+
+        /**
+         * There are no restrictions for accelerating GradientPaint, so
+         * this method always returns true.
+         */
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            return true;
+        }
+    }
+
+    /************************** TexturePaint support ****************************/
+
+    private static class Texture extends MTLPaints {
+        private Texture() {}
+
+        /**
+         * Returns true if the given TexturePaint instance can be used by the
+         * accelerated MTLPaints.Texture implementation.  A TexturePaint is
+         * considered valid if the following conditions are met:
+         *   - the texture image dimensions are power-of-two (or the
+         *     GL_ARB_texture_non_power_of_two extension is present)
+         *   - the texture image can be (or is already) cached in an OpenGL
+         *     texture object
+         */
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            TexturePaint paint = (TexturePaint)sg2d.paint;
+            MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
+            BufferedImage bi = paint.getImage();
+
+            // see if texture-non-pow2 extension is available
+            if (!dstData.isTexNonPow2Available()) {
+                int imgw = bi.getWidth();
+                int imgh = bi.getHeight();
+
+                // verify that the texture image dimensions are pow2
+                if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) {
+                    return false;
+                }
+            }
+
+            SurfaceData srcData =
+                    dstData.getSourceSurfaceData(bi,
+                            SunGraphics2D.TRANSFORM_ISIDENT,
+                            CompositeType.SrcOver, null);
+            if (!(srcData instanceof MTLSurfaceData)) {
+                // REMIND: this is a hack that attempts to cache the system
+                //         memory image from the TexturePaint instance into an
+                //         OpenGL texture...
+                srcData =
+                        dstData.getSourceSurfaceData(bi,
+                                SunGraphics2D.TRANSFORM_ISIDENT,
+                                CompositeType.SrcOver, null);
+                if (!(srcData instanceof MTLSurfaceData)) {
+                    return false;
+                }
+            }
+
+            // verify that the source surface is actually a texture
+            MTLSurfaceData oglData = (MTLSurfaceData)srcData;
+            if (oglData.getType() != MTLSurfaceData.TEXTURE) {
+                return false;
+            }
+
+            return true;
+        }
+    }
+
+    /****************** Shared MultipleGradientPaint support ********************/
+
+    private abstract static class MultiGradient extends MTLPaints {
+        protected MultiGradient() {}
+
+        /**
+         * Returns true if the given MultipleGradientPaint instance can be
+         * used by the accelerated MTLPaints.MultiGradient implementation.
+         * A MultipleGradientPaint is considered valid if the following
+         * conditions are met:
+         *   - the number of gradient "stops" is <= MAX_FRACTIONS
+         *   - the destination has support for fragment shaders
+         */
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
+            // REMIND: ugh, this creates garbage; would be nicer if
+            // we had a MultipleGradientPaint.getNumStops() method...
+            if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {
+                return false;
+            }
+
+            MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
+            MTLGraphicsConfig gc = dstData.getMTLGraphicsConfig();
+            if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) {
+                return false;
+            }
+
+            return true;
+        }
+    }
+
+    /********************** LinearGradientPaint support *************************/
+
+    private static class LinearGradient extends MultiGradient {
+        private LinearGradient() {}
+
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
+
+            if (paint.getFractions().length == 2 &&
+                    paint.getCycleMethod() != CycleMethod.REPEAT &&
+                    paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
+            {
+                // we can delegate to the optimized two-color gradient
+                // codepath, which does not require fragment shader support
+                return true;
+            }
+
+            return super.isPaintValid(sg2d);
+        }
+    }
+
+    /********************** RadialGradientPaint support *************************/
+
+    private static class RadialGradient extends MultiGradient {
+        private RadialGradient() {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,254 @@
+/*
+ * 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 sun.awt.util.ThreadGroupUtils;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.RenderQueue;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_CONFIG;
+import static sun.java2d.pipe.BufferedOpCodes.SYNC;
+
+/**
+ * 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 MTLRenderQueue extends RenderQueue {
+
+    private static MTLRenderQueue theInstance;
+    private final QueueFlusher flusher;
+
+    private MTLRenderQueue() {
+        /*
+         * 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 MTLRenderQueue instance.  If it has not yet been
+     * initialized, this method will first construct the single instance
+     * before returning it.
+     */
+    public static synchronized MTLRenderQueue getInstance() {
+        if (theInstance == null) {
+            theInstance = new MTLRenderQueue();
+        }
+        return theInstance;
+    }
+
+    /**
+     * Flushes the single MTLRenderQueue instance synchronously.  If an
+     * MTLRenderQueue 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) {
+        MTLRenderQueue rq = getInstance();
+        rq.lock();
+        try {
+            // make sure we make the context associated with the given
+            // GraphicsConfig current before disposing the native resources
+            MTLContext.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);
+    }
+
+
+    @Override
+    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 void flushBuffer(long buf, int limit);
+
+    private void flushBuffer() {
+        // assert lock.isHeldByCurrentThread();
+        int limit = buf.position();
+        if (limit > 0) {
+            // 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;
+            notify();
+
+            // wait for flush to complete
+            while (needsFlush) {
+                try {
+                    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
+                    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/MTLRenderer.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,223 @@
+/*
+ * 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 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 java.awt.*;
+import java.awt.geom.Path2D;
+
+import static sun.java2d.pipe.BufferedOpCodes.COPY_AREA;
+
+class MTLRenderer extends BufferedRenderPipe {
+
+    MTLRenderer(RenderQueue rq) {
+        super(rq);
+    }
+
+    @Override
+    protected void validateContext(SunGraphics2D sg2d) {
+        int ctxflags =
+                sg2d.paint.getTransparency() == Transparency.OPAQUE ?
+                        MTLContext.SRC_IS_OPAQUE : MTLContext.NO_CONTEXT_FLAGS;
+        MTLSurfaceData dstData;
+        try {
+            dstData = (MTLSurfaceData)sg2d.surfaceData;
+        } catch (ClassCastException e) {
+            throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+        }
+        MTLContext.validateContext(dstData, dstData,
+                sg2d.getCompClip(), sg2d.composite,
+                null, sg2d.paint, sg2d, ctxflags);
+    }
+
+    @Override
+    protected void validateContextAA(SunGraphics2D sg2d) {
+        int ctxflags = MTLContext.NO_CONTEXT_FLAGS;
+        MTLSurfaceData dstData;
+        try {
+            dstData = (MTLSurfaceData)sg2d.surfaceData;
+        } catch (ClassCastException e) {
+            throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+        }
+        MTLContext.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 ?
+                            MTLContext.SRC_IS_OPAQUE : MTLContext.NO_CONTEXT_FLAGS;
+            MTLSurfaceData dstData;
+            try {
+                dstData = (MTLSurfaceData)sg2d.surfaceData;
+            } catch (ClassCastException e) {
+                throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
+            }
+            MTLContext.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);
+
+    MTLRenderer traceWrap() {
+        return new Tracer(this);
+    }
+
+    private class Tracer extends MTLRenderer {
+        private MTLRenderer mtlr;
+        Tracer(MTLRenderer 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("MTLFillAAParallelogram");
+                    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("MTLDrawAAParallelogram");
+                    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("MTLDrawLine");
+            mtlr.drawLine(sg2d, x1, y1, x2, y2);
+        }
+        public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
+            GraphicsPrimitive.tracePrimitive("MTLDrawRect");
+            mtlr.drawRect(sg2d, x, y, w, h);
+        }
+        protected void drawPoly(SunGraphics2D sg2d,
+                                int[] xPoints, int[] yPoints,
+                                int nPoints, boolean isClosed)
+        {
+            GraphicsPrimitive.tracePrimitive("MTLDrawPoly");
+            mtlr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed);
+        }
+        public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
+            GraphicsPrimitive.tracePrimitive("MTLFillRect");
+            mtlr.fillRect(sg2d, x, y, w, h);
+        }
+        protected void drawPath(SunGraphics2D sg2d,
+                                Path2D.Float p2df, int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("MTLDrawPath");
+            mtlr.drawPath(sg2d, p2df, transx, transy);
+        }
+        protected void fillPath(SunGraphics2D sg2d,
+                                Path2D.Float p2df, int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("MTLFillPath");
+            mtlr.fillPath(sg2d, p2df, transx, transy);
+        }
+        protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
+                                 int transx, int transy)
+        {
+            GraphicsPrimitive.tracePrimitive("MTLFillSpans");
+            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("MTLFillParallelogram");
+            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("MTLDrawParallelogram");
+            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("MTLCopyArea");
+            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/MTLSurfaceData.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,885 @@
+/*
+ * 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 sun.awt.SunHints;
+import sun.awt.image.PixelConverter;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.SurfaceDataProxy;
+import sun.java2d.loops.CompositeType;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.loops.MaskFill;
+import sun.java2d.loops.SurfaceType;
+import sun.java2d.pipe.ParallelogramPipe;
+import sun.java2d.pipe.PixelToParallelogramConverter;
+import sun.java2d.pipe.RenderBuffer;
+import sun.java2d.pipe.TextPipe;
+import sun.java2d.pipe.hw.AccelSurface;
+import sun.lwawt.macosx.CPlatformView;
+
+import java.awt.*;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_LCD_SHADER;
+import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_TEXRECT;
+import static sun.java2d.pipe.BufferedOpCodes.FLUSH_SURFACE;
+import static sun.java2d.pipe.BufferedOpCodes.SWAP_BUFFERS;
+import static sun.java2d.pipe.hw.ContextCapabilities.*;
+
+public abstract class MTLSurfaceData extends SurfaceData
+        implements AccelSurface {
+
+    /**
+     * Pixel formats
+     */
+    public static final int PF_INT_ARGB        = 0;
+    public static final int PF_INT_ARGB_PRE    = 1;
+    public static final int PF_INT_RGB         = 2;
+    public static final int PF_INT_RGBX        = 3;
+    public static final int PF_INT_BGR         = 4;
+    public static final int PF_INT_BGRX        = 5;
+    public static final int PF_USHORT_565_RGB  = 6;
+    public static final int PF_USHORT_555_RGB  = 7;
+    public static final int PF_USHORT_555_RGBX = 8;
+    public static final int PF_BYTE_GRAY       = 9;
+    public static final int PF_USHORT_GRAY     = 10;
+    public static final int PF_3BYTE_BGR       = 11;
+    /**
+     * SurfaceTypes
+     */
+
+    private static final String DESC_MTL_SURFACE = "MTL Surface";
+    private static final String DESC_MTL_SURFACE_RTT =
+            "MTL Surface (render-to-texture)";
+    private static final String DESC_MTL_TEXTURE = "MTL Texture";
+
+
+    static final SurfaceType MTLSurface =
+            SurfaceType.Any.deriveSubType(DESC_MTL_SURFACE,
+                    PixelConverter.ArgbPre.instance);
+    static final SurfaceType MTLSurfaceRTT =
+            MTLSurface.deriveSubType(DESC_MTL_SURFACE_RTT);
+    static final SurfaceType MTLTexture =
+            SurfaceType.Any.deriveSubType(DESC_MTL_TEXTURE);
+
+    protected static MTLRenderer mtlRenderPipe;
+    protected static PixelToParallelogramConverter mtlTxRenderPipe;
+    protected static ParallelogramPipe mtlAAPgramPipe;
+    protected static MTLTextRenderer mtlTextPipe;
+    protected static MTLDrawImage mtlImagePipe;
+    /** This will be true if the fbobject system property has been enabled. */
+    private static boolean isFBObjectEnabled;
+    /** This will be true if the lcdshader system property has been enabled.*/
+    private static boolean isLCDShaderEnabled;
+    /** This will be true if the biopshader system property has been enabled.*/
+    private static boolean isBIOpShaderEnabled;
+    /** This will be true if the gradshader system property has been enabled.*/
+    private static boolean isGradShaderEnabled;
+
+    static {
+        if (!GraphicsEnvironment.isHeadless()) {
+            // fbobject currently enabled by default; use "false" to disable
+            String fbo = java.security.AccessController.doPrivileged(
+                    new sun.security.action.GetPropertyAction(
+                            "java2d.metal.fbobject"));
+            isFBObjectEnabled = !"false".equals(fbo);
+
+            // lcdshader currently enabled by default; use "false" to disable
+            String lcd = java.security.AccessController.doPrivileged(
+                    new sun.security.action.GetPropertyAction(
+                            "java2d.metal.lcdshader"));
+            isLCDShaderEnabled = !"false".equals(lcd);
+
+            // biopshader currently enabled by default; use "false" to disable
+            String biop = java.security.AccessController.doPrivileged(
+                    new sun.security.action.GetPropertyAction(
+                            "java2d.metal.biopshader"));
+            isBIOpShaderEnabled = !"false".equals(biop);
+
+            // gradshader currently enabled by default; use "false" to disable
+            String grad = java.security.AccessController.doPrivileged(
+                    new sun.security.action.GetPropertyAction(
+                            "java2d.metal.gradshader"));
+            isGradShaderEnabled = !"false".equals(grad);
+
+            MTLRenderQueue rq = MTLRenderQueue.getInstance();
+            mtlImagePipe = new MTLDrawImage();
+            mtlTextPipe = new MTLTextRenderer(rq);
+            mtlRenderPipe = new MTLRenderer(rq);
+            if (GraphicsPrimitive.tracingEnabled()) {
+                mtlTextPipe = mtlTextPipe.traceWrap();
+                //The wrapped mtlRenderPipe will wrap the AA pipe as well...
+                //mtlAAPgramPipe = mtlRenderPipe.traceWrap();
+            }
+            mtlAAPgramPipe = mtlRenderPipe.getAAParallelogramPipe();
+            mtlTxRenderPipe =
+                    new PixelToParallelogramConverter(mtlRenderPipe,
+                            mtlRenderPipe,
+                            1.0, 0.25, true);
+
+            MTLBlitLoops.register();
+            MTLMaskFill.register();
+            MTLMaskBlit.register();
+        }
+    }
+
+    protected final int scale;
+    protected final int width;
+    protected final int height;
+    protected CPlatformView pView;
+    protected int type;
+    private MTLGraphicsConfig graphicsConfig;
+    // these fields are set from the native code when the surface is
+    // initialized
+    private int nativeWidth;
+    private int nativeHeight;
+
+    /**
+     * Returns the appropriate SurfaceType corresponding to the given OpenGL
+     * surface type constant (e.g. TEXTURE -> MTLTexture).
+     */
+    private static SurfaceType getCustomSurfaceType(int oglType) {
+        switch (oglType) {
+            case TEXTURE:
+                return MTLTexture;
+            case RT_TEXTURE:
+                return MTLSurfaceRTT;
+            default:
+                return MTLSurface;
+        }
+    }
+
+    static void swapBuffers(long window) {
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            RenderBuffer buf = rq.getBuffer();
+            rq.ensureCapacityAndAlignment(12, 4);
+            buf.putInt(SWAP_BUFFERS);
+            buf.putLong(window);
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    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);
+
+    protected MTLSurfaceData(MTLGraphicsConfig gc, ColorModel cm, int type,
+                             int width, int height) {
+        super(getCustomSurfaceType(type), cm);
+        this.graphicsConfig = gc;
+        this.type = type;
+        setBlitProxyKey(gc.getProxyKey());
+
+        // TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
+        scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor();
+        this.width = width * scale;
+        this.height = height * scale;
+    }
+
+    protected MTLSurfaceData(CPlatformView pView, MTLGraphicsConfig gc,
+                             ColorModel cm, int type, int width, int height)
+    {
+        this(gc, cm, type, width, height);
+        this.pView = pView;
+        this.graphicsConfig = gc;
+
+        long pConfigInfo = gc.getNativeConfigInfo();
+        long pPeerData = 0L;
+        boolean isOpaque = true;
+        if (pView != null) {
+            pPeerData = pView.getAWTView();
+            isOpaque = pView.isOpaque();
+        }
+        MTLGraphicsConfig.refPConfigInfo(pConfigInfo);
+        initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque);
+    }
+
+    protected MTLSurfaceData(MTLLayer layer, MTLGraphicsConfig 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();
+        }
+        MTLGraphicsConfig.refPConfigInfo(pConfigInfo);
+        initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
+    }
+
+    @Override //SurfaceData
+    public GraphicsConfiguration getDeviceConfiguration() {
+        return graphicsConfig;
+    }
+
+    /**
+     * Creates a SurfaceData object representing the primary (front) buffer of
+     * an on-screen Window.
+     */
+    public static MTLWindowSurfaceData createData(CPlatformView pView) {
+        MTLGraphicsConfig gc = getGC(pView);
+        return new MTLWindowSurfaceData(pView, gc);
+    }
+
+    /**
+     * Creates a SurfaceData object representing the intermediate buffer
+     * between the Java2D flusher thread and the AppKit thread.
+     */
+    public static MTLLayerSurfaceData createData(MTLLayer layer) {
+        MTLGraphicsConfig gc = getGC(layer);
+        Rectangle r = layer.getBounds();
+        return new MTLLayerSurfaceData(layer, gc, r.width, r.height);
+    }
+
+    /**
+     * Creates a SurfaceData object representing the back buffer of a
+     * double-buffered on-screen Window.
+     */
+    public static MTLOffScreenSurfaceData createData(CPlatformView pView,
+                                                     Image image, int type) {
+        MTLGraphicsConfig gc = getGC(pView);
+        Rectangle r = pView.getBounds();
+        if (type == FLIP_BACKBUFFER) {
+            return new MTLOffScreenSurfaceData(pView, gc, r.width, r.height,
+                    image, gc.getColorModel(), FLIP_BACKBUFFER);
+        } else {
+            return new MTLVSyncOffScreenSurfaceData(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 MTLOffScreenSurfaceData createData(MTLGraphicsConfig gc,
+                                                     int width, int height, ColorModel cm, Image image, int type) {
+        return new MTLOffScreenSurfaceData(null, gc, width, height, image, cm,
+                type);
+    }
+
+    public static MTLGraphicsConfig getGC(CPlatformView pView) {
+        if (pView != null) {
+            return (MTLGraphicsConfig)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 (MTLGraphicsConfig) gd.getDefaultConfiguration();
+        }
+    }
+
+    public static MTLGraphicsConfig getGC(MTLLayer layer) {
+        return (MTLGraphicsConfig)layer.getGraphicsConfiguration();
+    }
+
+    public void validate() {
+        // Overridden in MTLWindowSurfaceData below
+    }
+
+    @Override
+    public double getDefaultScaleX() {
+        return scale;
+    }
+
+    @Override
+    public double getDefaultScaleY() {
+        return scale;
+    }
+
+    protected native void clearWindow();
+
+    protected native boolean initTexture(long pData,
+                                         boolean isOpaque, boolean texNonPow2,
+                                         boolean texRect,
+                                         int width, int height);
+
+    protected native boolean initRTexture(long pData,
+                                          boolean isOpaque, boolean texNonPow2,
+                                          boolean texRect,
+                                          int width, int height);
+
+    protected native boolean initFlipBackbuffer(long pData);
+
+    @Override
+    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
+        return MTLSurfaceDataProxy.createProxy(srcData, graphicsConfig);
+    }
+
+    /**
+     * Note: This should only be called from the QFT under the AWT lock.
+     * This method is kept separate from the initSurface() method below just
+     * to keep the code a bit cleaner.
+     */
+    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 RT_TEXTURE:
+                success = initRTexture(getNativeOps(),
+                        isOpaque, isTexNonPow2Available(),
+                        isTexRectAvailable(),
+                        width, height);
+                break;
+
+            case FLIP_BACKBUFFER:
+                success = initFlipBackbuffer(getNativeOps());
+                break;
+
+            default:
+                break;
+        }
+
+        if (!success) {
+            throw new OutOfMemoryError("can't create offscreen surface");
+        }
+    }
+
+    /**
+     * Initializes the appropriate OpenGL offscreen surface based on the value
+     * of the type parameter.  If the surface creation fails for any reason,
+     * an OutOfMemoryError will be thrown.
+     */
+    protected void initSurface(final int width, final int height) {
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            switch (type) {
+                case TEXTURE:
+                case RT_TEXTURE:
+                    // need to make sure the context is current before
+                    // creating the texture or fbobject
+                    MTLContext.setScratchSurface(graphicsConfig);
+                    break;
+                default:
+                    break;
+            }
+            rq.flushAndInvokeNow(new Runnable() {
+                public void run() {
+                    initSurfaceNow(width, height);
+                }
+            });
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    /**
+     * Returns the MTLContext for the GraphicsConfig associated with this
+     * surface.
+     */
+    public final MTLContext getContext() {
+        return graphicsConfig.getContext();
+    }
+
+    /**
+     * Returns the MTLGraphicsConfig associated with this surface.
+     */
+    final MTLGraphicsConfig getMTLGraphicsConfig() {
+        return graphicsConfig;
+    }
+
+    /**
+     * Returns one of the surface type constants defined above.
+     */
+    public final int getType() {
+        return type;
+    }
+
+    /**
+     * For now, we can only render LCD text if:
+     *   - the fragment shader extension is available, and
+     *   - the source color is opaque, and
+     *   - blending is SrcOverNoEa or disabled
+     *   - and the destination is opaque
+     *
+     * Eventually, we could enhance the native OGL text rendering code
+     * and remove the above restrictions, but that would require significantly
+     * more code just to support a few uncommon cases.
+     */
+    public boolean canRenderLCDText(SunGraphics2D sg2d) {
+        return
+                graphicsConfig.isCapPresent(CAPS_EXT_LCD_SHADER) &&
+                        sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&
+                        sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
+                        (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY ||
+                                (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA && canHandleComposite(sg2d.composite)));
+    }
+
+    private boolean canHandleComposite(Composite c) {
+        if (c instanceof AlphaComposite) {
+            AlphaComposite ac = (AlphaComposite)c;
+
+            return ac.getRule() == AlphaComposite.SRC_OVER && ac.getAlpha() >= 1f;
+        }
+        return false;
+    }
+
+    public void validatePipe(SunGraphics2D sg2d) {
+        TextPipe textpipe;
+        boolean validated = false;
+
+        // MTLTextRenderer 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.)
+
+        if (/* CompositeType.SrcNoEa (any color) */
+                (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
+                        sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR)         ||
+
+                        /* CompositeType.SrcOver (any color) */
+                        (sg2d.compositeState == SunGraphics2D.COMP_ALPHA   &&
+                                sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
+                                (((AlphaComposite)sg2d.composite).getRule() ==
+                                        AlphaComposite.SRC_OVER))                                 ||
+
+                        /* CompositeType.Xor (any color) */
+                        (sg2d.compositeState == SunGraphics2D.COMP_XOR &&
+                                sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR))
+        {
+            textpipe = mtlTextPipe;
+        } else {
+            // do this to initialize textpipe correctly; we will attempt
+            // to override the non-text pipes below
+            super.validatePipe(sg2d);
+            textpipe = sg2d.textpipe;
+            validated = true;
+        }
+
+        PixelToParallelogramConverter txPipe = null;
+        MTLRenderer 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 (MTLPaints.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 {
+            if (!validated) {
+                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
+        sg2d.imagepipe = mtlImagePipe;
+    }
+
+    @Override
+    protected MaskFill getMaskFill(SunGraphics2D sg2d) {
+        if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
+            /*
+             * We can only accelerate non-Color MaskFill operations if
+             * all of the following conditions hold true:
+             *   - there is an implementation for the given paintState
+             *   - the current Paint can be accelerated for this destination
+             *   - multitexturing is available (since we need to modulate
+             *     the alpha mask texture with the paint texture)
+             *
+             * In all other cases, we return null, in which case the
+             * validation code will choose a more general software-based loop.
+             */
+            if (!MTLPaints.isValid(sg2d) ||
+                    !graphicsConfig.isCapPresent(CAPS_MULTITEXTURE))
+            {
+                return null;
+            }
+        }
+        return super.getMaskFill(sg2d);
+    }
+
+    public void flush() {
+        invalidate();
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            // make sure we have a current context before
+            // disposing the native resources (e.g. texture object)
+            MTLContext.setScratchSurface(graphicsConfig);
+
+            RenderBuffer buf = rq.getBuffer();
+            rq.ensureCapacityAndAlignment(12, 4);
+            buf.putInt(FLUSH_SURFACE);
+            buf.putLong(getNativeOps());
+
+            // this call is expected to complete synchronously, so flush now
+            rq.flushNow();
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    /**
+     * Returns true if OpenGL textures can have non-power-of-two dimensions
+     * when using the basic GL_TEXTURE_2D target.
+     */
+    boolean isTexNonPow2Available() {
+        return graphicsConfig.isCapPresent(CAPS_TEXNONPOW2);
+    }
+
+    /**
+     * Returns true if OpenGL textures can have non-power-of-two dimensions
+     * when using the GL_TEXTURE_RECTANGLE_ARB target (only available when the
+     * GL_ARB_texture_rectangle extension is present).
+     */
+    boolean isTexRectAvailable() {
+        return graphicsConfig.isCapPresent(CAPS_EXT_TEXRECT);
+    }
+
+    /**
+     * Returns true if the surface is an on-screen window surface or
+     * a FBO texture attached to an on-screen CALayer.
+     *
+     * Needed by Mac OS X port.
+     */
+    public boolean isOnScreen() {
+        return getType() == WINDOW;
+    }
+
+    private native int getTextureTarget(long pData);
+
+    private native int getTextureID(long pData);
+
+    /**
+     * 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 native resource of specified {@code resType} associated with
+     * this surface.
+     *
+     * Specifically, for {@code MTLSurfaceData} this method returns the
+     * the following:
+     * <pre>
+     * TEXTURE              - texture id
+     * </pre>
+     *
+     * Note: the resource returned by this method is only valid on the rendering
+     * thread.
+     *
+     * @return native resource of specified type or 0L if
+     * such resource doesn't exist or can not be retrieved.
+     * @see AccelSurface#getNativeResource
+     */
+    public long getNativeResource(int resType) {
+        if (resType == TEXTURE) {
+            return getTextureID();
+        }
+        return 0L;
+    }
+
+    public Raster getRaster(int x, int y, int w, int h) {
+        throw new InternalError("not implemented yet");
+    }
+
+    @Override
+    public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
+                            int dx, int dy) {
+        if (sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
+            return false;
+        }
+        mtlRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
+        return true;
+    }
+
+    public Rectangle getNativeBounds() {
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            return new Rectangle(nativeWidth, nativeHeight);
+        } finally {
+            rq.unlock();
+        }
+    }
+
+    public static class MTLWindowSurfaceData extends MTLSurfaceData {
+
+        public MTLWindowSurfaceData(CPlatformView pView,
+                                    MTLGraphicsConfig 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();
+        }
+
+        public void validate() {
+            MTLRenderQueue rq = MTLRenderQueue.getInstance();
+            rq.lock();
+            try {
+                rq.flushAndInvokeNow(() -> {
+                    Rectangle peerBounds = pView.getBounds();
+                    validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque());
+                });
+            } finally {
+                rq.unlock();
+            }
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            clearWindow();
+        }
+    }
+
+    /**
+     * A surface which implements an intermediate buffer between
+     * the Java2D flusher thread and the AppKit thread.
+     *
+     * This surface serves as a buffer attached to a MTLLayer and
+     * the layer redirects all painting to the buffer's graphics.
+     */
+    public static class MTLLayerSurfaceData extends MTLSurfaceData {
+
+        private MTLLayer layer;
+
+        public MTLLayerSurfaceData(MTLLayer layer, MTLGraphicsConfig 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
+        public 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();
+        }
+    }
+
+    /**
+     * A surface which implements a v-synced flip back-buffer with COPIED
+     * FlipContents.
+     *
+     * This surface serves as a back-buffer to the outside world, while it is
+     * actually an offscreen surface. When the BufferStrategy this surface
+     * belongs to is showed, it is first copied to the real private
+     * FLIP_BACKBUFFER, which is then flipped.
+     */
+    public static class MTLVSyncOffScreenSurfaceData extends
+            MTLOffScreenSurfaceData {
+        private MTLOffScreenSurfaceData flipSurface;
+
+        public MTLVSyncOffScreenSurfaceData(CPlatformView pView,
+                                            MTLGraphicsConfig gc, int width, int height, Image image,
+                                            ColorModel cm, int type) {
+            super(pView, gc, width, height, image, cm, type);
+            flipSurface = MTLSurfaceData.createData(pView, image,
+                    FLIP_BACKBUFFER);
+        }
+
+        public SurfaceData getFlipSurface() {
+            return flipSurface;
+        }
+
+        @Override
+        public void flush() {
+            flipSurface.flush();
+            super.flush();
+        }
+    }
+
+    public static class MTLOffScreenSurfaceData extends MTLSurfaceData {
+        private Image offscreenImage;
+
+        public MTLOffScreenSurfaceData(CPlatformView pView,
+                                       MTLGraphicsConfig 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;
+        }
+    }
+
+
+    // additional cleanup
+    private static native void destroyCGLContext(long ctx);
+
+    public static void destroyOGLContext(long ctx) {
+        if (ctx != 0L) {
+            destroyCGLContext(ctx);
+        }
+    }
+
+    public static void dispose(long pData, long pConfigInfo) {
+        MTLGraphicsConfig.deRefPConfigInfo(pConfigInfo);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLSurfaceDataProxy.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,84 @@
+/*
+ * 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 sun.java2d.SurfaceData;
+import sun.java2d.SurfaceDataProxy;
+import sun.java2d.loops.CompositeType;
+
+import java.awt.*;
+
+/**
+ * The proxy class contains the logic for when to replace a
+ * SurfaceData with a cached OGL Texture and the code to create
+ * the accelerated surfaces.
+ */
+public class MTLSurfaceDataProxy extends SurfaceDataProxy {
+    public static SurfaceDataProxy createProxy(SurfaceData srcData,
+                                               MTLGraphicsConfig dstConfig)
+    {
+        if (srcData instanceof MTLSurfaceData) {
+            // srcData must be a VolatileImage which either matches
+            // our pixel format or not - either way we do not cache it...
+            return UNCACHED;
+        }
+
+        return new MTLSurfaceDataProxy(dstConfig, srcData.getTransparency());
+    }
+
+    MTLGraphicsConfig oglgc;
+    int transparency;
+
+    public MTLSurfaceDataProxy(MTLGraphicsConfig oglgc, int transparency) {
+        this.oglgc = oglgc;
+        this.transparency = transparency;
+    }
+
+    @Override
+    public SurfaceData validateSurfaceData(SurfaceData srcData,
+                                           SurfaceData cachedData,
+                                           int w, int h)
+    {
+        if (cachedData == null) {
+            try {
+                cachedData = oglgc.createManagedSurface(w, h, transparency);
+            } catch (OutOfMemoryError er) {
+                return null;
+            }
+        }
+        return cachedData;
+    }
+
+    @Override
+    public boolean isSupportedOperation(SurfaceData srcData,
+                                        int txtype,
+                                        CompositeType comp,
+                                        Color bgColor)
+    {
+        return comp.isDerivedFrom(CompositeType.AnyAlpha) &&
+                (bgColor == null || transparency == Transparency.OPAQUE);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLTextRenderer.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,72 @@
+/*
+ * 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
+ * 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.font.GlyphList;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.loops.GraphicsPrimitive;
+import sun.java2d.pipe.BufferedTextPipe;
+import sun.java2d.pipe.RenderQueue;
+
+import java.awt.*;
+
+class MTLTextRenderer extends BufferedTextPipe {
+
+    MTLTextRenderer(RenderQueue rq) {
+        super(rq);
+    }
+
+    @Override
+    protected native void drawGlyphList(int numGlyphs, boolean usePositions,
+                                        boolean subPixPos, boolean rgbOrder,
+                                        int lcdContrast,
+                                        float glOrigX, float glOrigY,
+                                        long[] images, float[] positions);
+
+    @Override
+    protected void validateContext(SunGraphics2D sg2d, Composite comp) {
+        // assert rq.lock.isHeldByCurrentThread();
+        MTLSurfaceData oglDst = (MTLSurfaceData)sg2d.surfaceData;
+        MTLContext.validateContext(oglDst, oglDst,
+                sg2d.getCompClip(), comp,
+                null, sg2d.paint, sg2d,
+                MTLContext.NO_CONTEXT_FLAGS);
+    }
+
+    MTLTextRenderer traceWrap() {
+        return new Tracer(this);
+    }
+
+    private static class Tracer extends MTLTextRenderer {
+        Tracer(MTLTextRenderer mtltr) {
+            super(mtltr.rq);
+        }
+        protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
+            GraphicsPrimitive.tracePrimitive("MTLDrawGlyphs");
+            super.drawGlyphList(sg2d, gl);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLUtilities.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,326 @@
+/*
+ * 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
+ * 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.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.pipe.Region;
+
+import java.awt.*;
+
+/**
+ * This class contains a number of static utility methods that may be
+ * called (via reflection) by a third-party library in order
+ * to interoperate with the metal-based Java 2D pipeline.
+ *
+ */
+class MTLUtilities {
+
+    /**
+     * These OGL-specific surface type constants are the same as those
+     * defined in the MTLSurfaceData class and are duplicated here so that
+     * clients of this API can access them more easily via reflection.
+     */
+    public static final int UNDEFINED       = MTLSurfaceData.UNDEFINED;
+    public static final int WINDOW          = MTLSurfaceData.WINDOW;
+    public static final int TEXTURE         = MTLSurfaceData.TEXTURE;
+    public static final int FLIP_BACKBUFFER = MTLSurfaceData.FLIP_BACKBUFFER;
+    public static final int RT_TEXTURE      = MTLSurfaceData.RT_TEXTURE;
+
+    private MTLUtilities() {
+    }
+
+    /**
+     * Returns true if the current thread is the OGL QueueFlusher thread.
+     */
+    public static boolean isQueueFlusherThread() {
+        return MTLRenderQueue.isQueueFlusherThread();
+    }
+
+    /**
+     * Invokes the given Runnable on the MTL QueueFlusher thread with the
+     * MTL context corresponding to the given Graphics object made
+     * current.  It is legal for MTL code executed in the given
+     * Runnable to change the current MTL context; it will be reset
+     * once the Runnable completes.  No guarantees are made as to the
+     * state of the MTL context of the Graphics object; for
+     *
+     * In order to avoid deadlock, it is important that the given Runnable
+     * does not attempt to acquire the AWT lock, as that will be handled
+     * automatically as part of the {@code rq.flushAndInvokeNow()} step.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * if null, the step making a context current to the destination surface
+     * will be skipped
+     * @param r the action to be performed on the QFT; cannot be null
+     * @return true if the operation completed successfully, or false if
+     * there was any problem making a context current to the surface
+     * associated with the given Graphics object
+     */
+    public static boolean invokeWithMTLContextCurrent(Graphics g, Runnable r) {
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            if (g != null) {
+                if (!(g instanceof SunGraphics2D)) {
+                    return false;
+                }
+                SurfaceData sData = ((SunGraphics2D)g).surfaceData;
+                if (!(sData instanceof MTLSurfaceData)) {
+                    return false;
+                }
+
+                // make a context current to the destination surface
+                MTLContext.validateContext((MTLSurfaceData)sData);
+            }
+
+            // invoke the given runnable on the QFT
+            rq.flushAndInvokeNow(r);
+
+            // invalidate the current context so that the next time we render
+            // with Java 2D, the context state will be completely revalidated
+            MTLContext.invalidateCurrentContext();
+        } finally {
+            rq.unlock();
+        }
+
+        return true;
+    }
+
+    /**
+     * Invokes the given Runnable on the MTL QueueFlusher thread with the
+     * "shared" MTL context (corresponding to the given
+     * GraphicsConfiguration object) made current.  This method is typically
+     * used when the Runnable needs a current context to complete its
+     * operation, but does not require that the context be made current to
+     * a particular surface.  For example, an application may call this
+     * method so that the given Runnable can query the OpenGL capabilities
+     * of the given GraphicsConfiguration, without making a context current
+     * to a dummy surface (or similar hacky techniques).
+     *
+     * In order to avoid deadlock, it is important that the given Runnable
+     * does not attempt to acquire the AWT lock, as that will be handled
+     * automatically as part of the {@code rq.flushAndInvokeNow()} step.
+     *
+     * @param config the GraphicsConfiguration object whose "shared"
+     * context will be made current during this operation; if this value is
+     * null or if MTL is not enabled for the GraphicsConfiguration, this
+     * method will return false
+     * @param r the action to be performed on the QFT; cannot be null
+     * @return true if the operation completed successfully, or false if
+     * there was any problem making the shared context current
+     */
+    public static boolean
+    invokeWithMTLSharedContextCurrent(GraphicsConfiguration config,
+                                      Runnable r)
+    {
+        if (!(config instanceof MTLGraphicsConfig)) {
+            return false;
+        }
+
+        MTLRenderQueue rq = MTLRenderQueue.getInstance();
+        rq.lock();
+        try {
+            // make the "shared" context current for the given GraphicsConfig
+            MTLContext.setScratchSurface((MTLGraphicsConfig)config);
+
+            // invoke the given runnable on the QFT
+            rq.flushAndInvokeNow(r);
+
+            // invalidate the current context so that the next time we render
+            // with Java 2D, the context state will be completely revalidated
+            MTLContext.invalidateCurrentContext();
+        } finally {
+            rq.unlock();
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the Rectangle describing the MTL viewport on the
+     * Java 2D surface associated with the given Graphics object and
+     * component width and height. When a third-party library is
+     * performing MTL rendering directly into the visible region of
+     * the associated surface, this viewport helps the application
+     * position the MTL output correctly on that surface.
+     *
+     * Note that the x/y values in the returned Rectangle object represent
+     * the lower-left corner of the viewport region, relative to the
+     * lower-left corner of the given surface.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * cannot be null
+     * @param componentWidth width of the component to be painted
+     * @param componentHeight height of the component to be painted
+     * @return a Rectangle describing the MTL viewport for the given
+     * destination surface and component dimensions, or null if the given
+     * Graphics object is invalid
+     */
+    public static Rectangle getMTLViewport(Graphics g,
+                                           int componentWidth,
+                                           int componentHeight)
+    {
+        if (!(g instanceof SunGraphics2D)) {
+            return null;
+        }
+
+        SunGraphics2D sg2d = (SunGraphics2D)g;
+        SurfaceData sData = sg2d.surfaceData;
+
+        // this is the upper-left origin of the region to be painted,
+        // relative to the upper-left origin of the surface
+        // (in Java2D coordinates)
+        int x0 = sg2d.transX;
+        int y0 = sg2d.transY;
+
+        // this is the lower-left origin of the region to be painted,
+        // relative to the lower-left origin of the surface
+        // (in OpenGL coordinates)
+        Rectangle surfaceBounds = sData.getBounds();
+        int x1 = x0;
+        int y1 = surfaceBounds.height - (y0 + componentHeight);
+
+        return new Rectangle(x1, y1, componentWidth, componentHeight);
+    }
+
+    /**
+     * Returns the Rectangle describing the MTL scissor box on the
+     * Java 2D surface associated with the given Graphics object.  When a
+     * third-party library is performing MTL rendering directly
+     * into the visible region of the associated surface, this scissor box
+     * must be set to avoid drawing over existing rendering results.
+     *
+     * Note that the x/y values in the returned Rectangle object represent
+     * the lower-left corner of the scissor region, relative to the
+     * lower-left corner of the given surface.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * cannot be null
+     * @return a Rectangle describing the MTL scissor box for the given
+     * Graphics object and corresponding destination surface, or null if the
+     * given Graphics object is invalid or the clip region is non-rectangular
+     */
+    public static Rectangle getOGLScissorBox(Graphics g) {
+        if (!(g instanceof SunGraphics2D)) {
+            return null;
+        }
+
+        SunGraphics2D sg2d = (SunGraphics2D)g;
+        SurfaceData sData = sg2d.surfaceData;
+        Region r = sg2d.getCompClip();
+        if (!r.isRectangular()) {
+            // caller probably doesn't know how to handle shape clip
+            // appropriately, so just return null (Swing currently never
+            // sets a shape clip, but that could change in the future)
+            return null;
+        }
+
+        // this is the upper-left origin of the scissor box relative to the
+        // upper-left origin of the surface (in Java 2D coordinates)
+        int x0 = r.getLoX();
+        int y0 = r.getLoY();
+
+        // this is the width and height of the scissor region
+        int w = r.getWidth();
+        int h = r.getHeight();
+
+        // this is the lower-left origin of the scissor box relative to the
+        // lower-left origin of the surface (in OpenGL coordinates)
+        Rectangle surfaceBounds = sData.getBounds();
+        int x1 = x0;
+        int y1 = surfaceBounds.height - (y0 + h);
+
+        return new Rectangle(x1, y1, w, h);
+    }
+
+    /**
+     * Returns an Object identifier for the Java 2D surface associated with
+     * the given Graphics object.  This identifier may be used to determine
+     * whether the surface has changed since the last invocation of this
+     * operation, and thereby whether the MTL state corresponding to the
+     * old surface must be destroyed and recreated.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * cannot be null
+     * @return an identifier for the surface associated with the given
+     * Graphics object, or null if the given Graphics object is invalid
+     */
+    public static Object getMTLSurfaceIdentifier(Graphics g) {
+        if (!(g instanceof SunGraphics2D)) {
+            return null;
+        }
+        return ((SunGraphics2D)g).surfaceData;
+    }
+
+    /**
+     * Returns one of the MTL-specific surface type constants (defined in
+     * this class), which describes the surface associated with the given
+     * Graphics object.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * cannot be null
+     * @return a constant that describes the surface associated with the
+     * given Graphics object; if the given Graphics object is invalid (i.e.
+     * is not associated with an OpenGL surface) this method will return
+     * {@code MTLUtilities.UNDEFINED}
+     */
+    public static int getMTLSurfaceType(Graphics g) {
+        if (!(g instanceof SunGraphics2D)) {
+            return UNDEFINED;
+        }
+        SurfaceData sData = ((SunGraphics2D)g).surfaceData;
+        if (!(sData instanceof MTLSurfaceData)) {
+            return UNDEFINED;
+        }
+        return ((MTLSurfaceData)sData).getType();
+    }
+
+    /**
+     * Returns the MTL texture target constant (either GL_TEXTURE_2D
+     * or GL_TEXTURE_RECTANGLE_ARB) for the surface associated with the
+     * given Graphics object.  This method is only useful for those surface
+     * types that are backed by an MTL texture, namely {@code TEXTURE},
+     * {@code RT_TEXTURE}, and (on Windows only) {@code PBUFFER}.
+     *
+     * @param g the Graphics object for the corresponding destination surface;
+     * cannot be null
+     * @return the texture target constant for the surface associated with the
+     * given Graphics object; if the given Graphics object is invalid (i.e.
+     * is not associated with an MTL surface), or the associated surface
+     * is not backed by an OpenGL texture, this method will return zero.
+     */
+    public static int getMTLTextureType(Graphics g) {
+        if (!(g instanceof SunGraphics2D)) {
+            return 0;
+        }
+        SurfaceData sData = ((SunGraphics2D)g).surfaceData;
+        if (!(sData instanceof MTLSurfaceData)) {
+            return 0;
+        }
+        return ((MTLSurfaceData)sData).getTextureTarget();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/classes/sun/java2d/metal/MTLVolatileSurfaceManager.java	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,146 @@
+/*
+ * 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 sun.awt.AWTAccessor;
+import sun.awt.AWTAccessor.ComponentAccessor;
+import sun.awt.image.SunVolatileImage;
+import sun.awt.image.VolatileSurfaceManager;
+import sun.java2d.BackBufferCapsProvider;
+import sun.java2d.SurfaceData;
+import sun.java2d.opengl.OGLSurfaceData;
+import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
+
+import java.awt.*;
+import java.awt.image.ColorModel;
+import java.awt.peer.ComponentPeer;
+
+import static java.awt.BufferCapabilities.FlipContents.COPIED;
+//import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_EXT_FBOBJECT;
+import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.VSYNC_ON;
+
+public class MTLVolatileSurfaceManager extends VolatileSurfaceManager {
+
+    private final boolean accelerationEnabled;
+
+    public MTLVolatileSurfaceManager(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();
+        MTLGraphicsConfig gc = (MTLGraphicsConfig) vImg.getGraphicsConfig();
+        accelerationEnabled = true;
+                //gc.isCapPresent(CAPS_EXT_FBOBJECT)
+                //&& transparency != Transparency.BITMASK;
+    }
+
+    protected boolean isAccelerationEnabled() {
+        return accelerationEnabled;
+    }
+
+    /**
+     * 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 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 = MTLSurfaceData.createData(peer, vImg, FLIP_BACKBUFFER);
+            } else {
+                MTLGraphicsConfig gc =
+                    (MTLGraphicsConfig)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 RT_TEXTURE
+                if (type == OGLSurfaceData.UNDEFINED) {
+                    type = OGLSurfaceData.FBOBJECT;
+                }
+                if (createVSynced) {
+                    // TODO: modify parameter to delegate
+//                  sData = MTLSurfaceData.createData(peer, vImg, type);
+                } else {
+                    sData = MTLSurfaceData.createData(gc,
+                                                      vImg.getWidth(),
+                                                      vImg.getHeight(),
+                                                      cm, vImg, type);
+                }
+            }
+        } catch (NullPointerException ex) {
+            sData = null;
+        } catch (OutOfMemoryError er) {
+            sData = null;
+        }
+
+        return sData;
+    }
+
+    @Override
+    protected boolean isConfigValid(GraphicsConfiguration gc) {
+        return ((gc == null) || (gc == vImg.getGraphicsConfig()));
+    }
+
+    @Override
+    public void initContents() {
+        if (vImg.getForcedAccelSurfaceType() != OGLSurfaceData.TEXTURE) {
+            super.initContents();
+        }
+    }
+}
+
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalBlitLoops.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,952 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.java2d.metal;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Transparency;
-import java.awt.geom.AffineTransform;
-import java.awt.image.AffineTransformOp;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.lang.ref.WeakReference;
-import sun.java2d.SurfaceData;
-import sun.java2d.loops.Blit;
-import sun.java2d.loops.CompositeType;
-import sun.java2d.loops.GraphicsPrimitive;
-import sun.java2d.loops.GraphicsPrimitiveMgr;
-import sun.java2d.loops.ScaledBlit;
-import sun.java2d.loops.SurfaceType;
-import sun.java2d.loops.TransformBlit;
-import sun.java2d.pipe.Region;
-import sun.java2d.pipe.RenderBuffer;
-import sun.java2d.pipe.RenderQueue;
-import static sun.java2d.pipe.BufferedOpCodes.*;
-import java.lang.annotation.Native;
-
-final class MetalBlitLoops {
-
-    static void register() {
-        /*Blit blitIntArgbPreToSurface =
-                new OGLSwToSurfaceBlit(SurfaceType.IntArgbPre,
-                        OGLSurfaceData.PF_INT_ARGB_PRE);
-        Blit blitIntArgbPreToTexture =
-                new OGLSwToTextureBlit(SurfaceType.IntArgbPre,
-                        OGLSurfaceData.PF_INT_ARGB_PRE);
-        TransformBlit transformBlitIntArgbPreToSurface =
-                new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre,
-                        OGLSurfaceData.PF_INT_ARGB_PRE);
-        OGLSurfaceToSwBlit blitSurfaceToIntArgbPre =
-                new OGLSurfaceToSwBlit(SurfaceType.IntArgbPre,
-                        OGLSurfaceData.PF_INT_ARGB_PRE);*/
-
-        GraphicsPrimitive[] primitives = {
-                // surface->surface ops
-                new MetalSurfaceToSurfaceBlit(),
-                /*new OGLSurfaceToSurfaceBlit(),
-                new OGLSurfaceToSurfaceScale(),
-                new OGLSurfaceToSurfaceTransform(),
-
-                // render-to-texture surface->surface ops
-                new OGLRTTSurfaceToSurfaceBlit(),
-                new OGLRTTSurfaceToSurfaceScale(),
-                new OGLRTTSurfaceToSurfaceTransform(),
-
-                // surface->sw ops
-                new OGLSurfaceToSwBlit(SurfaceType.IntArgb,
-                        OGLSurfaceData.PF_INT_ARGB),
-                blitSurfaceToIntArgbPre,
-
-                // sw->surface ops
-                blitIntArgbPreToSurface,
-                new OGLSwToSurfaceBlit(SurfaceType.IntRgb,
-                        OGLSurfaceData.PF_INT_RGB),
-                new OGLSwToSurfaceBlit(SurfaceType.IntRgbx,
-                        OGLSurfaceData.PF_INT_RGBX),
-                new OGLSwToSurfaceBlit(SurfaceType.IntBgr,
-                        OGLSurfaceData.PF_INT_BGR),
-                new OGLSwToSurfaceBlit(SurfaceType.IntBgrx,
-                        OGLSurfaceData.PF_INT_BGRX),
-                new OGLSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
-                        OGLSurfaceData.PF_3BYTE_BGR),
-                new OGLSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
-                        OGLSurfaceData.PF_USHORT_565_RGB),
-                new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
-                        OGLSurfaceData.PF_USHORT_555_RGB),
-                new OGLSwToSurfaceBlit(SurfaceType.Ushort555Rgbx,
-                        OGLSurfaceData.PF_USHORT_555_RGBX),
-                new OGLSwToSurfaceBlit(SurfaceType.ByteGray,
-                        OGLSurfaceData.PF_BYTE_GRAY),
-                new OGLSwToSurfaceBlit(SurfaceType.UshortGray,
-                        OGLSurfaceData.PF_USHORT_GRAY),
-                new OGLGeneralBlit(OGLSurfaceData.OpenGLSurface,
-                        CompositeType.AnyAlpha,
-                        blitIntArgbPreToSurface),
-
-                new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface,
-                        blitSurfaceToIntArgbPre,
-                        blitSurfaceToIntArgbPre,
-                        blitIntArgbPreToSurface),
-                new OGLAnyCompositeBlit(SurfaceType.Any,
-                        null,
-                        blitSurfaceToIntArgbPre,
-                        blitIntArgbPreToSurface),
-
-                new OGLSwToSurfaceScale(SurfaceType.IntRgb,
-                        OGLSurfaceData.PF_INT_RGB),
-                new OGLSwToSurfaceScale(SurfaceType.IntRgbx,
-                        OGLSurfaceData.PF_INT_RGBX),
-                new OGLSwToSurfaceScale(SurfaceType.IntBgr,
-                        OGLSurfaceData.PF_INT_BGR),
-                new OGLSwToSurfaceScale(SurfaceType.IntBgrx,
-                        OGLSurfaceData.PF_INT_BGRX),
-                new OGLSwToSurfaceScale(SurfaceType.ThreeByteBgr,
-                        OGLSurfaceData.PF_3BYTE_BGR),
-                new OGLSwToSurfaceScale(SurfaceType.Ushort565Rgb,
-                        OGLSurfaceData.PF_USHORT_565_RGB),
-                new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgb,
-                        OGLSurfaceData.PF_USHORT_555_RGB),
-                new OGLSwToSurfaceScale(SurfaceType.Ushort555Rgbx,
-                        OGLSurfaceData.PF_USHORT_555_RGBX),
-                new OGLSwToSurfaceScale(SurfaceType.ByteGray,
-                        OGLSurfaceData.PF_BYTE_GRAY),
-                new OGLSwToSurfaceScale(SurfaceType.UshortGray,
-                        OGLSurfaceData.PF_USHORT_GRAY),
-                new OGLSwToSurfaceScale(SurfaceType.IntArgbPre,
-                        OGLSurfaceData.PF_INT_ARGB_PRE),
-
-                new OGLSwToSurfaceTransform(SurfaceType.IntRgb,
-                        OGLSurfaceData.PF_INT_RGB),
-                new OGLSwToSurfaceTransform(SurfaceType.IntRgbx,
-                        OGLSurfaceData.PF_INT_RGBX),
-                new OGLSwToSurfaceTransform(SurfaceType.IntBgr,
-                        OGLSurfaceData.PF_INT_BGR),
-                new OGLSwToSurfaceTransform(SurfaceType.IntBgrx,
-                        OGLSurfaceData.PF_INT_BGRX),
-                new OGLSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
-                        OGLSurfaceData.PF_3BYTE_BGR),
-                new OGLSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
-                        OGLSurfaceData.PF_USHORT_565_RGB),
-                new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
-                        OGLSurfaceData.PF_USHORT_555_RGB),
-                new OGLSwToSurfaceTransform(SurfaceType.Ushort555Rgbx,
-                        OGLSurfaceData.PF_USHORT_555_RGBX),
-                new OGLSwToSurfaceTransform(SurfaceType.ByteGray,
-                        OGLSurfaceData.PF_BYTE_GRAY),
-                new OGLSwToSurfaceTransform(SurfaceType.UshortGray,
-                        OGLSurfaceData.PF_USHORT_GRAY),
-                transformBlitIntArgbPreToSurface,
-
-                new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
-
-                // texture->surface ops
-                new OGLTextureToSurfaceBlit(),
-                new OGLTextureToSurfaceScale(),
-                new OGLTextureToSurfaceTransform(),
-
-                // sw->texture ops
-                blitIntArgbPreToTexture,
-                new OGLSwToTextureBlit(SurfaceType.IntRgb,
-                        OGLSurfaceData.PF_INT_RGB),
-                new OGLSwToTextureBlit(SurfaceType.IntRgbx,
-                        OGLSurfaceData.PF_INT_RGBX),
-                new OGLSwToTextureBlit(SurfaceType.IntBgr,
-                        OGLSurfaceData.PF_INT_BGR),
-                new OGLSwToTextureBlit(SurfaceType.IntBgrx,
-                        OGLSurfaceData.PF_INT_BGRX),
-                new OGLSwToTextureBlit(SurfaceType.ThreeByteBgr,
-                        OGLSurfaceData.PF_3BYTE_BGR),
-                new OGLSwToTextureBlit(SurfaceType.Ushort565Rgb,
-                        OGLSurfaceData.PF_USHORT_565_RGB),
-                new OGLSwToTextureBlit(SurfaceType.Ushort555Rgb,
-                        OGLSurfaceData.PF_USHORT_555_RGB),
-                new OGLSwToTextureBlit(SurfaceType.Ushort555Rgbx,
-                        OGLSurfaceData.PF_USHORT_555_RGBX),
-                new OGLSwToTextureBlit(SurfaceType.ByteGray,
-                        OGLSurfaceData.PF_BYTE_GRAY),
-                new OGLSwToTextureBlit(SurfaceType.UshortGray,
-                        OGLSurfaceData.PF_USHORT_GRAY),
-                new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture,
-                        CompositeType.SrcNoEa,
-                        blitIntArgbPreToTexture),*/
-        };
-        GraphicsPrimitiveMgr.register(primitives);
-    }
-
-    /**
-     * The following offsets are used to pack the parameters in
-     * createPackedParams().  (They are also used at the native level when
-     * unpacking the params.)
-     */
-    @Native private static final int OFFSET_SRCTYPE = 16;
-    @Native private static final int OFFSET_HINT    =  8;
-    @Native private static final int OFFSET_TEXTURE =  3;
-    @Native private static final int OFFSET_RTT     =  2;
-    @Native private static final int OFFSET_XFORM   =  1;
-    @Native private static final int OFFSET_ISOBLIT =  0;
-
-    /**
-     * Packs the given parameters into a single int value in order to save
-     * space on the rendering queue.
-     */
-    private static int createPackedParams(boolean isoblit, boolean texture,
-                                          boolean rtt, boolean xform,
-                                          int hint, int srctype)
-    {
-        return
-                ((srctype           << OFFSET_SRCTYPE) |
-                        (hint              << OFFSET_HINT   ) |
-                        ((texture ? 1 : 0) << OFFSET_TEXTURE) |
-                        ((rtt     ? 1 : 0) << OFFSET_RTT    ) |
-                        ((xform   ? 1 : 0) << OFFSET_XFORM  ) |
-                        ((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
-    }
-
-    /**
-     * Enqueues a BLIT operation with the given parameters.  Note that the
-     * RenderQueue lock must be held before calling this method.
-     */
-    private static void enqueueBlit(RenderQueue rq,
-                                    SurfaceData src, SurfaceData dst,
-                                    int packedParams,
-                                    int sx1, int sy1,
-                                    int sx2, int sy2,
-                                    double dx1, double dy1,
-                                    double dx2, double dy2)
-    {
-        // assert rq.lock.isHeldByCurrentThread();
-        RenderBuffer buf = rq.getBuffer();
-        rq.ensureCapacityAndAlignment(72, 24);
-        buf.putInt(BLIT);
-        buf.putInt(packedParams);
-        buf.putInt(sx1).putInt(sy1);
-        buf.putInt(sx2).putInt(sy2);
-        buf.putDouble(dx1).putDouble(dy1);
-        buf.putDouble(dx2).putDouble(dy2);
-        buf.putLong(src.getNativeOps());
-        buf.putLong(dst.getNativeOps());
-    }
-
-    /*static void Blit(SurfaceData srcData, SurfaceData dstData,
-                     Composite comp, Region clip,
-                     AffineTransform xform, int hint,
-                     int sx1, int sy1,
-                     int sx2, int sy2,
-                     double dx1, double dy1,
-                     double dx2, double dy2,
-                     int srctype, boolean texture)
-    {
-        int ctxflags = 0;
-        if (srcData.getTransparency() == Transparency.OPAQUE) {
-            ctxflags |= OGLContext.SRC_IS_OPAQUE;
-        }
-
-        OGLRenderQueue rq = OGLRenderQueue.getInstance();
-        rq.lock();
-        try {
-            // make sure the RenderQueue keeps a hard reference to the
-            // source (sysmem) SurfaceData to prevent it from being
-            // disposed while the operation is processed on the QFT
-            rq.addReference(srcData);
-
-            OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
-            if (texture) {
-                // make sure we have a current context before uploading
-                // the sysmem data to the texture object
-                OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig();
-                OGLContext.setScratchSurface(gc);
-            } else {
-                OGLContext.validateContext(oglDst, oglDst,
-                        clip, comp, xform, null, null,
-                        ctxflags);
-            }
-
-            int packedParams = createPackedParams(false, texture,
-                    false, xform != null,
-                    hint, srctype);
-            enqueueBlit(rq, srcData, dstData,
-                    packedParams,
-                    sx1, sy1, sx2, sy2,
-                    dx1, dy1, dx2, dy2);
-
-            // always flush immediately, since we (currently) have no means
-            // of tracking changes to the system memory surface
-            rq.flushNow();
-        } finally {
-            rq.unlock();
-        }
-    }*/
-
-    /**
-     * Note: The srcImg and biop parameters are only used when invoked
-     * from the OGLBufImgOps.renderImageWithOp() method; in all other cases,
-     * this method can be called with null values for those two parameters,
-     * and they will be effectively ignored.
-     */
-    static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
-                        BufferedImage srcImg, BufferedImageOp biop,
-                        Composite comp, Region clip,
-                        AffineTransform xform, int hint,
-                        int sx1, int sy1,
-                        int sx2, int sy2,
-                        double dx1, double dy1,
-                        double dx2, double dy2,
-                        boolean texture)
-    {
-        /*int ctxflags = 0;
-        if (srcData.getTransparency() == Transparency.OPAQUE) {
-            ctxflags |= OGLContext.SRC_IS_OPAQUE;
-        }*/
-
-        MetalRenderQueue rq = MetalRenderQueue.getInstance();
-        rq.lock();
-        try {
-            MetalSurfaceData metalSrc = (MetalSurfaceData)srcData;
-            MetalSurfaceData metalDst = (MetalSurfaceData)dstData;
-            int srctype = metalSrc.getType();
-            /*boolean rtt;
-            OGLSurfaceData srcCtxData;
-            if (srctype == OGLSurfaceData.TEXTURE) {
-                // the source is a regular texture object; we substitute
-                // the destination surface for the purposes of making a
-                // context current
-                rtt = false;
-                srcCtxData = oglDst;
-            } else {
-                // the source is a pbuffer, backbuffer, or render-to-texture
-                // surface; we set rtt to true to differentiate this kind
-                // of surface from a regular texture object
-                rtt = true;
-                if (srctype == OGLSurfaceData.FBOBJECT) {
-                    srcCtxData = oglDst;
-                } else {
-                    srcCtxData = oglSrc;
-                }
-            }
-
-            OGLContext.validateContext(srcCtxData, oglDst,
-                    clip, comp, xform, null, null,
-                    ctxflags);
-
-            if (biop != null) {
-                OGLBufImgOps.enableBufImgOp(rq, oglSrc, srcImg, biop);
-            }*/
-
-            int packedParams = createPackedParams(true, texture,
-                    false, xform != null,
-                    hint, 0 /*unused*/);
-            enqueueBlit(rq, srcData, dstData,
-                    packedParams,
-                    sx1, sy1, sx2, sy2,
-                    dx1, dy1, dx2, dy2);
-
-            /*if (biop != null) {
-                OGLBufImgOps.disableBufImgOp(rq, biop);
-            }
-
-            if (rtt && oglDst.isOnScreen()) {
-                // we only have to flush immediately when copying from a
-                // (non-texture) surface to the screen; otherwise Swing apps
-                // might appear unresponsive until the auto-flush completes
-                rq.flushNow();
-            }*/
-        } finally {
-            rq.unlock();
-        }
-    }
-}
-
-/*class OGLSurfaceToSurfaceBlit extends Blit {
-
-    OGLSurfaceToSurfaceBlit() {
-        super(OGLSurfaceData.OpenGLSurface,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                false);
-    }
-}
-
-class OGLSurfaceToSurfaceScale extends ScaledBlit {
-
-    OGLSurfaceToSurfaceScale() {
-        super(OGLSurfaceData.OpenGLSurface,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Scale(SurfaceData src, SurfaceData dst,
-                      Composite comp, Region clip,
-                      int sx1, int sy1,
-                      int sx2, int sy2,
-                      double dx1, double dy1,
-                      double dx2, double dy2)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx1, sy1, sx2, sy2,
-                dx1, dy1, dx2, dy2,
-                false);
-    }
-}
-
-class OGLSurfaceToSurfaceTransform extends TransformBlit {
-
-    OGLSurfaceToSurfaceTransform() {
-        super(OGLSurfaceData.OpenGLSurface,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Transform(SurfaceData src, SurfaceData dst,
-                          Composite comp, Region clip,
-                          AffineTransform at, int hint,
-                          int sx, int sy, int dx, int dy,
-                          int w, int h)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, at, hint,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                false);
-    }
-}*/
-
-class MetalSurfaceToSurfaceBlit extends Blit {
-
-    MetalSurfaceToSurfaceBlit() {
-        super(MetalSurfaceData.MetalSurface,
-                CompositeType.AnyAlpha,
-                MetalSurfaceData.MetalSurface);
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy, int w, int h)
-    {
-        // TODO : Eventhough we push IsoBlit logic into queue,
-        // in renderer we have not yet implemented blit.
-        MetalBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                true);
-    }
-}
-
-/*class OGLRTTSurfaceToSurfaceScale extends ScaledBlit {
-
-    OGLRTTSurfaceToSurfaceScale() {
-        super(OGLSurfaceData.OpenGLSurfaceRTT,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Scale(SurfaceData src, SurfaceData dst,
-                      Composite comp, Region clip,
-                      int sx1, int sy1,
-                      int sx2, int sy2,
-                      double dx1, double dy1,
-                      double dx2, double dy2)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx1, sy1, sx2, sy2,
-                dx1, dy1, dx2, dy2,
-                true);
-    }
-}
-
-class OGLRTTSurfaceToSurfaceTransform extends TransformBlit {
-
-    OGLRTTSurfaceToSurfaceTransform() {
-        super(OGLSurfaceData.OpenGLSurfaceRTT,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Transform(SurfaceData src, SurfaceData dst,
-                          Composite comp, Region clip,
-                          AffineTransform at, int hint,
-                          int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, at, hint,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                true);
-    }
-}
-
-final class OGLSurfaceToSwBlit extends Blit {
-
-    private final int typeval;
-    private WeakReference<SurfaceData> srcTmp;
-
-    // destination will actually be ArgbPre or Argb
-    OGLSurfaceToSwBlit(final SurfaceType dstType,final int typeval) {
-        super(OGLSurfaceData.OpenGLSurface,
-                CompositeType.SrcNoEa,
-                dstType);
-        this.typeval = typeval;
-    }
-
-    private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
-                                              Composite comp, Region clip,
-                                              int sx, int sy, int dx, int dy,
-                                              int w, int h) {
-        SurfaceData cachedSrc = null;
-        if (srcTmp != null) {
-            // use cached intermediate surface, if available
-            cachedSrc = srcTmp.get();
-        }
-
-        // We can convert argb_pre data from OpenGL surface in two places:
-        // - During OpenGL surface -> SW blit
-        // - During SW -> SW blit
-        // The first one is faster when we use opaque OGL surface, because in
-        // this case we simply skip conversion and use color components as is.
-        // Because of this we align intermediate buffer type with type of
-        // destination not source.
-        final int type = typeval == OGLSurfaceData.PF_INT_ARGB_PRE ?
-                BufferedImage.TYPE_INT_ARGB_PRE :
-                BufferedImage.TYPE_INT_ARGB;
-
-        src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
-
-        // copy intermediate SW to destination SW using complex clip
-        final Blit performop = Blit.getFromCache(src.getSurfaceType(),
-                CompositeType.SrcNoEa,
-                dst.getSurfaceType());
-        performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
-
-        if (src != cachedSrc) {
-            // cache the intermediate surface
-            srcTmp = new WeakReference<>(src);
-        }
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy,
-                     int w, int h)
-    {
-        if (clip != null) {
-            clip = clip.getIntersectionXYWH(dx, dy, w, h);
-            // At the end this method will flush the RenderQueue, we should exit
-            // from it as soon as possible.
-            if (clip.isEmpty()) {
-                return;
-            }
-            sx += clip.getLoX() - dx;
-            sy += clip.getLoY() - dy;
-            dx = clip.getLoX();
-            dy = clip.getLoY();
-            w = clip.getWidth();
-            h = clip.getHeight();
-
-            if (!clip.isRectangular()) {
-                complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
-                return;
-            }
-        }
-
-        OGLRenderQueue rq = OGLRenderQueue.getInstance();
-        rq.lock();
-        try {
-            // make sure the RenderQueue keeps a hard reference to the
-            // destination (sysmem) SurfaceData to prevent it from being
-            // disposed while the operation is processed on the QFT
-            rq.addReference(dst);
-
-            RenderBuffer buf = rq.getBuffer();
-            OGLContext.validateContext((OGLSurfaceData)src);
-
-            rq.ensureCapacityAndAlignment(48, 32);
-            buf.putInt(SURFACE_TO_SW_BLIT);
-            buf.putInt(sx).putInt(sy);
-            buf.putInt(dx).putInt(dy);
-            buf.putInt(w).putInt(h);
-            buf.putInt(typeval);
-            buf.putLong(src.getNativeOps());
-            buf.putLong(dst.getNativeOps());
-
-            // always flush immediately
-            rq.flushNow();
-        } finally {
-            rq.unlock();
-        }
-    }
-}
-
-class OGLSwToSurfaceBlit extends Blit {
-
-    private int typeval;
-
-    OGLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
-        super(srcType,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-        this.typeval = typeval;
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.Blit(src, dst,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                typeval, false);
-    }
-}
-
-class OGLSwToSurfaceScale extends ScaledBlit {
-
-    private int typeval;
-
-    OGLSwToSurfaceScale(SurfaceType srcType, int typeval) {
-        super(srcType,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-        this.typeval = typeval;
-    }
-
-    public void Scale(SurfaceData src, SurfaceData dst,
-                      Composite comp, Region clip,
-                      int sx1, int sy1,
-                      int sx2, int sy2,
-                      double dx1, double dy1,
-                      double dx2, double dy2)
-    {
-        OGLBlitLoops.Blit(src, dst,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx1, sy1, sx2, sy2,
-                dx1, dy1, dx2, dy2,
-                typeval, false);
-    }
-}
-
-class OGLSwToSurfaceTransform extends TransformBlit {
-
-    private int typeval;
-
-    OGLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
-        super(srcType,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-        this.typeval = typeval;
-    }
-
-    public void Transform(SurfaceData src, SurfaceData dst,
-                          Composite comp, Region clip,
-                          AffineTransform at, int hint,
-                          int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.Blit(src, dst,
-                comp, clip, at, hint,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                typeval, false);
-    }
-}
-
-class OGLSwToTextureBlit extends Blit {
-
-    private int typeval;
-
-    OGLSwToTextureBlit(SurfaceType srcType, int typeval) {
-        super(srcType,
-                CompositeType.SrcNoEa,
-                OGLSurfaceData.OpenGLTexture);
-        this.typeval = typeval;
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.Blit(src, dst,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                typeval, true);
-    }
-}
-
-class OGLTextureToSurfaceBlit extends Blit {
-
-    OGLTextureToSurfaceBlit() {
-        super(OGLSurfaceData.OpenGLTexture,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Blit(SurfaceData src, SurfaceData dst,
-                     Composite comp, Region clip,
-                     int sx, int sy, int dx, int dy, int w, int h)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                true);
-    }
-}
-
-class OGLTextureToSurfaceScale extends ScaledBlit {
-
-    OGLTextureToSurfaceScale() {
-        super(OGLSurfaceData.OpenGLTexture,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Scale(SurfaceData src, SurfaceData dst,
-                      Composite comp, Region clip,
-                      int sx1, int sy1,
-                      int sx2, int sy2,
-                      double dx1, double dy1,
-                      double dx2, double dy2)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, null,
-                AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
-                sx1, sy1, sx2, sy2,
-                dx1, dy1, dx2, dy2,
-                true);
-    }
-}
-
-class OGLTextureToSurfaceTransform extends TransformBlit {
-
-    OGLTextureToSurfaceTransform() {
-        super(OGLSurfaceData.OpenGLTexture,
-                CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-    }
-
-    public void Transform(SurfaceData src, SurfaceData dst,
-                          Composite comp, Region clip,
-                          AffineTransform at, int hint,
-                          int sx, int sy, int dx, int dy,
-                          int w, int h)
-    {
-        OGLBlitLoops.IsoBlit(src, dst,
-                null, null,
-                comp, clip, at, hint,
-                sx, sy, sx+w, sy+h,
-                dx, dy, dx+w, dy+h,
-                true);
-    }
-}*/
-
-/**
- * This general Blit implementation converts any source surface to an
- * intermediate IntArgbPre surface, and then uses the more specific
- * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
- * (premultiplied) surface down to OpenGL using simple blit.
- */
-/*class OGLGeneralBlit extends Blit {
-
-    private final Blit performop;
-    private WeakReference<SurfaceData> srcTmp;
-
-    OGLGeneralBlit(SurfaceType dstType,
-                   CompositeType compType,
-                   Blit performop)
-    {
-        super(SurfaceType.Any, compType, dstType);
-        this.performop = performop;
-    }
-
-    public synchronized void Blit(SurfaceData src, SurfaceData dst,
-                                  Composite comp, Region clip,
-                                  int sx, int sy, int dx, int dy,
-                                  int w, int h)
-    {
-        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
-                CompositeType.SrcNoEa,
-                SurfaceType.IntArgbPre);
-
-        SurfaceData cachedSrc = null;
-        if (srcTmp != null) {
-            // use cached intermediate surface, if available
-            cachedSrc = srcTmp.get();
-        }
-
-        // convert source to IntArgbPre
-        src = convertFrom(convertsrc, src, sx, sy, w, h,
-                cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
-
-        // copy IntArgbPre intermediate surface to OpenGL surface
-        performop.Blit(src, dst, comp, clip,
-                0, 0, dx, dy, w, h);
-
-        if (src != cachedSrc) {
-            // cache the intermediate surface
-            srcTmp = new WeakReference<>(src);
-        }
-    }
-}*/
-
-/**
- * This general TransformedBlit implementation converts any source surface to an
- * intermediate IntArgbPre surface, and then uses the more specific
- * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate
- * (premultiplied) surface down to OpenGL using simple transformBlit.
- */
-/*final class OGLGeneralTransformedBlit extends TransformBlit {
-
-    private final TransformBlit performop;
-    private WeakReference<SurfaceData> srcTmp;
-
-    OGLGeneralTransformedBlit(final TransformBlit performop) {
-        super(SurfaceType.Any, CompositeType.AnyAlpha,
-                OGLSurfaceData.OpenGLSurface);
-        this.performop = performop;
-    }
-
-    @Override
-    public synchronized void Transform(SurfaceData src, SurfaceData dst,
-                                       Composite comp, Region clip,
-                                       AffineTransform at, int hint, int srcx,
-                                       int srcy, int dstx, int dsty, int width,
-                                       int height){
-        Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
-                CompositeType.SrcNoEa,
-                SurfaceType.IntArgbPre);
-        // use cached intermediate surface, if available
-        final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
-        // convert source to IntArgbPre
-        src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
-                BufferedImage.TYPE_INT_ARGB_PRE);
-
-        // transform IntArgbPre intermediate surface to OpenGL surface
-        performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
-                width, height);
-
-        if (src != cachedSrc) {
-            // cache the intermediate surface
-            srcTmp = new WeakReference<>(src);
-        }
-    }
-}*/
-
-/**
- * This general OGLAnyCompositeBlit implementation can convert any source/target
- * surface to an intermediate surface using convertsrc/convertdst loops, applies
- * necessary composite operation, and then uses convertresult loop to get the
- * intermediate surface down to OpenGL.
- */
-/*final class OGLAnyCompositeBlit extends Blit {
-
-    private WeakReference<SurfaceData> dstTmp;
-    private WeakReference<SurfaceData> srcTmp;
-    private final Blit convertsrc;
-    private final Blit convertdst;
-    private final Blit convertresult;
-
-    OGLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,
-                        Blit convertresult) {
-        super(srctype, CompositeType.Any, OGLSurfaceData.OpenGLSurface);
-        this.convertsrc = convertsrc;
-        this.convertdst = convertdst;
-        this.convertresult = convertresult;
-    }
-
-    public synchronized void Blit(SurfaceData src, SurfaceData dst,
-                                  Composite comp, Region clip,
-                                  int sx, int sy, int dx, int dy,
-                                  int w, int h)
-    {
-        if (convertsrc != null) {
-            SurfaceData cachedSrc = null;
-            if (srcTmp != null) {
-                // use cached intermediate surface, if available
-                cachedSrc = srcTmp.get();
-            }
-            // convert source to IntArgbPre
-            src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc,
-                    BufferedImage.TYPE_INT_ARGB_PRE);
-            if (src != cachedSrc) {
-                // cache the intermediate surface
-                srcTmp = new WeakReference<>(src);
-            }
-        }
-
-        SurfaceData cachedDst = null;
-
-        if (dstTmp != null) {
-            // use cached intermediate surface, if available
-            cachedDst = dstTmp.get();
-        }
-
-        // convert destination to IntArgbPre
-        SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,
-                cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);
-        Region bufferClip =
-                clip == null ? null : clip.getTranslatedRegion(-dx, -dy);
-
-        Blit performop = Blit.getFromCache(src.getSurfaceType(),
-                CompositeType.Any, dstBuffer.getSurfaceType());
-        performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h);
-
-        if (dstBuffer != cachedDst) {
-            // cache the intermediate surface
-            dstTmp = new WeakReference<>(dstBuffer);
-        }
-        // now blit the buffer back to the destination
-        convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx,
-                dy, w, h);
-    }
-}*/
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalContext.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * 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();
-        }
-    }*/
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalGraphicsConfig.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * 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;
-    }
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalLayer.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * 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);
-
-    }
-
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderQueue.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * 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();
-                }
-            }
-        }
-    }
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalRenderer.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * 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);
-        }
-    }
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalSurfaceData.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,556 +0,0 @@
-/*
- * 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
-}
--- a/src/java.desktop/macosx/classes/sun/java2d/metal/MetalVolatileSurfaceManager.java	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * 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 Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Fri Jun 21 12:08:37 2019 +0530
@@ -51,11 +51,11 @@
 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;
 import sun.lwawt.LWComponentPeer;
+import sun.lwawt.macosx.CFRetainedResource;
 import sun.lwawt.macosx.CPlatformView;
 
 import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_DOUBLEBUFFERED;
@@ -64,7 +64,7 @@
 import static sun.java2d.opengl.OGLSurfaceData.TEXTURE;
 
 public final class CGLGraphicsConfig extends CGraphicsConfig
-    implements OGLGraphicsConfig
+        implements OGLGraphicsConfig
 {
     //private static final int kOpenGLSwapInterval =
     // RuntimeOptions.getCurrentOptions().OpenGLSwapInterval;
@@ -111,7 +111,7 @@
         // add a record to the Disposer so that we destroy the native
         // CGLGraphicsConfigInfo data when this object goes away
         Disposer.addRecord(disposerReferent,
-                           new CGLGCDisposerRecord(pConfigInfo));
+                new CGLGCDisposerRecord(pConfigInfo));
     }
 
     @Override
@@ -122,9 +122,9 @@
     @Override
     public SurfaceData createManagedSurface(int w, int h, int transparency) {
         return CGLSurfaceData.createData(this, w, h,
-                                         getColorModel(transparency),
-                                         null,
-                                         OGLSurfaceData.TEXTURE);
+                getColorModel(transparency),
+                null,
+                OGLSurfaceData.TEXTURE);
     }
 
     public static CGLGraphicsConfig getConfig(CGraphicsDevice device,
@@ -195,27 +195,27 @@
     public BufferedImage createCompatibleImage(int width, int height) {
         ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
         WritableRaster
-            raster = model.createCompatibleWritableRaster(width, height);
+                raster = model.createCompatibleWritableRaster(width, height);
         return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
-                                 null);
+                null);
     }
 
     @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;
+            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;
         }
     }
 
@@ -265,13 +265,8 @@
     }
 
     @Override
-    public SurfaceData createSurfaceData(CGLLayer layer) {
-        return CGLSurfaceData.createData(layer);
-    }
-
-    @Override
-    public SurfaceData createSurfaceData(MetalLayer layer) {
-        return null;
+    public SurfaceData createSurfaceData(CFRetainedResource layer) {
+        return CGLSurfaceData.createData((CGLLayer) layer);
     }
 
     @Override
@@ -281,7 +276,7 @@
         ColorModel model = getColorModel(Transparency.OPAQUE);
         WritableRaster wr = model.createCompatibleWritableRaster(width, height);
         return new OffScreenImage(target, model, wr,
-                                  model.isAlphaPremultiplied());
+                model.isAlphaPremultiplied());
     }
 
     @Override
@@ -312,7 +307,7 @@
         final int w = Math.max(1, r.width);
         final int h = Math.max(1, r.height);
         final int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT
-                                                      : Transparency.OPAQUE;
+                : Transparency.OPAQUE;
         return new SunVolatileImage(this, w, h, transparency, null);
     }
 
@@ -338,7 +333,7 @@
             try {
                 bg.setBackground(peer.getBackground());
                 bg.clearRect(0, 0, backBuffer.getWidth(null),
-                             backBuffer.getHeight(null));
+                        backBuffer.getHeight(null));
             } finally {
                 bg.dispose();
             }
@@ -348,7 +343,7 @@
     private static class CGLBufferCaps extends BufferCapabilities {
         public CGLBufferCaps(boolean dblBuf) {
             super(imageCaps, imageCaps,
-                  dblBuf ? FlipContents.UNDEFINED : null);
+                    dblBuf ? FlipContents.UNDEFINED : null);
         }
     }
 
@@ -384,10 +379,10 @@
             return null;
         }
         SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
-                                                          transparency, type);
+                transparency, type);
         Surface sd = vi.getDestSurface();
         if (!(sd instanceof AccelSurface) ||
-            ((AccelSurface)sd).getType() != type)
+                ((AccelSurface)sd).getType() != type)
         {
             vi.flush();
             vi = null;
@@ -404,12 +399,12 @@
     @Override
     public int getMaxTextureWidth() {
         return Math.max(maxTextureSize / getDevice().getScaleFactor(),
-                        getBounds().width);
+                getBounds().width);
     }
 
     @Override
     public int getMaxTextureHeight() {
         return Math.max(maxTextureSize / getDevice().getScaleFactor(),
-                        getBounds().height);
+                getBounds().height);
     }
 }
--- a/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Fri Jun 21 12:08:37 2019 +0530
@@ -77,9 +77,11 @@
 import sun.awt.image.SunVolatileImage;
 import sun.awt.image.ToolkitImage;
 import sun.java2d.SunGraphics2D;
+import sun.java2d.macos.MacOSFlags;
+import sun.java2d.metal.MTLRenderQueue;
 import sun.java2d.opengl.OGLRenderQueue;
-import sun.java2d.metal.MetalRenderQueue;
 import sun.java2d.pipe.Region;
+import sun.java2d.pipe.RenderQueue;
 import sun.util.logging.PlatformLogger;
 
 public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@@ -1435,39 +1437,16 @@
     }
 
     protected static final void flushOnscreenGraphics(){
-
-        // 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();
-            }
+        RenderQueue rq = MacOSFlags.isMetalEnabled() ?
+                MTLRenderQueue.getInstance() : 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 Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Fri Jun 21 12:08:37 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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,15 +33,14 @@
 
 import sun.awt.CGraphicsConfig;
 import sun.awt.CGraphicsEnvironment;
-import sun.java2d.metal.MetalLayer;
-import sun.java2d.metal.MetalSurfaceData;
+import sun.java2d.macos.MacOSFlags;
+import sun.java2d.metal.MTLLayer;
+import sun.java2d.metal.MTLSurfaceData;
 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);
@@ -52,55 +51,31 @@
 
     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 CFRetainedResource windowLayer;
     private CPlatformResponder responder;
 
     public CPlatformView() {
         super(0, true);
     }
 
-    
     public void initialize(LWWindowPeer peer, CPlatformResponder responder) {
         initializeBase(peer, responder);
 
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            
-            if (isMetalSystemProperty()) {
-                this.windowMetalLayer = createMetalLayer();
-            } else {
-                this.windowLayer = createCGLayer();
-            }
+            this.windowLayer = MacOSFlags.isMetalEnabled()? createMTLLayer() : 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);
+    public MTLLayer createMTLLayer() {
+        return new MTLLayer(peer);
     }
+
+
     protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) {
         this.peer = peer;
         this.responder = responder;
@@ -120,11 +95,6 @@
      */
     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
@@ -145,20 +115,10 @@
     // ----------------------------------------------------------------------
     public SurfaceData replaceSurfaceData() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            
-            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();
-            }
-
+            surfaceData = (MacOSFlags.isMetalEnabled()) ?
+                    ((MTLLayer)windowLayer).replaceSurfaceData() :
+                    ((CGLLayer)windowLayer).replaceSurfaceData()
+            ;
         } else {
             if (surfaceData == null) {
                 CGraphicsConfig graphicsConfig = (CGraphicsConfig)getGraphicsConfiguration();
@@ -171,15 +131,11 @@
     }
 
     private void validateSurface() {
-
         if (surfaceData != null) {
-            // TODO : Why we are validating with View here
-            if (isMetalSystemProperty()) {
-                //((MetalSurfaceData)surfaceData).validate();
-                //windowMetalLayer.validate(getAWTView());
-                ((MetalSurfaceData)surfaceData).validate();
+            if (MacOSFlags.isMetalEnabled()) {
+                ((MTLSurfaceData) surfaceData).validate();
             } else {
-                ((CGLSurfaceData)surfaceData).validate();
+                ((CGLSurfaceData) surfaceData).validate();
             }
         }
     }
@@ -195,22 +151,16 @@
     @Override
     public void dispose() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            if (isMetalSystemProperty()) {
-                windowMetalLayer.dispose();
-            } else {
-                windowLayer.dispose();
-            }
+            windowLayer.dispose();
         }
         super.dispose();
     }
 
     public long getWindowLayerPtr() {
         if (!LWCToolkit.getSunAwtDisableCALayers()) {
-            if (isMetalSystemProperty()) {
-                return windowMetalLayer.getPointer();
-            } else {
-                return windowLayer.getPointer();
-            }
+            return MacOSFlags.isMetalEnabled() ?
+                    ((MTLLayer)windowLayer).getPointer() :
+                    ((CGLLayer)windowLayer).getPointer();
         } else {
             return 0;
         }
@@ -278,18 +228,18 @@
 
         if (event.getType() == CocoaConstants.NSScrollWheel) {
             responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(),
-                                        event.getScrollDeltaX(), event.getScrollDeltaY(),
-                                        event.getScrollPhase());
+                    event.getScrollDeltaX(), event.getScrollDeltaY(),
+                    event.getScrollPhase());
         } else {
             responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(),
-                                       event.getClickCount(), x, y,
-                                       absX, absY);
+                    event.getClickCount(), x, y,
+                    absX, absY);
         }
     }
 
     private void deliverKeyEvent(NSEvent event) {
         responder.handleKeyEvent(event.getType(), event.getModifierFlags(), event.getCharacters(),
-                                 event.getCharactersIgnoringModifiers(), event.getKeyCode(), true, false);
+                event.getCharactersIgnoringModifiers(), event.getKeyCode(), true, false);
     }
 
     /**
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Fri Jun 21 12:08:37 2019 +0530
@@ -62,7 +62,7 @@
 import sun.awt.AWTAccessor.ComponentAccessor;
 import sun.awt.AWTAccessor.WindowAccessor;
 import sun.java2d.SurfaceData;
-import sun.java2d.metal.MetalSurfaceData;
+import sun.java2d.metal.MTLSurfaceData;
 import sun.java2d.opengl.CGLSurfaceData;
 import sun.lwawt.LWLightweightFramePeer;
 import sun.lwawt.LWToolkit;
@@ -79,7 +79,7 @@
     private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h);
     private static native void nativeSetNSWindowLocationByPlatform(long nsWindowPtr);
     private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr,
-            double x, double y, double w, double h);
+                                                              double x, double y, double w, double h);
     private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH);
     private static native void nativePushNSWindowToBack(long nsWindowPtr);
     private static native void nativePushNSWindowToFront(long nsWindowPtr);
@@ -154,7 +154,7 @@
     static final int FULL_WINDOW_CONTENT = 1 << 14;
 
     static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE
-                                             | MINIMIZABLE | RESIZABLE | FULL_WINDOW_CONTENT;
+            | MINIMIZABLE | RESIZABLE | FULL_WINDOW_CONTENT;
 
     // corresponds to method-based properties
     static final int HAS_SHADOW = 1 << 10;
@@ -168,8 +168,8 @@
     static final int TRANSPARENT_TITLE_BAR = 1 << 18;
 
     static final int _METHOD_PROP_BITMASK = RESIZABLE | HAS_SHADOW | ZOOMABLE | ALWAYS_ON_TOP | HIDES_ON_DEACTIVATE
-                                              | DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE
-                                              | TRANSPARENT_TITLE_BAR;
+            | DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE
+            | TRANSPARENT_TITLE_BAR;
 
     // corresponds to callback-based properties
     static final int SHOULD_BECOME_KEY = 1 << 12;
@@ -189,68 +189,68 @@
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     static ClientPropertyApplicator<JRootPane, CPlatformWindow> CLIENT_PROPERTY_APPLICATOR = new ClientPropertyApplicator<JRootPane, CPlatformWindow>(new Property[] {
-        new Property<CPlatformWindow>(WINDOW_DOCUMENT_MODIFIED) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.setStyleBits(DOCUMENT_MODIFIED, value == null ? false : Boolean.parseBoolean(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_BRUSH_METAL_LOOK) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.setStyleBits(TEXTURED, Boolean.parseBoolean(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_ALPHA) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.target.setOpacity(value == null ? 1.0f : Float.parseFloat(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_SHADOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.setStyleBits(HAS_SHADOW, value == null ? true : Boolean.parseBoolean(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_MINIMIZABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.setStyleBits(MINIMIZABLE, Boolean.parseBoolean(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_CLOSEABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.setStyleBits(CLOSEABLE, Boolean.parseBoolean(value.toString()));
-        }},
-        new Property<CPlatformWindow>(WINDOW_ZOOMABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            boolean zoomable = Boolean.parseBoolean(value.toString());
-            if (c.target instanceof RootPaneContainer
-                    && c.getPeer().getPeerType() == PeerType.FRAME) {
-                if (c.isInFullScreen && !zoomable) {
-                    c.toggleFullScreen();
+            new Property<CPlatformWindow>(WINDOW_DOCUMENT_MODIFIED) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.setStyleBits(DOCUMENT_MODIFIED, value == null ? false : Boolean.parseBoolean(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_BRUSH_METAL_LOOK) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.setStyleBits(TEXTURED, Boolean.parseBoolean(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_ALPHA) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.target.setOpacity(value == null ? 1.0f : Float.parseFloat(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_SHADOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.setStyleBits(HAS_SHADOW, value == null ? true : Boolean.parseBoolean(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_MINIMIZABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.setStyleBits(MINIMIZABLE, Boolean.parseBoolean(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_CLOSEABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.setStyleBits(CLOSEABLE, Boolean.parseBoolean(value.toString()));
+            }},
+            new Property<CPlatformWindow>(WINDOW_ZOOMABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                boolean zoomable = Boolean.parseBoolean(value.toString());
+                if (c.target instanceof RootPaneContainer
+                        && c.getPeer().getPeerType() == PeerType.FRAME) {
+                    if (c.isInFullScreen && !zoomable) {
+                        c.toggleFullScreen();
+                    }
+                }
+                c.setStyleBits(ZOOMABLE, zoomable);
+            }},
+            new Property<CPlatformWindow>(WINDOW_FULLSCREENABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                boolean fullscrenable = Boolean.parseBoolean(value.toString());
+                if (c.target instanceof RootPaneContainer
+                        && c.getPeer().getPeerType() == PeerType.FRAME) {
+                    if (c.isInFullScreen && !fullscrenable) {
+                        c.toggleFullScreen();
+                    }
+                }
+                c.setStyleBits(FULLSCREENABLE, fullscrenable);
+            }},
+            new Property<CPlatformWindow>(WINDOW_SHADOW_REVALIDATE_NOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                c.execute(ptr -> nativeRevalidateNSWindowShadow(ptr));
+            }},
+            new Property<CPlatformWindow>(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) {
+                if (value == null || !(value instanceof java.io.File)) {
+                    c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, null));
+                    return;
+                }
+
+                final String filename = ((java.io.File)value).getAbsolutePath();
+                c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, filename));
+            }},
+            new Property<CPlatformWindow>(WINDOW_FULL_CONTENT) {
+                public void applyProperty(final CPlatformWindow c, final Object value) {
+                    boolean isFullWindowContent = Boolean.parseBoolean(value.toString());
+                    c.setStyleBits(FULL_WINDOW_CONTENT, isFullWindowContent);
+                }
+            },
+            new Property<CPlatformWindow>(WINDOW_TRANSPARENT_TITLE_BAR) {
+                public void applyProperty(final CPlatformWindow c, final Object value) {
+                    boolean isTransparentTitleBar = Boolean.parseBoolean(value.toString());
+                    c.setStyleBits(TRANSPARENT_TITLE_BAR, isTransparentTitleBar);
                 }
             }
-            c.setStyleBits(ZOOMABLE, zoomable);
-        }},
-        new Property<CPlatformWindow>(WINDOW_FULLSCREENABLE) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            boolean fullscrenable = Boolean.parseBoolean(value.toString());
-            if (c.target instanceof RootPaneContainer
-                    && c.getPeer().getPeerType() == PeerType.FRAME) {
-                if (c.isInFullScreen && !fullscrenable) {
-                    c.toggleFullScreen();
-                }
-            }
-            c.setStyleBits(FULLSCREENABLE, fullscrenable);
-        }},
-        new Property<CPlatformWindow>(WINDOW_SHADOW_REVALIDATE_NOW) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            c.execute(ptr -> nativeRevalidateNSWindowShadow(ptr));
-        }},
-        new Property<CPlatformWindow>(WINDOW_DOCUMENT_FILE) { public void applyProperty(final CPlatformWindow c, final Object value) {
-            if (value == null || !(value instanceof java.io.File)) {
-                c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, null));
-                return;
-            }
-
-            final String filename = ((java.io.File)value).getAbsolutePath();
-            c.execute(ptr->nativeSetNSWindowRepresentedFilename(ptr, filename));
-        }},
-        new Property<CPlatformWindow>(WINDOW_FULL_CONTENT) {
-            public void applyProperty(final CPlatformWindow c, final Object value) {
-                boolean isFullWindowContent = Boolean.parseBoolean(value.toString());
-                c.setStyleBits(FULL_WINDOW_CONTENT, isFullWindowContent);
-            }
-        },
-        new Property<CPlatformWindow>(WINDOW_TRANSPARENT_TITLE_BAR) {
-            public void applyProperty(final CPlatformWindow c, final Object value) {
-                boolean isTransparentTitleBar = Boolean.parseBoolean(value.toString());
-                c.setStyleBits(TRANSPARENT_TITLE_BAR, isTransparentTitleBar);
-            }
-        }
     }) {
         @SuppressWarnings("deprecation")
         public CPlatformWindow convertJComponentToTarget(final JRootPane p) {
@@ -333,16 +333,16 @@
             if (owner != null) {
                 hasOwnerPtr = 0L != owner.executeGet(ownerPtr -> {
                     ref.set(nativeCreateNSWindow(viewPtr, ownerPtr, styleBits,
-                                                    bounds.x, bounds.y,
-                                                    bounds.width, bounds.height));
+                            bounds.x, bounds.y,
+                            bounds.width, bounds.height));
                     return 1;
                 });
             }
 
             if (!hasOwnerPtr) {
                 ref.set(nativeCreateNSWindow(viewPtr, 0,
-                                             styleBits, bounds.x, bounds.y,
-                                             bounds.width, bounds.height));
+                        styleBits, bounds.x, bounds.y,
+                        bounds.width, bounds.height));
             }
         });
         setPtr(ref.get());
@@ -653,7 +653,7 @@
             if (visible) {
                 contentView.execute(viewPtr -> {
                     execute(ptr -> CWrapper.NSWindow.makeFirstResponder(ptr,
-                                                                        viewPtr));
+                            viewPtr));
                 });
 
                 boolean isPopup = (target.getType() == Window.Type.POPUP);
@@ -699,8 +699,8 @@
             bw.execute(blockerPtr -> {
                 execute(ptr -> {
                     CWrapper.NSWindow.orderWindow(ptr,
-                                                  CWrapper.NSWindow.NSWindowBelow,
-                                                  blockerPtr);
+                            CWrapper.NSWindow.NSWindowBelow,
+                            blockerPtr);
                 });
             });
         }
@@ -712,7 +712,7 @@
             Frame or Dialog is resizable.
             **/
             final boolean resizable = (target instanceof Frame) ? ((Frame)target).isResizable() :
-            ((target instanceof Dialog) ? ((Dialog)target).isResizable() : false);
+                    ((target instanceof Dialog) ? ((Dialog)target).isResizable() : false);
             if (resizable) {
                 setCanFullscreen(true);
             }
@@ -862,7 +862,7 @@
     public boolean rejectFocusRequest(FocusEvent.Cause cause) {
         // Cross-app activation requests are not allowed.
         if (cause != FocusEvent.Cause.MOUSE_EVENT &&
-            !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
+                !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
         {
             focusLogger.fine("the app is inactive, so the request is rejected");
             return true;
@@ -1057,8 +1057,8 @@
         SurfaceData surfaceData = getSurfaceData();
         if (surfaceData instanceof CGLSurfaceData) {
             ((CGLSurfaceData)surfaceData).validate();
-        } else if (surfaceData instanceof MetalSurfaceData) {
-            ((MetalSurfaceData)surfaceData).validate();
+        } else if (surfaceData instanceof MTLSurfaceData) {
+            ((MTLSurfaceData)surfaceData).validate();
         }
     }
 
@@ -1105,7 +1105,7 @@
     }
 
     protected void deliverMoveResizeEvent(int x, int y, int width, int height,
-                                        boolean byUser) {
+                                          boolean byUser) {
         AtomicBoolean ref = new AtomicBoolean();
         execute(ptr -> {
             ref.set(CWrapper.NSWindow.isZoomed(ptr));
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java	Fri Jun 21 12:08:37 2019 +0530
@@ -29,6 +29,7 @@
 import sun.awt.IconInfo;
 import sun.java2d.SunGraphics2D;
 import sun.java2d.SurfaceData;
+import sun.java2d.metal.MTLLayer;
 import sun.java2d.opengl.CGLLayer;
 import sun.lwawt.LWWindowPeer;
 import sun.lwawt.PlatformEventNotifier;
@@ -222,8 +223,8 @@
                     owner.execute(ownerPtr -> {
                         execute(ptr -> {
                             CWrapper.NSWindow.orderWindow(ptr,
-                                                          CWrapper.NSWindow.NSWindowAbove,
-                                                          ownerPtr);
+                                    CWrapper.NSWindow.NSWindowAbove,
+                                    ownerPtr);
                         });
                     });
 
@@ -300,6 +301,23 @@
                     }
                 };
             }
+            public MTLLayer createMTLLayer() {
+                return new MTLLayer(null) {
+                    public Rectangle getBounds() {
+                        return CWarningWindow.this.getBounds();
+                    }
+
+                    public GraphicsConfiguration getGraphicsConfiguration() {
+                        LWWindowPeer peer = ownerPeer.get();
+                        return peer.getGraphicsConfiguration();
+                    }
+
+                    public boolean isOpaque() {
+                        return false;
+                    }
+                };
+            }
+
         };
     }
 
@@ -349,7 +367,7 @@
                 currentSize = newSize;
                 IconInfo ico = getSecurityIconInfo(currentSize, 0);
                 AWTAccessor.getWindowAccessor().setSecurityWarningSize(
-                    ownerWindow, ico.getWidth(), ico.getHeight());
+                        ownerWindow, ico.getWidth(), ico.getHeight());
             }
         }
     }
@@ -361,7 +379,7 @@
         }
 
         return new SunGraphics2D(sd, SystemColor.windowText, SystemColor.window,
-                                 ownerWindow.getFont());
+                ownerWindow.getFont());
     }
 
 
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Jun 21 12:08:37 2019 +0530
@@ -109,6 +109,8 @@
 import sun.awt.SunToolkit;
 import sun.awt.datatransfer.DataTransferer;
 import sun.awt.util.ThreadGroupUtils;
+import sun.java2d.macos.MacOSFlags;
+import sun.java2d.metal.MTLRenderQueue;
 import sun.java2d.opengl.OGLRenderQueue;
 import sun.lwawt.LWComponentPeer;
 import sun.lwawt.LWCursorManager;
@@ -148,21 +150,21 @@
 
         ResourceBundle platformResources = java.security.AccessController.doPrivileged(
                 new java.security.PrivilegedAction<ResourceBundle>() {
-            @Override
-            public ResourceBundle run() {
-                ResourceBundle platformResources = null;
-                try {
-                    platformResources = ResourceBundle.getBundle("sun.awt.resources.awtosx");
-                } catch (MissingResourceException e) {
-                    // No resource file; defaults will be used.
-                }
+                    @Override
+                    public ResourceBundle run() {
+                        ResourceBundle platformResources = null;
+                        try {
+                            platformResources = ResourceBundle.getBundle("sun.awt.resources.awtosx");
+                        } catch (MissingResourceException e) {
+                            // No resource file; defaults will be used.
+                        }
 
-                System.loadLibrary("awt");
-                System.loadLibrary("fontmanager");
+                        System.loadLibrary("awt");
+                        System.loadLibrary("fontmanager");
 
-                return platformResources;
-            }
-        });
+                        return platformResources;
+                    }
+                });
 
         if (!GraphicsEnvironment.isHeadless() &&
             !PlatformGraphicsInfo.isInAquaSession())
@@ -210,9 +212,9 @@
     public static final int INACTIVE_SELECTION_BACKGROUND_COLOR = 1;
     public static final int INACTIVE_SELECTION_FOREGROUND_COLOR = 2;
     private static int[] appleColors = {
-        0xFF808080, // keyboardFocusColor = Color.gray;
-        0xFFC0C0C0, // secondarySelectedControlColor
-        0xFF303030, // controlDarkShadowColor
+            0xFF808080, // keyboardFocusColor = Color.gray;
+            0xFFC0C0C0, // secondarySelectedControlColor
+            0xFF303030, // controlDarkShadowColor
     };
 
     private native void loadNativeColors(final int[] systemColors, final int[] appleColors);
@@ -485,7 +487,11 @@
     @Override
     public void sync() {
         // flush the OGL pipeline (this is a no-op if OGL is not enabled)
-        OGLRenderQueue.sync();
+        if (MacOSFlags.isMetalEnabled()) {
+            MTLRenderQueue.sync();
+        } else {
+            OGLRenderQueue.sync();
+        }
         // setNeedsDisplay() selector was sent to the appropriate CALayer so now
         // we have to flush the native selectors queue.
         flushNativeSelectors();
@@ -635,7 +641,7 @@
         final boolean[] ret = new boolean[1];
 
         try {  invokeAndWait(new Runnable() { @Override
-                                              public void run() { synchronized(ret) {
+        public void run() { synchronized(ret) {
             ret[0] = a.equals(b);
         }}}, c); } catch (Exception e) { e.printStackTrace(); }
 
@@ -856,7 +862,7 @@
     public static synchronized boolean getSunAwtDisableCALayers() {
         if (sunAwtDisableCALayers == null) {
             sunAwtDisableCALayers = AccessController.doPrivileged(
-                new GetBooleanAction("sun.awt.disableCALayers"));
+                    new GetBooleanAction("sun.awt.disableCALayers"));
         }
         return sunAwtDisableCALayers;
     }
@@ -915,9 +921,9 @@
     @Override
     public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
         return (exclusionType == null) ||
-            (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) ||
-            (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) ||
-            (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
+                (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) ||
+                (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) ||
+                (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
     }
 
     @Override
@@ -925,10 +931,10 @@
         //TODO: FileDialog blocks excluded windows...
         //TODO: Test: 2 file dialogs, separate AppContexts: a) Dialog 1 blocked, shouldn't be. Frame 4 blocked (shouldn't be).
         return (modalityType == null) ||
-            (modalityType == Dialog.ModalityType.MODELESS) ||
-            (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) ||
-            (modalityType == Dialog.ModalityType.APPLICATION_MODAL) ||
-            (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
+                (modalityType == Dialog.ModalityType.MODELESS) ||
+                (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) ||
+                (modalityType == Dialog.ModalityType.APPLICATION_MODAL) ||
+                (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
     }
 
     @Override
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Fri Jun 21 12:08:37 2019 +0530
@@ -37,6 +37,8 @@
 #import <Carbon/Carbon.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
+jboolean metalEnabled = JNI_FALSE;
+
 @interface AWTView()
 @property (retain) CDropTarget *_dropTarget;
 @property (retain) CDragSource *_dragSource;
@@ -52,6 +54,8 @@
 //#define IM_DEBUG TRUE
 //#define EXTRA_DEBUG
 
+#define METAL_DEBUG
+
 static BOOL shouldUsePressAndHold() {
     static int shouldUsePressAndHold = -1;
     if (shouldUsePressAndHold != -1) return shouldUsePressAndHold;
@@ -1484,3 +1488,19 @@
 
     return underMouse;
 }
+
+jboolean GetStaticBoolean(JNIEnv *env, jclass fClass, const char *fieldName)
+{
+    jfieldID fieldID = (*env)->GetStaticFieldID(env, fClass, fieldName, "Z");
+    return (*env)->GetStaticBooleanField(env, fClass, fieldID);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_macos_MacOSFlags_initNativeFlags(JNIEnv *env,
+                                                     jclass flagsClass)
+{
+  metalEnabled = GetStaticBoolean(env, flagsClass, "metalEnabled");
+#ifdef METAL_DEBUG
+  fprintf(stderr, "metalEnabled=%d\n", metalEnabled);
+#endif
+}
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Mon Jun 10 14:13:09 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Fri Jun 21 12:08:37 2019 +0530
@@ -1171,6 +1171,8 @@
 JNF_COCOA_EXIT(env);
 }
 
+extern jboolean metalEnabled;
+
 /*
  * Class:     sun_lwawt_macosx_CPlatformWindow
  * Method:    nativeGetNSWindowInsets
@@ -1197,6 +1199,10 @@
     jint left = (jint)(contentRect.origin.x - frame.origin.x);
     jint bottom = (jint)(contentRect.origin.y - frame.origin.y);
     jint right = (jint)(frame.size.width - (contentRect.size.width + left));
+    if (metalEnabled == JNI_TRUE) {
+        bottom -= top;
+        top = 0;
+    }
 
     static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets");
     static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/common.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <simd/SIMD.h>
+
+#define PGRAM_VERTEX_COUNT 6
+
+enum VertexAttributes {
+    VertexAttributePosition = 0,
+    VertexAttributeTexPos = 1
+};
+
+enum BufferIndex  {
+    MeshVertexBuffer = 0,
+    FrameUniformBuffer = 1,
+    MatrixBuffer = 2
+};
+
+struct FrameUniforms {
+    vector_float4 color;
+};
+
+struct TransformMatrix {
+    matrix_float4x4 transformMatrix;
+};
+
+struct GradFrameUniforms {
+    vector_float3 params;
+    vector_float4 color1;
+    vector_float4 color2;
+};
+
+struct Vertex {
+    float position[3];
+};
+
+struct TxtVertex {
+    float position[3];
+    float txtpos[2];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/shaders.metal	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#include <simd/simd.h>
+#include <metal_stdlib>
+#include "common.h"
+
+using namespace metal;
+
+struct VertexInput {
+    float3 position [[attribute(VertexAttributePosition)]];
+};
+
+struct TxtVertexInput {
+    float3 position [[attribute(VertexAttributePosition)]];
+    float2 texCoords [[attribute(VertexAttributeTexPos)]];
+};
+
+struct ColShaderInOut {
+    float4 position [[position]];
+    half4  color;
+};
+
+struct TxtShaderInOut {
+    float4 position [[position]];
+    float2 texCoords;
+};
+
+struct GradShaderInOut {
+    float4 position [[position]];
+};
+
+vertex ColShaderInOut vert_col(VertexInput in [[stage_in]],
+	   constant FrameUniforms& uniforms [[buffer(FrameUniformBuffer)]],
+       constant TransformMatrix& transform [[buffer(MatrixBuffer)]]) {
+    ColShaderInOut out;
+    float4 pos4 = float4(in.position, 1.0);
+    out.position = transform.transformMatrix*pos4;
+    out.color = half4(uniforms.color.r, uniforms.color.g, uniforms.color.b, uniforms.color.a);
+    return out;
+}
+
+vertex GradShaderInOut vert_grad(VertexInput in [[stage_in]], constant TransformMatrix& transform [[buffer(MatrixBuffer)]]) {
+    GradShaderInOut out;
+    float4 pos4 = float4(in.position, 1.0);
+    out.position = transform.transformMatrix*pos4;
+    return out;
+}
+
+vertex TxtShaderInOut vert_txt(TxtVertexInput in [[stage_in]], constant TransformMatrix& transform [[buffer(MatrixBuffer)]]) {
+    TxtShaderInOut out;
+    float4 pos4 = float4(in.position, 1.0);
+    out.position = transform.transformMatrix*pos4;
+    out.texCoords = in.texCoords;
+    return out;
+}
+
+fragment half4 frag_col(ColShaderInOut in [[stage_in]]) {
+    return in.color;
+}
+
+fragment half4 frag_txt(
+        TxtShaderInOut vert [[stage_in]],
+        texture2d<float, access::sample> renderTexture [[texture(0)]]
+        )
+{
+    constexpr sampler textureSampler (mag_filter::linear,
+                                  min_filter::linear);
+    float4 pixelColor = renderTexture.sample(textureSampler, vert.texCoords);
+    return half4(pixelColor.r, pixelColor.g, pixelColor.b , pixelColor.a);
+}
+
+fragment half4 frag_grad(GradShaderInOut in [[stage_in]],
+                         constant GradFrameUniforms& uniforms [[buffer(0)]]) {
+    float3 v = float3(in.position.x, in.position.y, 1);
+    float  a = (dot(v,uniforms.params)-0.25)*2.0;
+    float4 c = mix(uniforms.color1, uniforms.color2, a);
+    return half4(c);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLBlitLoops_h_Included
+#define MTLBlitLoops_h_Included
+
+#include "sun_java2d_metal_MTLBlitLoops.h"
+#include "MTLSurfaceDataBase.h"
+#include "MTLContext.h"
+
+#define OFFSET_SRCTYPE sun_java2d_metal_MTLBlitLoops_OFFSET_SRCTYPE
+#define OFFSET_HINT    sun_java2d_metal_MTLBlitLoops_OFFSET_HINT
+#define OFFSET_TEXTURE sun_java2d_metal_MTLBlitLoops_OFFSET_TEXTURE
+#define OFFSET_RTT     sun_java2d_metal_MTLBlitLoops_OFFSET_RTT
+#define OFFSET_XFORM   sun_java2d_metal_MTLBlitLoops_OFFSET_XFORM
+#define OFFSET_ISOBLIT sun_java2d_metal_MTLBlitLoops_OFFSET_ISOBLIT
+
+void MTLBlitLoops_IsoBlit(JNIEnv *env,
+                          MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
+                          jboolean xform, jint hint,
+                          jboolean texture, jboolean rtt,
+                          jint sx1, jint sy1,
+                          jint sx2, jint sy2,
+                          jdouble dx1, jdouble dy1,
+                          jdouble dx2, jdouble dy2);
+
+void MTLBlitLoops_Blit(JNIEnv *env,
+                       MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
+                       jboolean xform, jint hint,
+                       jint srctype, jboolean texture,
+                       jint sx1, jint sy1,
+                       jint sx2, jint sy2,
+                       jdouble dx1, jdouble dy1,
+                       jdouble dx2, jdouble dy2);
+
+void MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
+                                  jlong pSrcOps, jlong pDstOps, jint dsttype,
+                                  jint srcx, jint srcy,
+                                  jint dstx, jint dsty,
+                                  jint width, jint height);
+
+void MTLBlitLoops_CopyArea(JNIEnv *env,
+                           MTLContext *mtlc, BMTLSDOps *dstOps,
+                           jint x, jint y,
+                           jint width, jint height,
+                           jint dx, jint dy);
+
+void MTLBlitTex2Tex(MTLContext *mtlc, id<MTLTexture> src, id<MTLTexture> dest);
+
+#endif /* MTLBlitLoops_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,482 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <jni.h>
+#include <jlong.h>
+
+#include "SurfaceData.h"
+#include "MTLBlitLoops.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceData.h"
+#include "MTLUtils.h"
+#include "GraphicsPrimitiveMgr.h"
+
+#include <stdlib.h> // malloc
+#include <string.h> // memcpy
+#include "IntArgbPre.h"
+
+extern MTLPixelFormat PixelFormats[];
+extern void J2dTraceImpl(int level, jboolean cr, const char *string, ...);
+
+void fillTxQuad(
+        struct TxtVertex * txQuadVerts,
+        jint sx1, jint sy1, jint sx2, jint sy2, jint sw, jint sh,
+        jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dw, jdouble dh
+) {
+    const float nsx1 = sx1/(float)sw;
+    const float nsy1 = sy1/(float)sh;
+    const float nsx2 = sx2/(float)sw;
+    const float nsy2 = sy2/(float)sh;
+
+    txQuadVerts[0].position[0] = dx1;
+    txQuadVerts[0].position[1] = dy1;
+    txQuadVerts[0].position[2] = 0;
+    txQuadVerts[0].txtpos[0]   = nsx1;
+    txQuadVerts[0].txtpos[1]   = nsy1;
+
+    txQuadVerts[1].position[0] = dx2;
+    txQuadVerts[1].position[1] = dy1;
+    txQuadVerts[1].position[2] = 0;
+    txQuadVerts[1].txtpos[0]   = nsx2;
+    txQuadVerts[1].txtpos[1]   = nsy1;
+
+    txQuadVerts[2].position[0] = dx2;
+    txQuadVerts[2].position[1] = dy2;
+    txQuadVerts[2].position[2] = 0;
+    txQuadVerts[2].txtpos[0]   = nsx2;
+    txQuadVerts[2].txtpos[1]   = nsy2;
+
+    txQuadVerts[3].position[0] = dx2;
+    txQuadVerts[3].position[1] = dy2;
+    txQuadVerts[3].position[2] = 0;
+    txQuadVerts[3].txtpos[0]   = nsx2;
+    txQuadVerts[3].txtpos[1]   = nsy2;
+
+    txQuadVerts[4].position[0] = dx1;
+    txQuadVerts[4].position[1] = dy2;
+    txQuadVerts[4].position[2] = 0;
+    txQuadVerts[4].txtpos[0]   = nsx1;
+    txQuadVerts[4].txtpos[1]   = nsy2;
+
+    txQuadVerts[5].position[0] = dx1;
+    txQuadVerts[5].position[1] = dy1;
+    txQuadVerts[5].position[2] = 0;
+    txQuadVerts[5].txtpos[0]   = nsx1;
+    txQuadVerts[5].txtpos[1]   = nsy1;
+}
+
+/**
+ * Inner loop used for copying a source MTL "Surface" (window, pbuffer,
+ * etc.) to a destination OpenGL "Surface".  Note that the same surface can
+ * be used as both the source and destination, as is the case in a copyArea()
+ * operation.  This method is invoked from MTLBlitLoops_IsoBlit() as well as
+ * MTLBlitLoops_CopyArea().
+ *
+ * The standard glCopyPixels() mechanism is used to copy the source region
+ * into the destination region.  If the regions have different dimensions,
+ * the source will be scaled into the destination as appropriate (only
+ * nearest neighbor filtering will be applied for simple scale operations).
+ */
+static void
+MTLBlitSurfaceToSurface(MTLContext *mtlc, BMTLSDOps *srcOps, BMTLSDOps *dstOps,
+                        jint sx1, jint sy1, jint sx2, jint sy2,
+                        jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    //TODO
+    //J2dTraceNotImplPrimitive("MTLBlitSurfaceToSurface");
+}
+
+static void drawTex2Tex(MTLContext *mtlc,
+                        id<MTLTexture> src, id<MTLTexture> dst,
+                        jboolean rtt, jint hint,
+                        jint sx1, jint sy1, jint sx2, jint sy2,
+                        jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    if (mtlc == NULL || src == nil || dst == nil)
+        return;
+
+//    J2dTraceLn2(J2D_TRACE_VERBOSE, "_drawTex2Tex: src tex=%p, dst tex=%p", src, dst);
+//    J2dTraceLn4(J2D_TRACE_VERBOSE, "  sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height);
+//    J2dTraceLn4(J2D_TRACE_VERBOSE, "  sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2);
+//    J2dTraceLn4(J2D_TRACE_VERBOSE, "  dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
+
+    id<MTLRenderCommandEncoder> encoder = [mtlc createSamplingEncoderForDest:dst];
+
+
+    const jboolean normalize = !mtlc.useTransform;
+    struct TxtVertex quadTxVerticesBuffer[6];
+    fillTxQuad(quadTxVerticesBuffer, sx1, sy1, sx2, sy2, src.width, src.height, dx1, dy1, dx2, dy2, dst.width, dst.height);
+
+    [encoder setVertexBytes:quadTxVerticesBuffer length:sizeof(quadTxVerticesBuffer) atIndex:MeshVertexBuffer];
+    [encoder setFragmentTexture:src atIndex: 0];
+    [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
+    [encoder endEncoding];
+}
+
+/**
+ * Inner loop used for copying a source MTL "Texture" to a destination
+ * MTL "Surface".  This method is invoked from MTLBlitLoops_IsoBlit().
+ *
+ * This method will copy, scale, or transform the source texture into the
+ * destination depending on the transform state, as established in
+ * and MTLContext_SetTransform().  If the source texture is
+ * transformed in any way when rendered into the destination, the filtering
+ * method applied is determined by the hint parameter (can be GL_NEAREST or
+ * GL_LINEAR).
+ */
+static void
+MTLBlitTextureToSurface(MTLContext *mtlc,
+                        BMTLSDOps *srcOps, BMTLSDOps *dstOps,
+                        jboolean rtt, jint hint,
+                        jint sx1, jint sy1, jint sx2, jint sy2,
+                        jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    id<MTLTexture> srcTex = srcOps->pTexture;
+
+#ifdef DEBUG
+    J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, "MTLBlitLoops_IsoBlit [via sampling]: bsrc=%p [tex=%p], bdst=%p [tex=%p] | s (%dx%d) -> d (%dx%d) | src (%d, %d, %d, %d) -> dst (%1.2f, %1.2f, %1.2f, %1.2f)", srcOps, srcOps->pTexture, dstOps, dstOps->pTexture, srcTex.width, srcTex.height, dstOps->width, dstOps->height, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif //DEBUG
+
+    drawTex2Tex(mtlc, srcOps->pTexture, dstOps->pTexture, rtt, hint, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+}
+
+/**
+ * Inner loop used for copying a source system memory ("Sw") surface to a
+ * destination MTL "Surface".  This method is invoked from
+ * MTLBlitLoops_Blit().
+ *
+ * The standard glDrawPixels() mechanism is used to copy the source region
+ * into the destination region.  If the regions have different
+ * dimensions, the source will be scaled into the destination
+ * as appropriate (only nearest neighbor filtering will be applied for simple
+ * scale operations).
+ */
+
+static void
+MTLBlitSwToSurfaceViaTexture(MTLContext *ctx, SurfaceDataRasInfo *srcInfo, BMTLSDOps * bmtlsdOps,
+                   MTPixelFormat *pf,
+                   jint sx1, jint sy1, jint sx2, jint sy2,
+                   jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    if (bmtlsdOps == NULL || bmtlsdOps->pTexture == NULL) {
+        J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitSwToSurfaceViaTexture: dest is null");
+        return;
+    }
+
+    const int sw = sx2 - sx1;
+    const int sh = sy2 - sy1;
+    id<MTLTexture> dest = bmtlsdOps->pTexture;
+
+#ifdef DEBUG
+    J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, "MTLBlitLoops_Blit [via pooled texture]: bdst=%p [tex=%p], sw=%d, sh=%d | src (%d, %d, %d, %d) -> dst (%1.2f, %1.2f, %1.2f, %1.2f)", bmtlsdOps, dest, sw, sh, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif //DEBUG
+
+    id<MTLTexture> texBuff = [ctx.texturePool getTexture:sw height:sh format:MTLPixelFormatBGRA8Unorm];
+    if (texBuff == nil) {
+        J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitSwToSurfaceViaTexture: can't obtain temporary texture object from pool");
+        return;
+    }
+    MTLRegion region = MTLRegionMake2D(0, 0, sw, sh);
+    [texBuff replaceRegion:region mipmapLevel:0 withBytes:srcInfo->rasBase bytesPerRow:srcInfo->scanStride]; // texBuff is locked for current frame
+
+    drawTex2Tex(ctx, texBuff, dest, 0, 0, 0, 0, sw, sh, dx1, dy1, dx2, dy2);
+}
+
+/**
+ * Inner loop used for copying a source system memory ("Sw") surface or
+ * MTL "Surface" to a destination OpenGL "Surface", using an MTL texture
+ * tile as an intermediate surface.  This method is invoked from
+ * MTLBlitLoops_Blit() for "Sw" surfaces and MTLBlitLoops_IsoBlit() for
+ * "Surface" surfaces.
+ *
+ * This method is used to transform the source surface into the destination.
+ * Pixel rectangles cannot be arbitrarily transformed (without the
+ * GL_EXT_pixel_transform extension, which is not supported on most modern
+ * hardware).  However, texture mapped quads do respect the GL_MODELVIEW
+ * transform matrix, so we use textures here to perform the transform
+ * operation.  This method uses a tile-based approach in which a small
+ * subregion of the source surface is copied into a cached texture tile.  The
+ * texture tile is then mapped into the appropriate location in the
+ * destination surface.
+ *
+ * REMIND: this only works well using GL_NEAREST for the filtering mode
+ *         (GL_LINEAR causes visible stitching problems between tiles,
+ *         but this can be fixed by making use of texture borders)
+ */
+static void
+MTLBlitToSurfaceViaTexture(MTLContext *mtlc, SurfaceDataRasInfo *srcInfo,
+                           MTPixelFormat *pf, MTLSDOps *srcOps,
+                           jboolean swsurface, jint hint,
+                           jint sx1, jint sy1, jint sx2, jint sy2,
+                           jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    //TODO
+    //J2dTraceNotImplPrimitive("MTLBlitToSurfaceViaTexture");
+}
+
+/**
+ * Inner loop used for copying a source system memory ("Sw") surface to a
+ * destination OpenGL "Texture".  This method is invoked from
+ * MTLBlitLoops_Blit().
+ *
+ * The source surface is effectively loaded into the MTL texture object,
+ * which must have already been initialized by MTLSD_initTexture().  Note
+ * that this method is only capable of copying the source surface into the
+ * destination surface (i.e. no scaling or general transform is allowed).
+ * This restriction should not be an issue as this method is only used
+ * currently to cache a static system memory image into an MTL texture in
+ * a hidden-acceleration situation.
+ */
+static void
+MTLBlitSwToTexture(SurfaceDataRasInfo *srcInfo, MTPixelFormat *pf,
+                   MTLSDOps *dstOps,
+                   jint dx1, jint dy1, jint dx2, jint dy2)
+{
+    //TODO
+    //J2dTraceNotImplPrimitive("MTLBlitSwToTexture");
+}
+
+/**
+ * General blit method for copying a native MTL surface (of type "Surface"
+ * or "Texture") to another MTL "Surface".  If texture is JNI_TRUE, this
+ * method will invoke the Texture->Surface inner loop; otherwise, one of the
+ * Surface->Surface inner loops will be invoked, depending on the transform
+ * state.
+ *
+ * REMIND: we can trick these blit methods into doing XOR simply by passing
+ *         in the (pixel ^ xorpixel) as the pixel value and preceding the
+ *         blit with a fillrect...
+ */
+void
+MTLBlitLoops_IsoBlit(JNIEnv *env,
+                     MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
+                     jboolean xform, jint hint,
+                     jboolean texture, jboolean rtt,
+                     jint sx1, jint sy1, jint sx2, jint sy2,
+                     jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
+    BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
+
+    RETURN_IF_NULL(srcOps);
+    RETURN_IF_NULL(dstOps);
+
+    id<MTLTexture> srcTex = srcOps->pTexture;
+    id<MTLTexture> dstTex = dstOps->pTexture;
+    if (mtlc == NULL || srcTex == nil || srcTex == nil) {
+        J2dTraceLn2(J2D_TRACE_ERROR, "MTLBlitLoops_IsoBlit: surface is null (stex=%p, dtex=%p)", srcTex, dstTex);
+        return;
+    }
+
+    const jint sw    = sx2 - sx1;
+    const jint sh    = sy2 - sy1;
+    const jdouble dw = dx2 - dx1;
+    const jdouble dh = dy2 - dy1;
+
+    if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) {
+        J2dTraceLn4(J2D_TRACE_WARNING, "MTLBlitLoops_IsoBlit: invalid dimensions: sw=%d, sh%d, dw=%d, dh=%d", sw, sh, dw, dh);
+        return;
+    }
+
+    SurfaceDataRasInfo srcInfo;
+    srcInfo.bounds.x1 = sx1;
+    srcInfo.bounds.y1 = sy1;
+    srcInfo.bounds.x2 = sx2;
+    srcInfo.bounds.y2 = sy2;
+    SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds, 0, 0, srcOps->width, srcOps->height);
+
+    if (srcInfo.bounds.x2 <= srcInfo.bounds.x1 || srcInfo.bounds.y2 <= srcInfo.bounds.y1) {
+        J2dTraceLn(J2D_TRACE_VERBOSE, "MTLBlitLoops_IsoBlit: source rectangle doesn't intersect with source surface bounds");
+        J2dTraceLn6(J2D_TRACE_VERBOSE, "  sx1=%d sy1=%d sx2=%d sy2=%d sw=%d sh=%d", sx1, sy1, sx2, sy2, srcOps->width, srcOps->height);
+        J2dTraceLn4(J2D_TRACE_VERBOSE, "  dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
+        return;
+    }
+
+    if (srcInfo.bounds.x1 != sx1) {
+        dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw);
+        sx1 = srcInfo.bounds.x1;
+    }
+    if (srcInfo.bounds.y1 != sy1) {
+        dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh);
+        sy1 = srcInfo.bounds.y1;
+    }
+    if (srcInfo.bounds.x2 != sx2) {
+        dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw);
+        sx2 = srcInfo.bounds.x2;
+    }
+    if (srcInfo.bounds.y2 != sy2) {
+        dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh);
+        sy2 = srcInfo.bounds.y2;
+    }
+
+    const jboolean useBlitEncoder =
+            mtlc.isBlendingDisabled
+            && fabs(dx2 - dx1 - sx2 + sx1) < 0.001f && fabs(dy2 - dy1 - sy2 + sy1) < 0.001f // dimensions are equal (TODO: check that dx1,dy1 is integer)
+            && !mtlc.useTransform; // TODO: check whether transform is simple translate (and use blitEncoder in this case)
+    if (useBlitEncoder) {
+#ifdef DEBUG
+        J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, "MTLBlitLoops_IsoBlit [via blitEncoder]: bdst=%p [tex=%p] %dx%d | src (%d, %d, %d, %d) -> dst (%1.2f, %1.2f, %1.2f, %1.2f)", dstOps, dstTex, dstTex.width, dstTex.height, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif //DEBUG
+        id <MTLBlitCommandEncoder> blitEncoder = [mtlc createBlitEncoder];
+        [blitEncoder copyFromTexture:srcTex sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(sx1, sy1, 0) sourceSize:MTLSizeMake(sx2 - sx1, sy2 - sy1, 1) toTexture:dstTex destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
+        [blitEncoder endEncoding];
+    } else {
+        // TODO: support other flags
+        MTLBlitTextureToSurface(mtlc, srcOps, dstOps, rtt, hint, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+    }
+}
+
+/**
+ * General blit method for copying a system memory ("Sw") surface to a native
+ * MTL surface (of type "Surface" or "Texture").  If texture is JNI_TRUE,
+ * this method will invoke the Sw->Texture inner loop; otherwise, one of the
+ * Sw->Surface inner loops will be invoked, depending on the transform state.
+ */
+void
+MTLBlitLoops_Blit(JNIEnv *env,
+                  MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
+                  jboolean xform, jint hint,
+                  jint srctype, jboolean texture,
+                  jint sx1, jint sy1, jint sx2, jint sy2,
+                  jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
+{
+    RETURN_IF_NULL(jlong_to_ptr(pSrcOps));
+    RETURN_IF_NULL(jlong_to_ptr(pDstOps));
+
+    SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
+    BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
+    SurfaceDataRasInfo srcInfo;
+    MTLPixelFormat pf = MTLPixelFormatBGRA8Unorm;//PixelFormats[srctype];
+
+    if (dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: dest is null");
+        return;
+    }
+    id<MTLTexture> dest = dstOps->pTexture;
+    if (dx1 < 0) {
+        sx1 += dx1;
+        dx1 = 0;
+    }
+    if (dx2 > dest.width) {
+        sx2 -= dx2 - dest.width;
+        dx2 = dest.width;
+    }
+    if (dy1 < 0) {
+        sy1 += dy1;
+        dy1 = 0;
+    }
+    if (dy2 > dest.height) {
+        sy2 -= dy2 - dest.height;
+        dy2 = dest.height;
+    }
+    jint sw    = sx2 - sx1;
+    jint sh    = sy2 - sy1;
+    jdouble dw = dx2 - dx1;
+    jdouble dh = dy2 - dy1;
+
+    if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0 || srctype < 0) {
+        J2dTraceLn(J2D_TRACE_WARNING, "MTLBlitLoops_Blit: invalid dimensions or srctype");
+        return;
+    }
+
+    srcInfo.bounds.x1 = sx1;
+    srcInfo.bounds.y1 = sy1;
+    srcInfo.bounds.x2 = sx2;
+    srcInfo.bounds.y2 = sy2;
+
+    if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
+        J2dTraceLn(J2D_TRACE_WARNING, "MTLBlitLoops_Blit: could not acquire lock");
+        return;
+    }
+
+    J2dTraceLn5(J2D_TRACE_VERBOSE, "MTLBlitLoops_Blit:  pf=%d texture=%d srctype=%d xform=%d hint=%d", pf, texture, srctype, xform, hint);
+
+    if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) {
+        srcOps->GetRasInfo(env, srcOps, &srcInfo);
+        if (srcInfo.rasBase) {
+            if (srcInfo.bounds.x1 != sx1) {
+                dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw);
+                sx1 = srcInfo.bounds.x1;
+            }
+            if (srcInfo.bounds.y1 != sy1) {
+                dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh);
+                sy1 = srcInfo.bounds.y1;
+            }
+            if (srcInfo.bounds.x2 != sx2) {
+                dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw);
+                sx2 = srcInfo.bounds.x2;
+            }
+            if (srcInfo.bounds.y2 != sy2) {
+                dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh);
+                sy2 = srcInfo.bounds.y2;
+            }
+
+            // NOTE: if (texture) => dest coordinates will always be integers since we only ever do a straight copy from sw to texture.
+            const jboolean useReplaceRegion = texture ||
+                    (mtlc.isBlendingDisabled
+                    && fabs(dx2 - dx1 - sx2 + sx1) < 0.001f && fabs(dy2 - dy1 - sy2 + sy1) < 0.001f // dimensions are equal (TODO: check that dx1,dy1 is integer)
+                    && !mtlc.useTransform); // TODO: check whether transform is simple translate (and use replaceRegion in this case)
+            if (useReplaceRegion) {
+                MTLRegion region = MTLRegionMake2D(dx1, dy1, dx2 - dx1, dy2 - dy1);
+#ifdef DEBUG
+                J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, "MTLBlitLoops_Blit [replaceRegion]: bdst=%p [tex=%p] %dx%d | src (%d, %d, %d, %d) -> dst (%1.2f, %1.2f, %1.2f, %1.2f)", dstOps, dest, dest.width, dest.height, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif //DEBUG
+                [dest replaceRegion:region mipmapLevel:0 withBytes:srcInfo.rasBase bytesPerRow:srcInfo.scanStride]; // executed at CPU (sync), TODO: lock dest for current frame
+            } else {
+                MTLBlitSwToSurfaceViaTexture(mtlc, &srcInfo, dstOps, &pf, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+            }
+        }
+        SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
+    }
+    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
+}
+
+/**
+ * Specialized blit method for copying a native MTL "Surface" (pbuffer,
+ * window, etc.) to a system memory ("Sw") surface.
+ */
+void
+MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
+                             jlong pSrcOps, jlong pDstOps, jint dsttype,
+                             jint srcx, jint srcy, jint dstx, jint dsty,
+                             jint width, jint height)
+{
+    //TODO
+    //J2dTraceNotImplPrimitive("MTLBlitLoops_SurfaceToSwBlit");
+}
+
+void
+MTLBlitLoops_CopyArea(JNIEnv *env,
+                      MTLContext *mtlc, BMTLSDOps *dstOps,
+                      jint x, jint y, jint width, jint height,
+                      jint dx, jint dy)
+{
+    //TODO
+    //J2dTraceNotImplPrimitive("MTLBlitLoops_CopyArea");
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLBufImgOps_h_Included
+#define MTLBufImgOps_h_Included
+
+#include "MTLContext.h"
+
+void MTLBufImgOps_EnableConvolveOp(MTLContext *mtlc, jlong pSrcOps,
+                                   jboolean edgeZeroFill,
+                                   jint kernelWidth, jint KernelHeight,
+                                   unsigned char *kernelVals);
+void MTLBufImgOps_DisableConvolveOp(MTLContext *mtlc);
+void MTLBufImgOps_EnableRescaleOp(MTLContext *mtlc, jlong pSrcOps,
+                                  jboolean nonPremult,
+                                  unsigned char *scaleFactors,
+                                  unsigned char *offsets);
+void MTLBufImgOps_DisableRescaleOp(MTLContext *mtlc);
+void MTLBufImgOps_EnableLookupOp(MTLContext *mtlc, jlong pSrcOps,
+                                 jboolean nonPremult, jboolean shortData,
+                                 jint numBands, jint bandLength, jint offset,
+                                 void *tableValues);
+void MTLBufImgOps_DisableLookupOp(MTLContext *mtlc);
+
+#endif /* MTLBufImgOps_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,369 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <jlong.h>
+
+#include "MTLBufImgOps.h"
+#include "MTLContext.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceDataBase.h"
+#include "GraphicsPrimitiveMgr.h"
+
+/** Evaluates to true if the given bit is set on the local flags variable. */
+#define IS_SET(flagbit) \
+    (((flags) & (flagbit)) != 0)
+
+/**************************** ConvolveOp support ****************************/
+
+/**
+ * The ConvolveOp shader is fairly straightforward.  For each texel in
+ * the source texture, the shader samples the MxN texels in the surrounding
+ * area, multiplies each by its corresponding kernel value, and then sums
+ * them all together to produce a single color result.  Finally, the
+ * resulting value is multiplied by the current OpenGL color, which contains
+ * the extra alpha value.
+ *
+ * Note that this shader source code includes some "holes" marked by "%s".
+ * This allows us to build different shader programs (e.g. one for
+ * 3x3, one for 5x5, and so on) simply by filling in these "holes" with
+ * a call to sprintf().  See the MTLBufImgOps_CreateConvolveProgram() method
+ * for more details.
+ *
+ * REMIND: Currently this shader (and the supporting code in the
+ *         EnableConvolveOp() method) only supports 3x3 and 5x5 filters.
+ *         Early shader-level hardware did not support non-constant sized
+ *         arrays but modern hardware should support them (although I
+ *         don't know of any simple way to find out, other than to compile
+ *         the shader at runtime and see if the drivers complain).
+ */
+static const char *convolveShaderSource =
+    // maximum size supported by this shader
+    "const int MAX_KERNEL_SIZE = %s;"
+    // image to be convolved
+    "uniform sampler%s baseImage;"
+    // image edge limits:
+    //   imgEdge.xy = imgMin.xy (anything < will be treated as edge case)
+    //   imgEdge.zw = imgMax.xy (anything > will be treated as edge case)
+    "uniform vec4 imgEdge;"
+    // value for each location in the convolution kernel:
+    //   kernelVals[i].x = offsetX[i]
+    //   kernelVals[i].y = offsetY[i]
+    //   kernelVals[i].z = kernel[i]
+    "uniform vec3 kernelVals[MAX_KERNEL_SIZE];"
+    ""
+    "void main(void)"
+    "{"
+    "    int i;"
+    "    vec4 sum;"
+    ""
+    "    if (any(lessThan(gl_TexCoord[0].st, imgEdge.xy)) ||"
+    "        any(greaterThan(gl_TexCoord[0].st, imgEdge.zw)))"
+    "    {"
+             // (placeholder for edge condition code)
+    "        %s"
+    "    } else {"
+    "        sum = vec4(0.0);"
+    "        for (i = 0; i < MAX_KERNEL_SIZE; i++) {"
+    "            sum +="
+    "                kernelVals[i].z *"
+    "                texture%s(baseImage,"
+    "                          gl_TexCoord[0].st + kernelVals[i].xy);"
+    "        }"
+    "    }"
+    ""
+         // modulate with gl_Color in order to apply extra alpha
+    "    gl_FragColor = sum * gl_Color;"
+    "}";
+
+/**
+ * Flags that can be bitwise-or'ed together to control how the shader
+ * source code is generated.
+ */
+#define CONVOLVE_RECT            (1 << 0)
+#define CONVOLVE_EDGE_ZERO_FILL  (1 << 1)
+#define CONVOLVE_5X5             (1 << 2)
+
+/**
+ * The handles to the ConvolveOp fragment program objects.  The index to
+ * the array should be a bitwise-or'ing of the CONVOLVE_* flags defined
+ * above.  Note that most applications will likely need to initialize one
+ * or two of these elements, so the array is usually sparsely populated.
+ */
+static GLhandleARB convolvePrograms[8];
+
+/**
+ * The maximum kernel size supported by the ConvolveOp shader.
+ */
+#define MAX_KERNEL_SIZE 25
+
+/**
+ * Compiles and links the ConvolveOp shader program.  If successful, this
+ * function returns a handle to the newly created shader program; otherwise
+ * returns 0.
+ */
+static GLhandleARB
+MTLBufImgOps_CreateConvolveProgram(jint flags)
+{
+    //TODO
+    return NULL;
+}
+
+void
+MTLBufImgOps_EnableConvolveOp(MTLContext *mtlc, jlong pSrcOps,
+                              jboolean edgeZeroFill,
+                              jint kernelWidth, jint kernelHeight,
+                              unsigned char *kernel)
+{
+    //TODO
+}
+
+void
+MTLBufImgOps_DisableConvolveOp(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLBufImgOps_DisableConvolveOp");
+}
+
+/**************************** RescaleOp support *****************************/
+
+/**
+ * The RescaleOp shader is one of the simplest possible.  Each fragment
+ * from the source image is multiplied by the user's scale factor and added
+ * to the user's offset value (these are component-wise operations).
+ * Finally, the resulting value is multiplied by the current OpenGL color,
+ * which contains the extra alpha value.
+ *
+ * The RescaleOp spec says that the operation is performed regardless of
+ * whether the source data is premultiplied or non-premultiplied.  This is
+ * a problem for the OpenGL pipeline in that a non-premultiplied
+ * BufferedImage will have already been converted into premultiplied
+ * when uploaded to an OpenGL texture.  Therefore, we have a special mode
+ * called RESCALE_NON_PREMULT (used only for source images that were
+ * originally non-premultiplied) that un-premultiplies the source color
+ * prior to the rescale operation, then re-premultiplies the resulting
+ * color before returning from the fragment shader.
+ *
+ * Note that this shader source code includes some "holes" marked by "%s".
+ * This allows us to build different shader programs (e.g. one for
+ * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
+ * simply by filling in these "holes" with a call to sprintf().  See the
+ * MTLBufImgOps_CreateRescaleProgram() method for more details.
+ */
+static const char *rescaleShaderSource =
+    // image to be rescaled
+    "uniform sampler%s baseImage;"
+    // vector containing scale factors
+    "uniform vec4 scaleFactors;"
+    // vector containing offsets
+    "uniform vec4 offsets;"
+    ""
+    "void main(void)"
+    "{"
+    "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
+         // (placeholder for un-premult code)
+    "    %s"
+         // rescale source value
+    "    vec4 result = (srcColor * scaleFactors) + offsets;"
+         // (placeholder for re-premult code)
+    "    %s"
+         // modulate with gl_Color in order to apply extra alpha
+    "    gl_FragColor = result * gl_Color;"
+    "}";
+
+/**
+ * Flags that can be bitwise-or'ed together to control how the shader
+ * source code is generated.
+ */
+#define RESCALE_RECT        (1 << 0)
+#define RESCALE_NON_PREMULT (1 << 1)
+
+/**
+ * The handles to the RescaleOp fragment program objects.  The index to
+ * the array should be a bitwise-or'ing of the RESCALE_* flags defined
+ * above.  Note that most applications will likely need to initialize one
+ * or two of these elements, so the array is usually sparsely populated.
+ */
+static GLhandleARB rescalePrograms[4];
+
+/**
+ * Compiles and links the RescaleOp shader program.  If successful, this
+ * function returns a handle to the newly created shader program; otherwise
+ * returns 0.
+ */
+static GLhandleARB
+MTLBufImgOps_CreateRescaleProgram(jint flags)
+{
+    //TODO
+    return NULL;
+}
+
+void
+MTLBufImgOps_EnableRescaleOp(MTLContext *mtlc, jlong pSrcOps,
+                             jboolean nonPremult,
+                             unsigned char *scaleFactors,
+                             unsigned char *offsets)
+{
+    //TODO
+}
+
+void
+MTLBufImgOps_DisableRescaleOp(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLBufImgOps_DisableRescaleOp");
+    RETURN_IF_NULL(mtlc);
+}
+
+/**************************** LookupOp support ******************************/
+
+/**
+ * The LookupOp shader takes a fragment color (from the source texture) as
+ * input, subtracts the optional user offset value, and then uses the
+ * resulting value to index into the lookup table texture to provide
+ * a new color result.  Finally, the resulting value is multiplied by
+ * the current OpenGL color, which contains the extra alpha value.
+ *
+ * The lookup step requires 3 texture accesses (or 4, when alpha is included),
+ * which is somewhat unfortunate because it's not ideal from a performance
+ * standpoint, but that sort of thing is getting faster with newer hardware.
+ * In the 3-band case, we could consider using a three-dimensional texture
+ * and performing the lookup with a single texture access step.  We already
+ * use this approach in the LCD text shader, and it works well, but for the
+ * purposes of this LookupOp shader, it's probably overkill.  Also, there's
+ * a difference in that the LCD text shader only needs to populate the 3D LUT
+ * once, but here we would need to populate it on every invocation, which
+ * would likely be a waste of VRAM and CPU/GPU cycles.
+ *
+ * The LUT texture is currently hardcoded as 4 rows/bands, each containing
+ * 256 elements.  This means that we currently only support user-provided
+ * tables with no more than 256 elements in each band (this is checked at
+ * at the Java level).  If the user provides a table with less than 256
+ * elements per band, our shader will still work fine, but if elements are
+ * accessed with an index >= the size of the LUT, then the shader will simply
+ * produce undefined values.  Typically the user would provide an offset
+ * value that would prevent this from happening, but it's worth pointing out
+ * this fact because the software LookupOp implementation would usually
+ * throw an ArrayIndexOutOfBoundsException in this scenario (although it is
+ * not something demanded by the spec).
+ *
+ * The LookupOp spec says that the operation is performed regardless of
+ * whether the source data is premultiplied or non-premultiplied.  This is
+ * a problem for the OpenGL pipeline in that a non-premultiplied
+ * BufferedImage will have already been converted into premultiplied
+ * when uploaded to an OpenGL texture.  Therefore, we have a special mode
+ * called LOOKUP_NON_PREMULT (used only for source images that were
+ * originally non-premultiplied) that un-premultiplies the source color
+ * prior to the lookup operation, then re-premultiplies the resulting
+ * color before returning from the fragment shader.
+ *
+ * Note that this shader source code includes some "holes" marked by "%s".
+ * This allows us to build different shader programs (e.g. one for
+ * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
+ * simply by filling in these "holes" with a call to sprintf().  See the
+ * MTLBufImgOps_CreateLookupProgram() method for more details.
+ */
+static const char *lookupShaderSource =
+    // source image (bound to texture unit 0)
+    "uniform sampler%s baseImage;"
+    // lookup table (bound to texture unit 1)
+    "uniform sampler2D lookupTable;"
+    // offset subtracted from source index prior to lookup step
+    "uniform vec4 offset;"
+    ""
+    "void main(void)"
+    "{"
+    "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
+         // (placeholder for un-premult code)
+    "    %s"
+         // subtract offset from original index
+    "    vec4 srcIndex = srcColor - offset;"
+         // use source value as input to lookup table (note that
+         // "v" texcoords are hardcoded to hit texel centers of
+         // each row/band in texture)
+    "    vec4 result;"
+    "    result.r = texture2D(lookupTable, vec2(srcIndex.r, 0.125)).r;"
+    "    result.g = texture2D(lookupTable, vec2(srcIndex.g, 0.375)).r;"
+    "    result.b = texture2D(lookupTable, vec2(srcIndex.b, 0.625)).r;"
+         // (placeholder for alpha store code)
+    "    %s"
+         // (placeholder for re-premult code)
+    "    %s"
+         // modulate with gl_Color in order to apply extra alpha
+    "    gl_FragColor = result * gl_Color;"
+    "}";
+
+/**
+ * Flags that can be bitwise-or'ed together to control how the shader
+ * source code is generated.
+ */
+#define LOOKUP_RECT          (1 << 0)
+#define LOOKUP_USE_SRC_ALPHA (1 << 1)
+#define LOOKUP_NON_PREMULT   (1 << 2)
+
+/**
+ * The handles to the LookupOp fragment program objects.  The index to
+ * the array should be a bitwise-or'ing of the LOOKUP_* flags defined
+ * above.  Note that most applications will likely need to initialize one
+ * or two of these elements, so the array is usually sparsely populated.
+ */
+static GLhandleARB lookupPrograms[8];
+
+/**
+ * The handle to the lookup table texture object used by the shader.
+ */
+static GLuint lutTextureID = 0;
+
+/**
+ * Compiles and links the LookupOp shader program.  If successful, this
+ * function returns a handle to the newly created shader program; otherwise
+ * returns 0.
+ */
+static GLhandleARB
+MTLBufImgOps_CreateLookupProgram(jint flags)
+{
+    //TODO
+
+    return NULL;
+}
+
+void
+MTLBufImgOps_EnableLookupOp(MTLContext *mtlc, jlong pSrcOps,
+                            jboolean nonPremult, jboolean shortData,
+                            jint numBands, jint bandLength, jint offset,
+                            void *tableValues)
+{
+    //TODO
+}
+
+void
+MTLBufImgOps_DisableLookupOp(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLBufImgOps_DisableLookupOp");
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLContext_h_Included
+#define MTLContext_h_Included
+
+#include <simd/simd.h>
+
+#include "sun_java2d_pipe_BufferedContext.h"
+#include "sun_java2d_metal_MTLContext.h"
+#include "sun_java2d_metal_MTLContext_MTLContextCaps.h"
+
+#import <Metal/Metal.h>
+#include "j2d_md.h"
+#include "MTLSurfaceDataBase.h"
+#include "MTLTexturePool.h"
+#include "MTLPipelineStatesStorage.h"
+
+/**
+ * The MTLBlendRule structure encapsulates the two enumerated values that
+ * comprise a given Porter-Duff blending (compositing) rule.  For example,
+ * the "SrcOver" rule can be represented by:
+ *     rule.src = GL_ONE;
+ *     rule.dst = GL_ONE_MINUS_SRC_ALPHA;
+ *
+ *     GLenum src;
+ * The constant representing the source factor in this Porter-Duff rule.
+ *
+ *     GLenum dst;
+ * The constant representing the destination factor in this Porter-Duff rule.
+ */
+typedef struct {
+    jint src;
+    jint dst;
+} MTLBlendRule;
+
+/**
+ * The MTLContext class contains cached state relevant to the native
+ * MTL context stored within the native ctxInfo field.  Each Java-level
+ * MTLContext object is associated with a native-level MTLContext class.
+ * */
+@interface MTLContext : NSObject
+
+@property jint          compState;
+@property jfloat        extraAlpha;
+@property jint          alphaCompositeRule;
+@property jint          xorPixel;
+@property jint          pixel;
+
+@property jdouble       p0;
+@property jdouble       p1;
+@property jdouble       p3;
+@property jboolean      cyclic;
+@property jint          pixel1;
+@property jint          pixel2;
+
+@property jubyte        r;
+@property jubyte        g;
+@property jubyte        b;
+@property jubyte        a;
+@property jint          paintState;
+@property jboolean      useMask;
+@property jboolean      useTransform;
+@property simd_float4x4 transform4x4;
+@property jint          blitTextureID;
+@property jint          textureFunction;
+@property jboolean      vertexCacheEnabled;
+
+@property (readonly, strong)   id<MTLDevice>   device;
+@property (strong) id<MTLLibrary>              library;
+@property (strong) id<MTLRenderPipelineState>  pipelineState;
+@property (strong) id<MTLCommandQueue>         commandQueue;
+@property (readonly,strong) id<MTLCommandBuffer>        commandBuffer;
+@property (strong) id<MTLBuffer>               vertexBuffer;
+@property jint                        color;
+@property MTLScissorRect              clipRect;
+@property jboolean                    useClip;
+@property (strong)MTLPipelineStatesStorage*   pipelineStateStorage;
+@property (strong)MTLTexturePool*             texturePool;
+
+- (void)releaseCommandBuffer;
+/**
+ * Fetches the MTLContext associated with the given destination surface,
+ * makes the context current for those surfaces, updates the destination
+ * viewport, and then returns a pointer to the MTLContext.
+ */
++ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst;
+
+- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib;
+
+/**
+ * Resets the current clip state (disables both scissor and depth tests).
+ */
+- (void)resetClip;
+
+/**
+ * Sets the Metal scissor bounds to the provided rectangular clip bounds.
+ */
+- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2;
+
+/**
+ * Sets up a complex (shape) clip using the OpenGL depth buffer.  This
+ * method prepares the depth buffer so that the clip Region spans can
+ * be "rendered" into it.  The depth buffer is first cleared, then the
+ * depth func is setup so that when we render the clip spans,
+ * nothing is rendered into the color buffer, but for each pixel that would
+ * be rendered, a non-zero value is placed into that location in the depth
+ * buffer.  With depth test enabled, pixels will only be rendered into the
+ * color buffer if the corresponding value at that (x,y) location in the
+ * depth buffer differs from the incoming depth value.
+ */
+- (void)beginShapeClip;
+
+/**
+ * Finishes setting up the shape clip by resetting the depth func
+ * so that future rendering operations will once again be written into the
+ * color buffer (while respecting the clip set up in the depth buffer).
+ */
+- (void)endShapeClip;
+
+/**
+ * Initializes the OpenGL state responsible for applying extra alpha.  This
+ * step is only necessary for any operation that uses glDrawPixels() or
+ * glCopyPixels() with a non-1.0f extra alpha value.  Since the source is
+ * always premultiplied, we apply the extra alpha value to both alpha and
+ * color components using GL_*_SCALE.
+ */
+- (void)setExtraAlpha:(jfloat)ea;
+
+/**
+ * Resets all OpenGL compositing state (disables blending and logic
+ * operations).
+ */
+- (void)resetComposite;
+
+/**
+ * Initializes the OpenGL blending state.  XOR mode is disabled and the
+ * appropriate blend functions are setup based on the AlphaComposite rule
+ * constant.
+ */
+- (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha
+                        flags:(jint)flags;
+
+/**
+ * Initializes the OpenGL logic op state to XOR mode.  Blending is disabled
+ * before enabling logic op mode.  The XOR pixel value will be applied
+ * later in the MTLContext_SetColor() method.
+ */
+- (void)setXorComposite:(jint)xorPixel;
+- (jboolean)isBlendingDisabled;
+
+/**
+ * Resets the OpenGL transform state back to the identity matrix.
+ */
+- (void)resetTransform;
+
+/**
+ * Initializes the OpenGL transform state by setting the modelview transform
+ * using the given matrix parameters.
+ *
+ * REMIND: it may be worthwhile to add serial id to AffineTransform, so we
+ *         could do a quick check to see if the xform has changed since
+ *         last time... a simple object compare won't suffice...
+ */
+- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
+                    M01:(jdouble) m01 M11:(jdouble) m11
+                    M02:(jdouble) m02 M12:(jdouble) m12;
+
+/**
+ * Initializes a small texture tile for use with tiled blit operations (see
+ * MTLBlitLoops.c and MTLMaskBlit.c for usage examples).  The texture ID for
+ * the tile is stored in the given MTLContext.  The tile is initially filled
+ * with garbage values, but the tile is updated as needed (via
+ * glTexSubImage2D()) with real RGBA values used in tiled blit situations.
+ * The internal format for the texture is GL_RGBA8, which should be sufficient
+ * for storing system memory surfaces of any known format (see PixelFormats
+ * for a list of compatible surface formats).
+ */
+- (jboolean)initBlitTileTexture;
+
+
+/**
+ * Creates a 2D texture of the given format and dimensions and returns the
+ * texture object identifier.  This method is typically used to create a
+ * temporary texture for intermediate work, such as in the
+ * MTLContext_InitBlitTileTexture() method below.
+ */
+- (jint)createBlitTextureFormat:(jint)internalFormat pixelFormat:(jint)pixelFormat
+                          width:(jint)width height:(jint)height;
+
+- (void)destroyContextResources;
+
+- (void)setColorR:(int)r G:(int)g B:(int)b A:(int)a;
+- (void)setColorInt:(int)pixel;
+
+- (id<MTLRenderCommandEncoder>)createSamplingEncoderForDest:(id<MTLTexture>)dest clearRed:(int)clearRed;
+- (id<MTLRenderCommandEncoder>)createSamplingEncoderForDest:(id<MTLTexture>)dest;
+- (id<MTLBlitCommandEncoder>)createBlitEncoder;
+// NOTE: debug parameners will be removed soon
+- (id<MTLRenderCommandEncoder>)createRenderEncoderForDest:(id<MTLTexture>)dest clearRed:(int) clearRed/*debug param*/;
+- (id<MTLRenderCommandEncoder>)createRenderEncoderForDest:(id<MTLTexture>)dest;
+- (void)setGradientPaintUseMask:(jboolean)useMask cyclic:(jboolean)cyclic p0:(jdouble) p0 p1:(jdouble) p1 p3:(jdouble)p3
+                         pixel1:(jint)pixel1 pixel2:(jint) pixel2;
+- (void) setEncoderTransform:(id<MTLRenderCommandEncoder>) encoder dest:(id<MTLTexture>) dest;
+- (void)dealloc;
+@end
+
+/**
+ * See BufferedContext.java for more on these flags...
+ */
+#define MTLC_NO_CONTEXT_FLAGS \
+    sun_java2d_pipe_BufferedContext_NO_CONTEXT_FLAGS
+#define MTLC_SRC_IS_OPAQUE    \
+    sun_java2d_pipe_BufferedContext_SRC_IS_OPAQUE
+#define MTLC_USE_MASK         \
+    sun_java2d_pipe_BufferedContext_USE_MASK
+
+#endif /* MTLContext_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,434 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "sun_java2d_SunGraphics2D.h"
+
+#include "jlong.h"
+#include "jni_util.h"
+#import "MTLContext.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceDataBase.h"
+#include "GraphicsPrimitiveMgr.h"
+#include "Region.h"
+#include "common.h"
+
+#include "jvm.h"
+
+extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);
+extern MTLContext *MTLSD_MakeMTLContextCurrent(JNIEnv *env,
+                                               MTLSDOps *srcOps,
+                                               MTLSDOps *dstOps);
+
+#define RGBA_TO_V4(c)              \
+{                                  \
+    (((c) >> 16) & (0xFF))/255.0f, \
+    (((c) >> 8) & 0xFF)/255.0f,    \
+    ((c) & 0xFF)/255.0f,           \
+    (((c) >> 24) & 0xFF)/255.0f    \
+}
+
+/**
+ * This table contains the standard blending rules (or Porter-Duff compositing
+ * factors) used in glBlendFunc(), indexed by the rule constants from the
+ * AlphaComposite class.
+ */
+MTLBlendRule MTStdBlendRules[] = {
+};
+
+static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = {
+        {{-1.0, 1.0, 0.0}, {0.0, 0.0}},
+        {{1.0, 1.0, 0.0}, {1.0, 0.0}},
+        {{1.0, -1.0, 0.0}, {1.0, 1.0}},
+        {{1.0, -1.0, 0.0}, {1.0, 1.0}},
+        {{-1.0, -1.0, 0.0}, {0.0, 1.0}},
+        {{-1.0, 1.0, 0.0}, {0.0, 0.0}}
+};
+
+
+static void _traceMatrix(simd_float4x4 * mtx) {
+    for (int row = 0; row < 4; ++row) {
+        J2dTraceLn4(J2D_TRACE_VERBOSE, "  [%lf %lf %lf %lf]",
+                    mtx->columns[0][row], mtx->columns[1][row], mtx->columns[2][row], mtx->columns[3][row]);
+    }
+}
+
+MTLRenderPassDescriptor* createRenderPassDesc(id<MTLTexture> dest) {
+    MTLRenderPassDescriptor * result = [MTLRenderPassDescriptor renderPassDescriptor];
+    if (result == nil)
+        return nil;
+
+    if (dest == nil) {
+        J2dTraceLn(J2D_TRACE_ERROR, "_createRenderPassDesc: destination texture is null");
+        return nil;
+    }
+
+    MTLRenderPassColorAttachmentDescriptor * ca = result.colorAttachments[0];
+    ca.texture = dest;
+    ca.loadAction = MTLLoadActionLoad;
+    ca.clearColor = MTLClearColorMake(0.0f, 0.9f, 0.0f, 1.0f);
+    ca.storeAction = MTLStoreActionStore;
+    return result;
+}
+
+@implementation MTLContext {
+    id<MTLCommandBuffer> _commandBuffer;
+}
+
+@synthesize compState, extraAlpha, alphaCompositeRule, xorPixel, pixel, p0,
+            p1, p3, cyclic, pixel1, pixel2, r, g, b, a, paintState, useMask,
+            useTransform, transform4x4, blitTextureID, textureFunction,
+            vertexCacheEnabled, device, library, pipelineState, pipelineStateStorage,
+            commandQueue, vertexBuffer,
+            color, clipRect, useClip, texturePool;
+
+
+ - (id<MTLCommandBuffer>) commandBuffer {
+    if (_commandBuffer == nil) {
+        // NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously.
+        _commandBuffer = [[self.commandQueue commandBuffer] retain];// released in [layer blitTexture]
+    }
+    return _commandBuffer;
+}
+
+- (void)releaseCommandBuffer {
+    [_commandBuffer release];
+    _commandBuffer = nil;
+}
+
++ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst {
+    BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc);
+    BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);
+    MTLContext *mtlc = NULL;
+
+    if (srcOps == NULL || dstOps == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null");
+        return NULL;
+    }
+
+    J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", srcOps, srcOps->pTexture, srcOps->drawableType, dstOps, dstOps->pTexture, dstOps->drawableType);
+
+    if (dstOps->drawableType == MTLSD_TEXTURE) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "MTLContext_SetSurfaces: texture cannot be used as destination");
+        return NULL;
+    }
+
+    if (dstOps->drawableType == MTLSD_UNDEFINED) {
+        // initialize the surface as an OGLSD_WINDOW
+        if (!MTLSD_InitMTLWindow(env, dstOps)) {
+            J2dRlsTraceLn(J2D_TRACE_ERROR,
+                          "MTLContext_SetSurfaces: could not init OGL window");
+            return NULL;
+        }
+    }
+
+    // make the context current
+    MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps;
+    mtlc = dstCGLOps->configInfo->context;
+
+    if (mtlc == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "MTLContext_SetSurfaces: could not make context current");
+        return NULL;
+    }
+
+    // perform additional one-time initialization, if necessary
+    if (dstOps->needsInit) {
+        if (dstOps->isOpaque) {
+            // in this case we are treating the destination as opaque, but
+            // to do so, first we need to ensure that the alpha channel
+            // is filled with fully opaque values (see 6319663)
+            //MTLContext_InitAlphaChannel();
+        }
+        dstOps->needsInit = JNI_FALSE;
+    }
+
+    return mtlc;
+}
+
+- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {
+    self = [super init];
+    if (self) {
+        // Initialization code here.
+        device = d;
+
+        texturePool = [[MTLTexturePool alloc] initWithDevice:device];
+        pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib];
+
+        vertexBuffer = [device newBufferWithBytes:verts
+                                           length:sizeof(verts)
+                                          options:MTLResourceCPUCacheModeDefaultCache];
+
+        NSError *error = nil;
+
+        library = [device newLibraryWithFile:shadersLib error:&error];
+        if (!library) {
+            NSLog(@"Failed to load library. error %@", error);
+            exit(0);
+        }
+
+        _commandBuffer = nil;
+
+        // Create command queue
+        commandQueue = [device newCommandQueue];
+    }
+    return self;
+}
+
+- (void)resetClip {
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip");
+    useClip = JNI_FALSE;
+}
+
+- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {
+    //TODO
+    jint width = x2 - x1;
+    jint height = y2 - y1;
+
+    J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setClipRect: x=%d y=%d w=%d h=%d", x1, y1, width, height);
+
+    clipRect.x = x1;
+    clipRect.y = y1;
+    clipRect.width = width;
+    clipRect.height = height;
+    useClip = JNI_TRUE;
+}
+
+- (void)beginShapeClip {
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip");
+}
+
+- (void)endShapeClip {
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip");
+}
+
+- (void)resetComposite {
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetComposite");
+}
+
+- (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)_extraAlpha
+                        flags:(jint)flags {
+    J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags);
+
+    extraAlpha = _extraAlpha;
+    alphaCompositeRule = rule;
+}
+
+
+- (void)setXorComposite:(jint)xp {
+    //TODO
+    J2dTraceLn1(J2D_TRACE_INFO,
+                "MTLContext.setXorComposite: xorPixel=%08x", xp);
+}
+
+- (jboolean)isBlendingDisabled {
+    // TODO: hold case mtlc->alphaCompositeRule == RULE_SrcOver && sun_java2d_pipe_BufferedContext_SRC_IS_OPAQUE
+    return alphaCompositeRule == RULE_Src && (extraAlpha - 1.0f < 0.001f);
+}
+
+
+- (void)resetTransform {
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform");
+    useTransform = JNI_FALSE;
+}
+
+- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
+                    M01:(jdouble) m01 M11:(jdouble) m11
+                    M02:(jdouble) m02 M12:(jdouble) m12 {
+
+
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform");
+
+    memset(&(transform4x4), 0, sizeof(transform4x4));
+    transform4x4.columns[0][0] = m00;
+    transform4x4.columns[0][1] = m10;
+    transform4x4.columns[1][0] = m01;
+    transform4x4.columns[1][1] = m11;
+    transform4x4.columns[3][0] = m02;
+    transform4x4.columns[3][1] = m12;
+    transform4x4.columns[3][3] = 1.0;
+    transform4x4.columns[4][4] = 1.0;
+    useTransform = JNI_TRUE;
+}
+
+- (jboolean)initBlitTileTexture {
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture");
+
+    return JNI_TRUE;
+}
+
+- (jint)createBlitTextureFormat:(jint)internalFormat pixelFormat:(jint)pixelFormat
+                          width:(jint)width height:(jint)height {
+    //TODO
+    return 0;
+}
+
+
+- (void)setColorR:(int)_r G:(int)_g B:(int)_b A:(int)_a {
+    color = 0;
+    color |= (_r & (0xFF)) << 16;
+    color |= (_g & (0xFF)) << 8;
+    color |= _b & (0xFF);
+    color |= (_a & (0xFF)) << 24;
+    J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setColor (%d, %d, %d) %d", r,g,b,a);
+}
+
+- (void)setColorInt:(int)_pixel {
+    color = _pixel;
+    J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorInt: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF);
+}
+
+- (id<MTLRenderCommandEncoder>) createEncoderForDest:(id<MTLTexture>) dest {
+    id<MTLCommandBuffer> cb = self.commandBuffer;
+    if (cb == nil)
+        return nil;
+
+    MTLRenderPassDescriptor * rpd = createRenderPassDesc(dest);
+    if (rpd == nil)
+        return nil;
+
+    // J2dTraceLn1(J2D_TRACE_VERBOSE, "MTLContext: created render encoder to draw on tex=%p", dest);
+    return [cb renderCommandEncoderWithDescriptor:rpd];
+}
+
+- (void) setEncoderTransform:(id<MTLRenderCommandEncoder>) encoder dest:(id<MTLTexture>) dest {
+    simd_float4x4 normalize;
+    memset(&normalize, 0, sizeof(normalize));
+    normalize.columns[0][0] = 2/(double)dest.width;
+    normalize.columns[1][1] = -2/(double)dest.height;
+    normalize.columns[3][0] = -1.f;
+    normalize.columns[3][1] = 1.f;
+    normalize.columns[3][3] = 1.0;
+    normalize.columns[4][4] = 1.0;
+
+    if (useTransform) {
+        simd_float4x4 vertexMatrix = simd_mul(normalize, transform4x4);
+        [encoder setVertexBytes:&(vertexMatrix) length:sizeof(vertexMatrix) atIndex:MatrixBuffer];
+    } else {
+        [encoder setVertexBytes:&(normalize) length:sizeof(normalize) atIndex:MatrixBuffer];
+    }
+}
+
+- (id<MTLRenderCommandEncoder>) createRenderEncoderForDest:(id<MTLTexture>) dest {
+    id <MTLRenderCommandEncoder> mtlEncoder = [self createEncoderForDest: dest];
+    if (useClip)
+        [mtlEncoder setScissorRect:clipRect];
+
+    if (compState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) {
+        // set pipeline state
+        [mtlEncoder setRenderPipelineState:[self.pipelineStateStorage getRenderPipelineState:NO]];
+        struct FrameUniforms uf = {RGBA_TO_V4(color)};
+        [mtlEncoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
+    } else if (compState == sun_java2d_SunGraphics2D_PAINT_GRADIENT) {
+        // set viewport and pipeline state
+        //[mtlEncoder setRenderPipelineState:gradPipelineState];
+        [mtlEncoder setRenderPipelineState:[self.pipelineStateStorage getRenderPipelineState:YES]];
+
+        struct GradFrameUniforms uf = {
+                {p0, p1, p3},
+                RGBA_TO_V4(pixel1),
+                RGBA_TO_V4(pixel2)};
+
+        [mtlEncoder setFragmentBytes: &uf length:sizeof(uf) atIndex:0];
+    }
+    [self setEncoderTransform:mtlEncoder dest:dest];
+    return mtlEncoder;
+}
+
+- (id<MTLRenderCommandEncoder>)createSamplingEncoderForDest:(id<MTLTexture>)dest {
+    id <MTLRenderCommandEncoder> mtlEncoder = [self createRenderEncoderForDest:dest];
+    [mtlEncoder setRenderPipelineState:[pipelineStateStorage getTexturePipelineState:NO compositeRule:alphaCompositeRule]];
+    [self setEncoderTransform:mtlEncoder dest:dest];
+    return mtlEncoder;
+}
+
+- (id<MTLBlitCommandEncoder>)createBlitEncoder {
+    return _commandBuffer == nil ? nil : [_commandBuffer blitCommandEncoder];
+}
+
+- (void)dealloc {
+    J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc");
+
+    self.texturePool = nil;
+    self.library = nil;
+    self.vertexBuffer = nil;
+    self.commandQueue = nil;
+    self.pipelineState = nil;
+    self.pipelineStateStorage = nil;
+    [super dealloc];
+}
+
+- (void)setGradientPaintUseMask:(jboolean)_useMask cyclic:(jboolean)_cyclic p0:(jdouble) _p0 p1:(jdouble)_p1
+                             p3:(jdouble)_p3 pixel1:(jint)_pixel1 pixel2:(jint)_pixel2 {
+
+    //TODO Resolve gradient distribution problem
+    //TODO Implement useMask
+    //TODO Implement cyclic
+    //fprintf(stderr,
+    //        "MTLPaints_SetGradientPaint useMask=%d cyclic=%d "
+    //        "p0=%f p1=%f p3=%f pix1=%d pix2=%d\n", useMask, cyclic,
+    //        p0, p1, p3, pixel1, pixel2);
+
+    compState = sun_java2d_SunGraphics2D_PAINT_GRADIENT;
+    useMask = _useMask;
+    pixel1 = _pixel1;
+    pixel2 = _pixel2;
+    p0 = _p0;
+    p1 = _p1;
+    p3 = _p3;
+    cyclic = _cyclic;
+ }
+
+@end
+
+/*
+ * Class:     sun_java2d_metal_MTLContext
+ * Method:    getMTLIdString
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_java2d_metal_MTLContext_getMTLIdString
+  (JNIEnv *env, jclass mtlcc)
+{
+    char *vendor, *renderer, *version;
+    char *pAdapterId;
+    jobject ret = NULL;
+    int len;
+
+    return NULL;
+}
+
+
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLFuncs.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLFuncs_h_Included
+#define MTLFuncs_h_Included
+
+#ifdef MACOSX
+#include <dlfcn.h>
+#endif
+#include "jni.h"
+#include "Trace.h"
+
+jboolean MTLFuncs_OpenLibrary();
+void     MTLFuncs_CloseLibrary();
+jboolean MTLFuncs_InitPlatformFuncs();
+jboolean MTLFuncs_InitBaseFuncs();
+jboolean MTLFuncs_InitExtFuncs();
+
+#endif /* MTLFuncs_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLFuncs.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include "MTLFuncs.h"
+
+
+jboolean
+MTLFuncs_OpenLibrary()
+{
+    //TODO
+
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLFuncs_OpenLibrary");
+
+
+    return JNI_TRUE;
+}
+
+void
+MTLFuncs_CloseLibrary()
+{
+    //TODO
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLFuncs_CloseLibrary");
+
+}
+
+jboolean
+MTLFuncs_InitPlatformFuncs()
+{
+    //TODO
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLFuncs_InitPlatformFuncs");
+
+    return JNI_TRUE;
+}
+
+jboolean
+MTLFuncs_InitBaseFuncs()
+{
+    //TODO
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLFuncs_InitBaseFuncs");
+
+
+    return JNI_TRUE;
+}
+
+jboolean
+MTLFuncs_InitExtFuncs()
+{
+    //TODO
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLFuncs_InitExtFuncs");
+
+    return JNI_TRUE;
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGraphicsConfig.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLGraphicsConfig_h_Included
+#define MTLGraphicsConfig_h_Included
+
+#import "jni.h"
+#import "MTLSurfaceDataBase.h"
+#import "MTLContext.h"
+#import <Cocoa/Cocoa.h>
+#import <Metal/Metal.h>
+
+
+@interface MTLGraphicsConfigUtil : NSObject {}
++ (void) _getMTLConfigInfo: (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.
+ */
+
+
+/**
+ * The MTLGraphicsConfigInfo 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.
+ *
+ *     MTLContext *context;
+ * The context associated with this CGLGraphicsConfig.
+ */
+typedef struct _MTLGraphicsConfigInfo {
+    jint                screen;
+    NSOpenGLPixelFormat *pixfmt;
+    MTLContext          *context;
+} MTLGraphicsConfigInfo;
+
+#endif /* MTLGraphicsConfig_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGraphicsConfig.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+#import "sun_java2d_metal_MTLGraphicsConfig.h"
+
+#import "MTLGraphicsConfig.h"
+#import "MTLSurfaceData.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 GL pipeline ---"
+
+/**
+ * Disposes all memory and resources associated with the given
+ * CGLGraphicsConfigInfo (including its native MTLContext data).
+ */
+void
+MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "MTLGC_DestroyMTLGraphicsConfig");
+
+    MTLGraphicsConfigInfo *mtlinfo =
+        (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+    if (mtlinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+                      "MTLGC_DestroyMTLGraphicsConfig: info is null");
+        return;
+    }
+
+    MTLContext *mtlc = (MTLContext*)mtlinfo->context;
+    if (mtlc != NULL) {
+        [mtlinfo->context release];
+        mtlinfo->context = nil;
+    }
+    free(mtlinfo);
+}
+
+#pragma mark -
+#pragma mark "--- MTLGraphicsConfig methods ---"
+
+
+/**
+ * Attempts to initialize CGL and the core OpenGL library.
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_metal_MTLGraphicsConfig_initMTL
+    (JNIEnv *env, jclass cglgc)
+{
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_initMTL");
+
+    if (!MTLFuncs_OpenLibrary()) {
+        return JNI_FALSE;
+    }
+
+    if (!MTLFuncs_InitPlatformFuncs() ||
+        !MTLFuncs_InitBaseFuncs() ||
+        !MTLFuncs_InitExtFuncs())
+    {
+        MTLFuncs_CloseLibrary();
+        return JNI_FALSE;
+    }
+
+    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_MTLGraphicsConfig_getMTLConfigInfo
+    (JNIEnv *env, jclass cglgc, jint displayID, jstring mtlShadersLib)
+{
+  jlong ret = 0L;
+  JNF_COCOA_ENTER(env);
+  NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3];
+  [retArray addObject: [NSNumber numberWithInt: (int)displayID]];
+  [retArray addObject: [NSString stringWithUTF8String: JNU_GetStringPlatformChars(env, mtlShadersLib, 0)]];
+  if ([NSThread isMainThread]) {
+      [MTLGraphicsConfigUtil _getMTLConfigInfo: retArray];
+  } else {
+      [MTLGraphicsConfigUtil performSelectorOnMainThread: @selector(_getMTLConfigInfo:) withObject: retArray waitUntilDone: YES];
+  }
+  NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0];
+  ret = (jlong)[num longValue];
+  JNF_COCOA_EXIT(env);
+  return ret;
+}
+
+
+
+
+@implementation MTLGraphicsConfigUtil
++ (void) _getMTLConfigInfo: (NSMutableArray *)argValue {
+    AWT_ASSERT_APPKIT_THREAD;
+
+    jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
+    NSString *mtlShadersLib = (NSString *)[argValue objectAtIndex: 1];
+    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
+    [argValue removeAllObjects];
+
+    J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_getMTLConfigInfo");
+
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+
+    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, "MTLGraphicsConfig_getMTLConfigInfo: NSWindow is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+    NSView *scratchSurface =
+        [[NSView alloc]
+            initWithFrame: contentRect];
+    if (scratchSurface == nil) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: NSView is NULL");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    [window setContentView: scratchSurface];
+
+    MTLContext *mtlc = [[MTLContext alloc] initWithDevice:CGDirectDisplayCopyCurrentMetalDevice(displayID)
+                        shadersLib:mtlShadersLib];
+    if (mtlc == 0L) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGC_InitMTLContext: could not allocate memory for mtlc");
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+
+
+    // create the MTLGraphicsConfigInfo record for this config
+    MTLGraphicsConfigInfo *mtlinfo = (MTLGraphicsConfigInfo *)malloc(sizeof(MTLGraphicsConfigInfo));
+    if (mtlinfo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: could not allocate memory for mtlinfo");
+        free(mtlc);
+        [argValue addObject: [NSNumber numberWithLong: 0L]];
+        return;
+    }
+    memset(mtlinfo, 0, sizeof(MTLGraphicsConfigInfo));
+    mtlinfo->screen = displayID;
+    mtlinfo->context = mtlc;
+
+    [argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(mtlinfo)]];
+    [pool drain];
+}
+@end //GraphicsConfigUtil
+
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_metal_MTLGraphicsConfig_nativeGetMaxTextureSize
+    (JNIEnv *env, jclass mtlgc)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_nativeGetMaxTextureSize");
+
+    __block int max = 0;
+
+//    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+//    }];
+
+    return (jint)max;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLLayer_h_Included
+#define MTLLayer_h_Included
+#import <Metal/Metal.h>
+#import <QuartzCore/CAMetalLayer.h>
+#import "common.h"
+
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+
+@interface MTLLayer : CAMetalLayer
+{
+@private
+    JNFWeakJObjectWrapper *javaLayer;
+
+    // intermediate buffer, used the RQ lock to synchronize
+    MTLContext* ctx;
+    float bufferWidth;
+    float bufferHeight;
+    id<MTLTexture> buffer;
+}
+
+@property (nonatomic, retain) JNFWeakJObjectWrapper *javaLayer;
+@property (readwrite, assign) MTLContext* ctx;
+@property (readwrite, assign) float bufferWidth;
+@property (readwrite, assign) float bufferHeight;
+@property (readwrite, assign) id<MTLTexture> buffer;
+
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer;
+
+- (void) blitTexture:(id<MTLCommandBuffer>)commandBuf;
+- (void) fillParallelogramCtxX:(jfloat)x
+                             Y:(jfloat)y
+                           DX1:(jfloat)dx1
+                           DY1:(jfloat)dy1
+                           DX2:(jfloat)dx2
+                           DY2:(jfloat)dy2;
+@end
+
+#endif /* CGLLayer_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+#import "MTLGraphicsConfig.h"
+#import "MTLLayer.h"
+#import "ThreadUtilities.h"
+#import "LWCToolkit.h"
+#import "MTLSurfaceData.h"
+
+#import "MTLBlitLoops.h"
+
+@implementation MTLLayer
+
+
+@synthesize javaLayer;
+@synthesize ctx;
+@synthesize bufferWidth;
+@synthesize bufferHeight;
+@synthesize buffer;
+
+- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer
+{
+    AWT_ASSERT_APPKIT_THREAD;
+    // Initialize ourselves
+    self = [super init];
+    if (self == nil) return self;
+
+    self.javaLayer = layer;
+
+    self.contentsGravity = kCAGravityTopLeft;
+
+    //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];
+
+
+    return self;
+}
+
+- (void) blitTexture:(id<MTLCommandBuffer>)commandBuf {
+    if (self.ctx == NULL || self.javaLayer == NULL || self.buffer == nil || ctx.device == nil) {
+        J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, devide=%p)", self.ctx, self.javaLayer, self.buffer, ctx.device);
+        return;
+    }
+
+    if (commandBuf == nil) {
+        J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nothing to do (commandBuf is null)");
+        return;
+    }
+
+    @autoreleasepool {
+        self.device = ctx.device;
+        self.pixelFormat = MTLPixelFormatBGRA8Unorm;
+        self.framebufferOnly = NO;
+
+        self.drawableSize =
+            CGSizeMake(self.buffer.width,
+                       self.buffer.height);
+
+        id<CAMetalDrawable> mtlDrawable = [self nextDrawable];
+        if (mtlDrawable == nil) {
+            return;
+        }
+        J2dTraceLn6(J2D_TRACE_INFO, "MTLLayer.blitTexture: src tex=%p (w=%d, h=%d), dst tex=%p (w=%d, h=%d)", self.buffer, self.buffer.width, self.buffer.height, mtlDrawable.texture, mtlDrawable.texture.width, mtlDrawable.texture.height);
+        id <MTLBlitCommandEncoder> blitEncoder = [commandBuf blitCommandEncoder];
+        [blitEncoder
+                copyFromTexture:self.buffer sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(0, 0, 0) sourceSize:MTLSizeMake(self.buffer.width, self.buffer.height, 1)
+                toTexture:mtlDrawable.texture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)];
+        [blitEncoder endEncoding];
+
+        [commandBuf presentDrawable:mtlDrawable];
+
+        [commandBuf addCompletedHandler:^(id <MTLCommandBuffer> cmdBuff) {
+                [cmdBuff release];
+                [ctx.texturePool markAllTexturesFree];
+        }];
+
+        [commandBuf commit];
+    }
+}
+
+- (void) dealloc {
+    self.javaLayer = nil;
+    [super dealloc];
+}
+
+@end
+
+/*
+ * Class:     sun_java2d_metal_CGLLayer
+ * Method:    nativeCreateLayer
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_metal_MTLLayer_nativeCreateLayer
+(JNIEnv *env, jobject obj)
+{
+    __block MTLLayer *layer = nil;
+
+JNF_COCOA_ENTER(env);
+
+    JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env];
+
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+            AWT_ASSERT_APPKIT_THREAD;
+        
+            layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer];
+    }];
+    
+JNF_COCOA_EXIT(env);
+
+    return ptr_to_jlong(layer);
+}
+
+// Must be called under the RQ lock.
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLLayer_validate
+(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)
+{
+    MTLLayer *layer = OBJC(layerPtr);
+
+    if (surfaceData != NULL) {
+        BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData);
+        layer.bufferWidth = bmtlsdo->width;
+        layer.bufferHeight = bmtlsdo->width;
+        layer.buffer = bmtlsdo->pTexture;
+        layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context;
+        layer.device = layer.ctx.device;
+    } else {
+        layer.ctx = NULL;
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLLayer_nativeSetScale
+(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)
+{
+    JNF_COCOA_ENTER(env);
+    MTLLayer *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/MTLMaskBlit.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLMaskBlit_h_Included
+#define MTLMaskBlit_h_Included
+
+#include "MTLContext.h"
+
+void MTLMaskBlit_MaskBlit(JNIEnv *env, MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint dstx, jint dsty,
+                          jint width, jint height,
+                          void *pPixels);
+
+#endif /* MTLMaskBlit_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskBlit.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+#include <jlong.h>
+
+#include "MTLMaskBlit.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceDataBase.h"
+
+/**
+ * REMIND: This method assumes that the dimensions of the incoming pixel
+ *         array are less than or equal to the cached blit texture tile;
+ *         these are rather fragile assumptions, and should be cleaned up...
+ */
+void
+MTLMaskBlit_MaskBlit(JNIEnv *env, MTLContext *mtlc, BMTLSDOps * dstOps,
+                     jint dstx, jint dsty,
+                     jint width, jint height,
+                     void *pPixels)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLMaskBlit_MaskBlit");
+
+    if (width <= 0 || height <= 0) {
+        J2dTraceLn(J2D_TRACE_WARNING,
+                   "MTLMaskBlit_MaskBlit: invalid dimensions");
+        return;
+    }
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLMaskFill_h_Included
+#define MTLMaskFill_h_Included
+
+#include "MTLContext.h"
+
+void MTLMaskFill_MaskFill(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint x, jint y, jint w, jint h,
+                          jint maskoff, jint maskscan, jint masklen,
+                          unsigned char *pMask);
+
+#endif /* MTLMaskFill_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include "sun_java2d_metal_MTLMaskFill.h"
+
+#include "MTLMaskFill.h"
+#include "MTLRenderQueue.h"
+#include "MTLVertexCache.h"
+
+/**
+ * This implementation first copies the alpha tile into a texture and then
+ * maps that texture to the destination surface.  This approach appears to
+ * offer the best performance despite being a two-step process.
+ *
+ * When the source paint is a Color, we can simply use the GL_MODULATE
+ * function to multiply the current color (already premultiplied with the
+ * extra alpha value from the AlphaComposite) with the alpha value from
+ * the mask texture tile.  In picture form, this process looks like:
+ *
+ *                        A     R    G     B
+ *     primary color      Pa    Pr   Pg    Pb    (modulated with...)
+ *     texture unit 0     Ca    Ca   Ca    Ca
+ *     ---------------------------------------
+ *     resulting color    Ra    Rr   Rg    Rb
+ *
+ * where:
+ *     Px = current color (already premultiplied by extra alpha)
+ *     Cx = coverage value from mask tile
+ *     Rx = resulting color/alpha component
+ *
+ * When the source paint is not a Color, it means that we are rendering with
+ * a complex paint (e.g. GradientPaint, TexturePaint).  In this case, we
+ * rely on the GL_ARB_multitexture extension to effectively multiply the
+ * paint fragments (autogenerated on texture unit 1, see the
+ * MTLPaints_Set{Gradient,Texture,etc}Paint() methods for more details)
+ * with the coverage values from the mask texture tile (provided on texture
+ * unit 0), all of which is multiplied with the current color value (which
+ * contains the extra alpha value).  In picture form:
+ *
+ *                        A     R    G     B
+ *     primary color      Ea    Ea   Ea    Ea    (modulated with...)
+ *     texture unit 0     Ca    Ca   Ca    Ca    (modulated with...)
+ *     texture unit 1     Pa    Pr   Pg    Pb
+ *     ---------------------------------------
+ *     resulting color    Ra    Rr   Rg    Rb
+ *
+ * where:
+ *     Ea = extra alpha
+ *     Cx = coverage value from mask tile
+ *     Px = gradient/texture paint color (generated for each fragment)
+ *     Rx = resulting color/alpha component
+ *
+ * Here are some descriptions of the many variables used in this method:
+ *   x,y     - upper left corner of the tile destination
+ *   w,h     - width/height of the mask tile
+ *   x0      - placekeeper for the original destination x location
+ *   tw,th   - width/height of the actual texture tile in pixels
+ *   sx1,sy1 - upper left corner of the mask tile source region
+ *   sx2,sy2 - lower left corner of the mask tile source region
+ *   sx,sy   - "current" upper left corner of the mask tile region of interest
+ */
+void
+MTLMaskFill_MaskFill(MTLContext *mtlc, BMTLSDOps * dstOps,
+                     jint x, jint y, jint w, jint h,
+                     jint maskoff, jint maskscan, jint masklen,
+                     unsigned char *pMask)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLMaskFill_MaskFill");
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLMaskFill_maskFill
+    (JNIEnv *env, jobject self,
+     jint x, jint y, jint w, jint h,
+     jint maskoff, jint maskscan, jint masklen,
+     jbyteArray maskArray)
+{
+    MTLContext *mtlc = MTLRenderQueue_GetCurrentContext();
+    unsigned char *mask;
+    //TODO
+    J2dTraceLn(J2D_TRACE_ERROR, "MTLMaskFill_maskFill");
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+/*
+ */
+
+#ifndef MTLPaints_h_Included
+#define MTLPaints_h_Included
+
+#include "MTLContext.h"
+
+void MTLPaints_ResetPaint(MTLContext *mtlc);
+
+void MTLPaints_SetColor(MTLContext *mtlc, jint pixel);
+
+
+void MTLPaints_SetLinearGradientPaint(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                      jboolean useMask, jboolean linear,
+                                      jint cycleMethod, jint numStops,
+                                      jfloat p0, jfloat p1, jfloat p3,
+                                      void *fractions, void *pixels);
+
+void MTLPaints_SetRadialGradientPaint(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                      jboolean useMask, jboolean linear,
+                                      jint cycleMethod, jint numStops,
+                                      jfloat m00, jfloat m01, jfloat m02,
+                                      jfloat m10, jfloat m11, jfloat m12,
+                                      jfloat focusX,
+                                      void *fractions, void *pixels);
+
+void MTLPaints_SetTexturePaint(MTLContext *mtlc,
+                               jboolean useMask,
+                               jlong pSrcOps, jboolean filter,
+                               jdouble xp0, jdouble xp1, jdouble xp3,
+                               jdouble yp0, jdouble yp1, jdouble yp3);
+
+#endif /* MTLPaints_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,453 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <jlong.h>
+#include <string.h>
+
+#include "sun_java2d_SunGraphics2D.h"
+#include "sun_java2d_pipe_BufferedPaints.h"
+
+#include "MTLPaints.h"
+#include "MTLContext.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceData.h"
+
+void
+MTLPaints_ResetPaint(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLPaints_ResetPaint");
+}
+
+void
+MTLPaints_SetColor(MTLContext *mtlc, jint pixel)
+{
+    mtlc.compState = sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR;
+    //TODO
+    [mtlc setColorInt:pixel];
+}
+
+/************************* GradientPaint support ****************************/
+
+static GLuint gradientTexID = 0;
+
+static void
+MTLPaints_InitGradientTexture()
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLPaints_InitGradientTexture");
+}
+
+
+/************************** TexturePaint support ****************************/
+
+void
+MTLPaints_SetTexturePaint(MTLContext *mtlc,
+                          jboolean useMask,
+                          jlong pSrcOps, jboolean filter,
+                          jdouble xp0, jdouble xp1, jdouble xp3,
+                          jdouble yp0, jdouble yp1, jdouble yp3)
+{
+    //TODO
+}
+
+/****************** Shared MultipleGradientPaint support ********************/
+
+/**
+ * These constants are identical to those defined in the
+ * MultipleGradientPaint.CycleMethod enum; they are copied here for
+ * convenience (ideally we would pull them directly from the Java level,
+ * but that entails more hassle than it is worth).
+ */
+#define CYCLE_NONE    0
+#define CYCLE_REFLECT 1
+#define CYCLE_REPEAT  2
+
+/**
+ * The following constants are flags that can be bitwise-or'ed together
+ * to control how the MultipleGradientPaint shader source code is generated:
+ *
+ *   MULTI_CYCLE_METHOD
+ *     Placeholder for the CycleMethod enum constant.
+ *
+ *   MULTI_LARGE
+ *     If set, use the (slower) shader that supports a larger number of
+ *     gradient colors; otherwise, use the optimized codepath.  See
+ *     the MAX_FRACTIONS_SMALL/LARGE constants below for more details.
+ *
+ *   MULTI_USE_MASK
+ *     If set, apply the alpha mask value from texture unit 0 to the
+ *     final color result (only used in the MaskFill case).
+ *
+ *   MULTI_LINEAR_RGB
+ *     If set, convert the linear RGB result back into the sRGB color space.
+ */
+#define MULTI_CYCLE_METHOD (3 << 0)
+#define MULTI_LARGE        (1 << 2)
+#define MULTI_USE_MASK     (1 << 3)
+#define MULTI_LINEAR_RGB   (1 << 4)
+
+/**
+ * This value determines the size of the array of programs for each
+ * MultipleGradientPaint type.  This value reflects the maximum value that
+ * can be represented by performing a bitwise-or of all the MULTI_*
+ * constants defined above.
+ */
+#define MAX_PROGRAMS 32
+
+/** Evaluates to true if the given bit is set on the local flags variable. */
+#define IS_SET(flagbit) \
+    (((flags) & (flagbit)) != 0)
+
+/** Composes the given parameters as flags into the given flags variable.*/
+#define COMPOSE_FLAGS(flags, cycleMethod, large, useMask, linear) \
+    do {                                                   \
+        flags |= ((cycleMethod) & MULTI_CYCLE_METHOD);     \
+        if (large)   flags |= MULTI_LARGE;                 \
+        if (useMask) flags |= MULTI_USE_MASK;              \
+        if (linear)  flags |= MULTI_LINEAR_RGB;            \
+    } while (0)
+
+/** Extracts the CycleMethod enum value from the given flags variable. */
+#define EXTRACT_CYCLE_METHOD(flags) \
+    ((flags) & MULTI_CYCLE_METHOD)
+
+/**
+ * The maximum number of gradient "stops" supported by the fragment shader
+ * and related code.  When the MULTI_LARGE flag is set, we will use
+ * MAX_FRACTIONS_LARGE; otherwise, we use MAX_FRACTIONS_SMALL.  By having
+ * two separate values, we can have one highly optimized shader (SMALL) that
+ * supports only a few fractions/colors, and then another, less optimal
+ * shader that supports more stops.
+ */
+#define MAX_FRACTIONS sun_java2d_pipe_BufferedPaints_MULTI_MAX_FRACTIONS
+#define MAX_FRACTIONS_LARGE MAX_FRACTIONS
+#define MAX_FRACTIONS_SMALL 4
+
+/**
+ * The maximum number of gradient colors supported by all of the gradient
+ * fragment shaders.  Note that this value must be a power of two, as it
+ * determines the size of the 1D texture created below.  It also must be
+ * greater than or equal to MAX_FRACTIONS (there is no strict requirement
+ * that the two values be equal).
+ */
+#define MAX_COLORS 16
+
+/**
+ * The handle to the gradient color table texture object used by the shaders.
+ */
+static jint multiGradientTexID = 0;
+
+/**
+ * This is essentially a template of the shader source code that can be used
+ * for either LinearGradientPaint or RadialGradientPaint.  It includes the
+ * structure and some variables that are common to each; the remaining
+ * code snippets (for CycleMethod, ColorSpaceType, and mask modulation)
+ * are filled in prior to compiling the shader at runtime depending on the
+ * paint parameters.  See MTLPaints_CreateMultiGradProgram() for more details.
+ */
+static const char *multiGradientShaderSource =
+    // gradient texture size (in texels)
+    "const int TEXTURE_SIZE = %d;"
+    // maximum number of fractions/colors supported by this shader
+    "const int MAX_FRACTIONS = %d;"
+    // size of a single texel
+    "const float FULL_TEXEL = (1.0 / float(TEXTURE_SIZE));"
+    // size of half of a single texel
+    "const float HALF_TEXEL = (FULL_TEXEL / 2.0);"
+    // texture containing the gradient colors
+    "uniform sampler1D colors;"
+    // array of gradient stops/fractions
+    "uniform float fractions[MAX_FRACTIONS];"
+    // array of scale factors (one for each interval)
+    "uniform float scaleFactors[MAX_FRACTIONS-1];"
+    // (placeholder for mask variable)
+    "%s"
+    // (placeholder for Linear/RadialGP-specific variables)
+    "%s"
+    ""
+    "void main(void)"
+    "{"
+    "    float dist;"
+         // (placeholder for Linear/RadialGradientPaint-specific code)
+    "    %s"
+    ""
+    "    float tc;"
+         // (placeholder for CycleMethod-specific code)
+    "    %s"
+    ""
+         // calculate interpolated color
+    "    vec4 result = texture1D(colors, tc);"
+    ""
+         // (placeholder for ColorSpace conversion code)
+    "    %s"
+    ""
+         // (placeholder for mask modulation code)
+    "    %s"
+    ""
+         // modulate with gl_Color in order to apply extra alpha
+    "    gl_FragColor = result * gl_Color;"
+    "}";
+
+/**
+ * This code takes a "dist" value as input (as calculated earlier by the
+ * LGP/RGP-specific code) in the range [0,1] and produces a texture
+ * coordinate value "tc" that represents the position of the chosen color
+ * in the one-dimensional gradient texture (also in the range [0,1]).
+ *
+ * One naive way to implement this would be to iterate through the fractions
+ * to figure out in which interval "dist" falls, and then compute the
+ * relative distance between the two nearest stops.  This approach would
+ * require an "if" check on every iteration, and it is best to avoid
+ * conditionals in fragment shaders for performance reasons.  Also, one might
+ * be tempted to use a break statement to jump out of the loop once the
+ * interval was found, but break statements (and non-constant loop bounds)
+ * are not natively available on most graphics hardware today, so that is
+ * a non-starter.
+ *
+ * The more optimal approach used here avoids these issues entirely by using
+ * an accumulation function that is equivalent to the process described above.
+ * The scaleFactors array is pre-initialized at enable time as follows:
+ *     scaleFactors[i] = 1.0 / (fractions[i+1] - fractions[i]);
+ *
+ * For each iteration, we subtract fractions[i] from dist and then multiply
+ * that value by scaleFactors[i].  If we are within the target interval,
+ * this value will be a fraction in the range [0,1] indicating the relative
+ * distance between fraction[i] and fraction[i+1].  If we are below the
+ * target interval, this value will be negative, so we clamp it to zero
+ * to avoid accumulating any value.  If we are above the target interval,
+ * the value will be greater than one, so we clamp it to one.  Upon exiting
+ * the loop, we will have accumulated zero or more 1.0's and a single
+ * fractional value.  This accumulated value tells us the position of the
+ * fragment color in the one-dimensional gradient texture, i.e., the
+ * texcoord called "tc".
+ */
+static const char *texCoordCalcCode =
+    "int i;"
+    "float relFraction = 0.0;"
+    "for (i = 0; i < MAX_FRACTIONS-1; i++) {"
+    "    relFraction +="
+    "        clamp((dist - fractions[i]) * scaleFactors[i], 0.0, 1.0);"
+    "}"
+    // we offset by half a texel so that we find the linearly interpolated
+    // color between the two texel centers of interest
+    "tc = HALF_TEXEL + (FULL_TEXEL * relFraction);";
+
+/** Code for NO_CYCLE that gets plugged into the CycleMethod placeholder. */
+static const char *noCycleCode =
+    "if (dist <= 0.0) {"
+    "    tc = 0.0;"
+    "} else if (dist >= 1.0) {"
+    "    tc = 1.0;"
+    "} else {"
+         // (placeholder for texcoord calculation)
+    "    %s"
+    "}";
+
+/** Code for REFLECT that gets plugged into the CycleMethod placeholder. */
+static const char *reflectCode =
+    "dist = 1.0 - (abs(fract(dist * 0.5) - 0.5) * 2.0);"
+    // (placeholder for texcoord calculation)
+    "%s";
+
+/** Code for REPEAT that gets plugged into the CycleMethod placeholder. */
+static const char *repeatCode =
+    "dist = fract(dist);"
+    // (placeholder for texcoord calculation)
+    "%s";
+
+static void
+MTLPaints_InitMultiGradientTexture()
+{
+    //TODO
+}
+
+/**
+ * Compiles and links the MultipleGradientPaint shader program.  If
+ * successful, this function returns a handle to the newly created
+ * shader program; otherwise returns 0.
+ */
+static GLhandleARB
+MTLPaints_CreateMultiGradProgram(jint flags,
+                                 char *paintVars, char *distCode)
+{
+
+    //TODO
+    return NULL;
+}
+
+/**
+ * Called from the MTLPaints_SetLinear/RadialGradientPaint() methods
+ * in order to setup the fraction/color values that are common to both.
+ */
+static void
+MTLPaints_SetMultiGradientPaint(GLhandleARB multiGradProgram,
+                                jint numStops,
+                                void *pFractions, void *pPixels)
+{
+    //TODO
+
+}
+
+/********************** LinearGradientPaint support *************************/
+
+/**
+ * The handles to the LinearGradientPaint fragment program objects.  The
+ * index to the array should be a bitwise-or'ing of the MULTI_* flags defined
+ * above.  Note that most applications will likely need to initialize one
+ * or two of these elements, so the array is usually sparsely populated.
+ */
+static GLhandleARB linearGradPrograms[MAX_PROGRAMS];
+
+/**
+ * Compiles and links the LinearGradientPaint shader program.  If successful,
+ * this function returns a handle to the newly created shader program;
+ * otherwise returns 0.
+ */
+static GLhandleARB
+MTLPaints_CreateLinearGradProgram(jint flags)
+{
+    char *paintVars;
+    char *distCode;
+
+    J2dTraceLn1(J2D_TRACE_INFO,
+                "MTLPaints_CreateLinearGradProgram",
+                flags);
+
+    /*
+     * To simplify the code and to make it easier to upload a number of
+     * uniform values at once, we pack a bunch of scalar (float) values
+     * into vec3 values below.  Here's how the values are related:
+     *
+     *   params.x = p0
+     *   params.y = p1
+     *   params.z = p3
+     *
+     *   yoff = dstOps->yOffset + dstOps->height
+     */
+    paintVars =
+        "uniform vec3 params;"
+        "uniform float yoff;";
+    distCode =
+        // note that gl_FragCoord is in window space relative to the
+        // lower-left corner, so we have to flip the y-coordinate here
+        "vec3 fragCoord = vec3(gl_FragCoord.x, yoff-gl_FragCoord.y, 1.0);"
+        "dist = dot(params, fragCoord);";
+
+    return MTLPaints_CreateMultiGradProgram(flags, paintVars, distCode);
+}
+
+void
+MTLPaints_SetLinearGradientPaint(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                 jboolean useMask, jboolean linear,
+                                 jint cycleMethod, jint numStops,
+                                 jfloat p0, jfloat p1, jfloat p3,
+                                 void *fractions, void *pixels)
+{
+    //TODO
+}
+
+/********************** RadialGradientPaint support *************************/
+
+/**
+ * The handles to the RadialGradientPaint fragment program objects.  The
+ * index to the array should be a bitwise-or'ing of the MULTI_* flags defined
+ * above.  Note that most applications will likely need to initialize one
+ * or two of these elements, so the array is usually sparsely populated.
+ */
+static GLhandleARB radialGradPrograms[MAX_PROGRAMS];
+
+/**
+ * Compiles and links the RadialGradientPaint shader program.  If successful,
+ * this function returns a handle to the newly created shader program;
+ * otherwise returns 0.
+ */
+static GLhandleARB
+MTLPaints_CreateRadialGradProgram(jint flags)
+{
+    char *paintVars;
+    char *distCode;
+
+    J2dTraceLn1(J2D_TRACE_INFO,
+                "MTLPaints_CreateRadialGradProgram",
+                flags);
+
+    /*
+     * To simplify the code and to make it easier to upload a number of
+     * uniform values at once, we pack a bunch of scalar (float) values
+     * into vec3 and vec4 values below.  Here's how the values are related:
+     *
+     *   m0.x = m00
+     *   m0.y = m01
+     *   m0.z = m02
+     *
+     *   m1.x = m10
+     *   m1.y = m11
+     *   m1.z = m12
+     *
+     *   precalc.x = focusX
+     *   precalc.y = yoff = dstOps->yOffset + dstOps->height
+     *   precalc.z = 1.0 - (focusX * focusX)
+     *   precalc.w = 1.0 / precalc.z
+     */
+    paintVars =
+        "uniform vec3 m0;"
+        "uniform vec3 m1;"
+        "uniform vec4 precalc;";
+
+    /*
+     * The following code is derived from Daniel Rice's whitepaper on
+     * radial gradient performance (attached to the bug report for 6521533).
+     * Refer to that document as well as the setup code in the Java-level
+     * BufferedPaints.setRadialGradientPaint() method for more details.
+     */
+    distCode =
+        // note that gl_FragCoord is in window space relative to the
+        // lower-left corner, so we have to flip the y-coordinate here
+        "vec3 fragCoord ="
+        "    vec3(gl_FragCoord.x, precalc.y - gl_FragCoord.y, 1.0);"
+        "float x = dot(fragCoord, m0);"
+        "float y = dot(fragCoord, m1);"
+        "float xfx = x - precalc.x;"
+        "dist = (precalc.x*xfx + sqrt(xfx*xfx + y*y*precalc.z))*precalc.w;";
+
+    return MTLPaints_CreateMultiGradProgram(flags, paintVars, distCode);
+}
+
+void
+MTLPaints_SetRadialGradientPaint(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                 jboolean useMask, jboolean linear,
+                                 jint cycleMethod, jint numStops,
+                                 jfloat m00, jfloat m01, jfloat m02,
+                                 jfloat m10, jfloat m11, jfloat m12,
+                                 jfloat focusX,
+                                 void *fractions, void *pixels)
+{
+    //TODO
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,31 @@
+#ifndef MTLPipelineStatesStorage_h_Included
+#define MTLPipelineStatesStorage_h_Included
+
+#import <Metal/Metal.h>
+
+@interface MTLPipelineStatesStorage : NSObject {
+@private
+
+id<MTLDevice>       device;
+id<MTLLibrary>      library;
+NSMutableDictionary<NSString*, id<MTLFunction>> * shaders;
+NSMutableDictionary<NSString*, id<MTLRenderPipelineState>> * states;
+MTLRenderPipelineDescriptor * templateRenderPipelineDesc;
+MTLRenderPipelineDescriptor * templateTexturePipelineDesc;
+}
+
+@property (readwrite, assign) id<MTLDevice> device;
+@property (readwrite, retain) id<MTLLibrary> library;
+@property (readwrite, retain) NSMutableDictionary<NSString*, id<MTLFunction>> * shaders;
+@property (readwrite, retain) NSMutableDictionary<NSString*, id<MTLRenderPipelineState>> * states;
+@property (readwrite, retain) MTLRenderPipelineDescriptor * templateRenderPipelineDesc;
+@property (readwrite, retain) MTLRenderPipelineDescriptor * templateTexturePipelineDesc;
+
+- (id) initWithDevice:(id<MTLDevice>)device shaderLibPath:(NSString *)shadersLib;
+- (id<MTLRenderPipelineState>) getRenderPipelineState:(bool)isGradient;
+- (id<MTLRenderPipelineState>) getTexturePipelineState:(bool)isSourcePremultiplied compositeRule:(int)compositeRule;
+- (id<MTLFunction>) getShader:(NSString *)name;
+@end
+
+
+#endif // MTLPipelineStatesStorage_h_Included
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,147 @@
+#import "MTLPipelineStatesStorage.h"
+#import "Trace.h"
+
+#include "GraphicsPrimitiveMgr.h"
+#import "common.h"
+
+@implementation MTLPipelineStatesStorage
+
+@synthesize device;
+@synthesize library;
+@synthesize shaders;
+@synthesize states;
+@synthesize templateRenderPipelineDesc;
+@synthesize templateTexturePipelineDesc;
+
+- (id) initWithDevice:(id<MTLDevice>)dev shaderLibPath:(NSString *)shadersLib {
+    self = [super init];
+    if (self == nil) return self;
+
+    self.device = dev;
+
+    NSError *error = nil;
+    self.library = [dev newLibraryWithFile:shadersLib error:&error];
+    if (!self.library) {
+        NSLog(@"Failed to load library. error %@", error);
+        exit(0);
+    }
+    self.shaders = [NSMutableDictionary dictionaryWithCapacity:10];
+    self.states = [NSMutableDictionary dictionaryWithCapacity:10];
+
+    { // init template descriptors
+        MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease];
+        vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat3;
+        vertDesc.attributes[VertexAttributePosition].offset = 0;
+        vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;
+        vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex);
+        vertDesc.layouts[MeshVertexBuffer].stepRate = 1;
+        vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
+
+        self.templateRenderPipelineDesc = [[MTLRenderPipelineDescriptor new] autorelease];
+        self.templateRenderPipelineDesc.sampleCount = 1;
+        self.templateRenderPipelineDesc.vertexDescriptor = vertDesc;
+        self.templateRenderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
+        self.templateRenderPipelineDesc.label = @"template_render";
+
+        self.templateTexturePipelineDesc = [[self.templateRenderPipelineDesc copy] autorelease];
+        self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;
+        self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 3*sizeof(float);
+        self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;
+        self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex);
+        self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1;
+        self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
+        self.templateTexturePipelineDesc.label = @"template_texture";
+    }
+
+    { // pre-create main states
+        [self getRenderPipelineState:YES];
+        [self getRenderPipelineState:NO];
+        [self getTexturePipelineState:NO compositeRule:RULE_Src];
+        [self getTexturePipelineState:NO compositeRule:RULE_SrcOver];
+    }
+
+    return self;
+}
+
+- (id<MTLRenderPipelineState>) getRenderPipelineState:(bool)isGradient {
+    NSString * uid = [NSString stringWithFormat:@"render_grad[%d]", isGradient];
+
+    id<MTLRenderPipelineState> result = [self.states valueForKey:uid];
+    if (result == nil) {
+        id<MTLFunction> vertexShader   = isGradient ? [self getShader:@"vert_grad"] : [self getShader:@"vert_col"];
+        id<MTLFunction> fragmentShader = isGradient ? [self getShader:@"frag_grad"] : [self getShader:@"frag_col"];
+        MTLRenderPipelineDescriptor *pipelineDesc = [[self.templateRenderPipelineDesc copy] autorelease];
+        pipelineDesc.vertexFunction = vertexShader;
+        pipelineDesc.fragmentFunction = fragmentShader;
+        pipelineDesc.label = uid;
+
+        NSError *error = nil;
+        result = [self.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error];
+        if (result == nil) {
+            NSLog(@"Failed to create render pipeline state '%@', error %@", uid, error);
+            exit(0);
+        }
+
+        [self.states setValue:result forKey:uid];
+    }
+
+    return result;
+};
+
+- (id<MTLRenderPipelineState>) getTexturePipelineState:(bool)isSourcePremultiplied compositeRule:(int)compositeRule {
+    NSString * uid = [NSString stringWithFormat:@"texture_compositeRule[%d]", compositeRule];
+
+    id<MTLRenderPipelineState> result = [self.states valueForKey:uid];
+    if (result == nil) {
+        id<MTLFunction> vertexShader   = [self getShader:@"vert_txt"];
+        id<MTLFunction> fragmentShader = [self getShader:@"frag_txt"];
+        MTLRenderPipelineDescriptor *pipelineDesc = [[self.templateTexturePipelineDesc copy] autorelease];
+        pipelineDesc.vertexFunction = vertexShader;
+        pipelineDesc.fragmentFunction = fragmentShader;
+
+        if (compositeRule != RULE_Src) {
+            pipelineDesc.colorAttachments[0].blendingEnabled = YES;
+
+            if (!isSourcePremultiplied)
+                pipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
+
+            //RGB = Source.rgb * SBF + Dest.rgb * DBF
+            //A = Source.a * SBF + Dest.a * DBF
+            //
+            //default SRC:
+            //DBF=0
+            //SBF=1
+            if (compositeRule == RULE_SrcOver) {
+                // SRC_OVER (Porter-Duff Source Over Destination rule):
+                // Ar = As + Ad*(1-As)
+                // Cr = Cs + Cd*(1-As)
+                pipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+                pipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+            } else {
+                J2dTrace1(J2D_TRACE_ERROR, "Unimplemented composite rule %d (will be used Src)", compositeRule);
+                pipelineDesc.colorAttachments[0].blendingEnabled = NO;
+            }
+        }
+
+        NSError *error = nil;
+        result = [self.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error];
+        if (result == nil) {
+            NSLog(@"Failed to create texture pipeline state '%@', error %@", uid, error);
+            exit(0);
+        }
+
+        [self.states setValue:result forKey:uid];
+    }
+
+    return result;
+}
+
+- (id<MTLFunction>) getShader:(NSString *)name {
+    id<MTLFunction> result = [self.shaders valueForKey:name];
+    if (result == nil) {
+        result = [[self.library newFunctionWithName:name] autorelease];
+        [self.shaders setValue:result forKey:name];
+    }
+    return result;
+}
+@end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLRenderQueue_h_Included
+#define MTLRenderQueue_h_Included
+
+#include "MTLContext.h"
+#include "MTLSurfaceData.h"
+
+/*
+ * 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)
+
+/*
+ * Parameter used by the RESET_PREVIOUS_OP() convenience macro, which
+ * indicates that any "open" state (such as an unmatched glBegin() or
+ * glEnable(GL_TEXTURE_2D)) should be completed before the following operation
+ * is performed.  SET_SURFACES is an example of an operation that needs to
+ * call RESET_PREVIOUS_OP() before completing the surface change operation.
+ */
+#define MTL_STATE_RESET  -1
+
+/*
+ * Parameter passed to the CHECK_PREVIOUS_OP() macro to indicate that the
+ * following operation represents a "simple" state change.  A simple state
+ * change is one that is allowed to occur within a series of texturing
+ * operations; in other words, this type of state change can occur without
+ * first calling glDisable(GL_TEXTURE_2D).  An example of such an operation
+ * is SET_RECT_CLIP.
+ */
+#define MTL_STATE_CHANGE -2
+
+/*
+ * Parameter passed to the CHECK_PREVIOUS_OP() macro to indicate that the
+ * following operation represents an operation that uses an alpha mask,
+ * such as MTLMaskFill and MTLTR_DrawGrayscaleGlyphNoCache().
+ */
+#define MTL_STATE_MASK_OP -3
+
+/*
+ * Parameter passed to the CHECK_PREVIOUS_OP() macro to indicate that the
+ * following operation represents an operation that uses the glyph cache,
+ * such as MTLTR_DrawGrayscaleGlyphViaCache().
+ */
+#define MTL_STATE_GLYPH_OP -4
+
+/*
+ * Parameter passed to the CHECK_PREVIOUS_OP() macro to indicate that the
+ * following operation represents an operation that renders a
+ * parallelogram via a fragment program (see MTLRenderer).
+ */
+#define MTL_STATE_PGRAM_OP -5
+
+/*
+ * Initializes the "previous operation" state to its default value.
+ */
+#define INIT_PREVIOUS_OP() previousOp = MTL_STATE_RESET
+
+/*
+ * These macros now simply delegate to the CheckPreviousOp() method.
+ */
+#define CHECK_PREVIOUS_OP(op) MTLRenderQueue_CheckPreviousOp(op)
+#define RESET_PREVIOUS_OP() CHECK_PREVIOUS_OP(MTL_STATE_RESET)
+
+/*
+ * The following macros allow the caller to return (or continue) if the
+ * provided value is NULL.  (The strange else clause is included below to
+ * allow for a trailing ';' after RETURN/CONTINUE_IF_NULL() invocations.)
+ */
+#define ACT_IF_NULL(ACTION, value)         \
+    if ((value) == NULL) {                 \
+        J2dTraceLn1(J2D_TRACE_ERROR,       \
+                    "%s is null", #value); \
+        ACTION;                            \
+    } else do { } while (0)
+#define RETURN_IF_NULL(value)   ACT_IF_NULL(return, value)
+#define CONTINUE_IF_NULL(value) ACT_IF_NULL(continue, value)
+
+/*
+ * Exports.
+ */
+extern jint previousOp;
+
+MTLContext *MTLRenderQueue_GetCurrentContext();
+BMTLSDOps *MTLRenderQueue_GetCurrentDestination();
+void MTLRenderQueue_CheckPreviousOp(jint op);
+void MTLTR_DisableGlyphModeState();
+
+#endif /* MTLRenderQueue_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,831 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+
+#include "sun_java2d_pipe_BufferedOpCodes.h"
+
+#include "jlong.h"
+#include "MTLBlitLoops.h"
+#include "MTLBufImgOps.h"
+#include "MTLMaskBlit.h"
+#include "MTLMaskFill.h"
+#include "MTLPaints.h"
+#include "MTLRenderQueue.h"
+#include "MTLRenderer.h"
+#include "MTLTextRenderer.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
+ * MTLRenderQueue_CheckPreviousOp() method below for more information.
+ */
+jint previousOp;
+
+/**
+ * References to the "current" context and destination surface.
+ */
+static MTLContext *mtlc = NULL;
+static BMTLSDOps *dstOps = NULL;
+
+/**
+ * The following methods are implemented in the windowing system (i.e. GLX
+ * and WGL) source files.
+ */
+extern void MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo);
+extern void MTLSD_SwapBuffers(JNIEnv *env, jlong window);
+
+/**
+ * Helper methods to manage modified layers
+ */
+static MTLLayer ** g_modifiedLayers = NULL;
+static int g_modifiedLayersCount = 0;
+static int g_modifiedLayersAllocatedCount = 0;
+
+static void markLayerModified(MTLLayer * modifiedLayer) {
+    if (modifiedLayer == NULL)
+        return;
+    if (g_modifiedLayers == NULL) {
+        g_modifiedLayersAllocatedCount = 3;
+        g_modifiedLayers = malloc(g_modifiedLayersAllocatedCount * sizeof(MTLLayer *));
+    }
+    for (int c = 0; c < g_modifiedLayersCount; ++c) {
+        if (g_modifiedLayers[c] == modifiedLayer)
+            return;
+    }
+    ++g_modifiedLayersCount;
+    if (g_modifiedLayersCount > g_modifiedLayersAllocatedCount) {
+        g_modifiedLayersAllocatedCount = g_modifiedLayersCount;
+        g_modifiedLayers = realloc(g_modifiedLayers, g_modifiedLayersAllocatedCount * sizeof(MTLLayer *));
+    }
+    g_modifiedLayers[g_modifiedLayersCount - 1] = modifiedLayer;
+}
+
+static void scheduleBlitAllModifiedLayers() {
+    for (int c = 0; c < g_modifiedLayersCount; ++c) {
+        MTLLayer * layer = g_modifiedLayers[c];
+        MTLContext * ctx = layer.ctx;
+        if (layer == NULL || ctx == NULL)
+            continue;
+        id<MTLCommandBuffer> bufferToCommit = ctx.commandBuffer;
+        [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+            [layer blitTexture:bufferToCommit];
+        }];
+
+        [ctx releaseCommandBuffer];
+    }
+    g_modifiedLayersCount = 0;
+}
+
+static void onSurfaceModified(BMTLSDOps *bmtldst) {
+    if (bmtldst != NULL && bmtldst->privOps != NULL && ((MTLSDOps *)bmtldst->privOps)->layer != NULL)
+        markLayerModified(((MTLSDOps *) bmtldst->privOps)->layer);
+}
+
+static const jint g_drawOpcodes[] = {
+        sun_java2d_pipe_BufferedOpCodes_DRAW_LINE,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_RECT,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_POLY,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM,
+        sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM,
+
+        sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST,
+
+        sun_java2d_pipe_BufferedOpCodes_FILL_RECT,
+        sun_java2d_pipe_BufferedOpCodes_FILL_SPANS,
+        sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM,
+        sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM,
+
+        sun_java2d_pipe_BufferedOpCodes_COPY_AREA,
+        sun_java2d_pipe_BufferedOpCodes_MASK_FILL,
+        sun_java2d_pipe_BufferedOpCodes_MASK_BLIT,
+        sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS
+};
+
+static jboolean isDrawOpcode(jint opcode) {
+    for (int c = 0; c < sizeof(g_drawOpcodes)/sizeof(g_drawOpcodes[0]); ++c) {
+        if (opcode == g_drawOpcodes[c])
+            return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
+    (JNIEnv *env, jobject mtlrq,
+     jlong buf, jint limit)
+{
+    jboolean sync = JNI_FALSE;
+    unsigned char *b, *end;
+
+    J2dTraceLn1(J2D_TRACE_INFO,
+                "MTLRenderQueue_flushBuffer: limit=%d", limit);
+
+    b = (unsigned char *)jlong_to_ptr(buf);
+    if (b == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+            "MTLRenderQueue_flushBuffer: cannot get direct buffer address");
+        return;
+    }
+
+    INIT_PREVIOUS_OP();
+    end = b + limit;
+
+    while (b < end) {
+        jint opcode = NEXT_INT(b);
+
+        J2dTraceLn2(J2D_TRACE_VERBOSE,
+                    "MTLRenderQueue_flushBuffer: opcode=%d, rem=%d",
+                    opcode, (end-b));
+
+        if (opcode != sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST &&
+            opcode != sun_java2d_pipe_BufferedOpCodes_NOOP)
+        {
+            //MTLTR_DisableGlyphModeState();
+        }
+
+        switch (opcode) {
+
+        // draw ops
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
+            {
+                J2dTraceLn(J2D_TRACE_VERBOSE, "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);
+                MTLRenderer_DrawLine(mtlc, dstOps, 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);
+                MTLRenderer_DrawRect(mtlc, dstOps, 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;
+                MTLRenderer_DrawPoly(mtlc, dstOps, 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);
+                CONTINUE_IF_NULL(mtlc);
+                //TODO
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
+            {
+                jint count = NEXT_INT(b);
+                MTLRenderer_DrawScanlines(mtlc, dstOps, 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);
+
+                MTLRenderer_DrawParallelogram(mtlc, dstOps,
+                                              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);
+
+                MTLRenderer_DrawAAParallelogram(mtlc, 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);
+                MTLRenderer_FillRect(mtlc, dstOps, x, y, w, h);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
+            {
+                jint count = NEXT_INT(b);
+                MTLRenderer_FillSpans(mtlc, dstOps, 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);
+                MTLRenderer_FillParallelogram(mtlc, dstOps,
+                                              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);
+                MTLRenderer_FillAAParallelogram(mtlc, 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;
+                }
+                MTLTR_DrawGlyphList(env, mtlc, 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);
+                MTLBlitLoops_CopyArea(env, mtlc, 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) {
+                    MTLBlitLoops_IsoBlit(env, mtlc, pSrc, pDst,
+                                         xform, hint, texture, rtt,
+                                         sx1, sy1, sx2, sy2,
+                                         dx1, dy1, dx2, dy2);
+                } else {
+                    jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
+                    MTLBlitLoops_Blit(env, mtlc, pSrc, pDst,
+                                      xform, hint, srctype, texture,
+                                      sx1, sy1, sx2, sy2,
+                                      dx1, dy1, dx2, dy2);
+                }
+                onSurfaceModified(jlong_to_ptr(pDst));
+            }
+            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);
+                MTLBlitLoops_SurfaceToSwBlit(env, mtlc,
+                                             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;
+                MTLMaskFill_MaskFill(mtlc, dstOps, 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);
+                MTLMaskBlit_MaskBlit(env, mtlc, dstOps,
+                                     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);
+                [mtlc setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
+            {
+                [mtlc beginShapeClip];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
+            {
+                jint count = NEXT_INT(b);
+                MTLRenderer_FillSpans(mtlc, dstOps, count, (jint *)b);
+                SKIP_BYTES(b, count * BYTES_PER_SPAN);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
+            {
+                //TODO
+                [mtlc endShapeClipDstOps:dstOps];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
+            {
+                [mtlc resetClip];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
+            {
+                jint rule         = NEXT_INT(b);
+                jfloat extraAlpha = NEXT_FLOAT(b);
+                jint flags        = NEXT_INT(b);
+                [mtlc setAlphaCompositeRule:rule extraAlpha:extraAlpha flags:flags];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
+            {
+                jint xorPixel = NEXT_INT(b);
+                [mtlc setXorComposite:xorPixel];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
+            {
+                [mtlc resetComposite];
+            }
+            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);
+                [mtlc setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
+            {
+                [mtlc resetTransform];
+            }
+            break;
+
+        // context-related ops
+        case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
+            {
+
+                jlong pSrc = NEXT_LONG(b);
+                jlong pDst = NEXT_LONG(b);
+                if (mtlc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+
+                dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);
+                [MTLContext setSurfacesEnv:env src:pSrc dst:pDst];
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
+            {
+                jlong pConfigInfo = NEXT_LONG(b);
+                MTLGraphicsConfigInfo *mtlInfo =
+                        (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+
+                if (mtlInfo == NULL) {
+
+                } else {
+                    MTLContext *newMtlc = mtlInfo->context;
+                    if (newMtlc == NULL) {
+
+                    } else {
+                        mtlc = newMtlc;
+                        dstOps = NULL;
+                    }
+                }
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
+            {
+                jlong pData = NEXT_LONG(b);
+                BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
+                if (mtlsdo != NULL) {
+                    CONTINUE_IF_NULL(mtlc);
+                    RESET_PREVIOUS_OP();
+                    MTLSD_Delete(env, mtlsdo);
+                }
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
+            {
+                jlong pData = NEXT_LONG(b);
+                BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
+                if (mtlsdo != NULL) {
+                    CONTINUE_IF_NULL(mtlc);
+                    RESET_PREVIOUS_OP();
+                    MTLSD_Delete(env, mtlsdo);
+                    if (mtlsdo->privOps != NULL) {
+                        free(mtlsdo->privOps);
+                    }
+                }
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
+            {
+                jlong pConfigInfo = NEXT_LONG(b);
+                CONTINUE_IF_NULL(mtlc);
+                RESET_PREVIOUS_OP();
+                [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+                    MTLGC_DestroyMTLGraphicsConfig(pConfigInfo);
+                }];
+
+
+                // the previous method will call glX/wglMakeCurrent(None),
+                // so we should nullify the current mtlc and dstOps to avoid
+                // calling glFlush() (or similar) while no context is current
+                mtlc = NULL;
+             //   dstOps = NULL;
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
+            {
+                //TODO
+                // flush just in case there are any pending operations in
+                // the hardware pipe
+                if (mtlc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                // invalidate the references to the current context and
+                // destination surface that are maintained at the native level
+                mtlc = NULL;
+            //    dstOps = NULL;
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE:
+            {
+                //TODO
+            }
+            break;
+
+        case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE:
+            {
+                //TODO
+
+            }
+            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 (mtlc != NULL) {
+                    RESET_PREVIOUS_OP();
+                }
+                MTLSD_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:
+            {
+                MTLPaints_ResetPaint(mtlc);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
+            {
+                jint pixel = NEXT_INT(b);
+
+                if (dstOps != NULL) {
+                    MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps;
+                    dstCGLOps->configInfo->context.color = pixel;
+                }
+                MTLPaints_SetColor(mtlc, pixel);
+            }
+            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);
+                if (dstOps != NULL) {
+                    MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps;
+                    [dstCGLOps->configInfo->context setGradientPaintUseMask:useMask cyclic:cyclic
+                                                                         p0:p0 p1:p1 p3:p3
+                                                                     pixel1:pixel1 pixel2: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));
+                MTLPaints_SetLinearGradientPaint(mtlc, 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));
+                MTLPaints_SetRadialGradientPaint(mtlc, 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);
+                MTLPaints_SetTexturePaint(mtlc, 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);
+                MTLBufImgOps_EnableConvolveOp(mtlc, pSrc, edgeZero,
+                                              kernelWidth, kernelHeight, b);
+                SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
+            {
+                MTLBufImgOps_DisableConvolveOp(mtlc);
+            }
+            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));
+                MTLBufImgOps_EnableRescaleOp(mtlc, pSrc, nonPremult,
+                                             scaleFactors, offsets);
+                SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
+            {
+                MTLBufImgOps_DisableRescaleOp(mtlc);
+            }
+            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;
+                MTLBufImgOps_EnableLookupOp(mtlc, pSrc, nonPremult, shortData,
+                                            numBands, bandLength, offset,
+                                            tableValues);
+                SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
+            }
+            break;
+        case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
+            {
+                MTLBufImgOps_DisableLookupOp(mtlc);
+            }
+            break;
+
+        default:
+            J2dRlsTraceLn1(J2D_TRACE_ERROR,
+                "MTLRenderQueue_flushBuffer: invalid opcode=%d", opcode);
+            if (mtlc != NULL) {
+                RESET_PREVIOUS_OP();
+            }
+            return;
+        }
+
+        if (isDrawOpcode(opcode)) // performed rendering operation on dstOps
+            onSurfaceModified(dstOps);
+    }
+
+    MTLTR_DisableGlyphModeState();
+    scheduleBlitAllModifiedLayers();
+}
+
+/**
+ * Returns a pointer to the "current" context, as set by the last SET_SURFACES
+ * or SET_SCRATCH_SURFACE operation.
+ */
+MTLContext *
+MTLRenderQueue_GetCurrentContext()
+{
+    return mtlc;
+}
+
+/**
+ * Returns a pointer to the "current" destination surface, as set by the last
+ * SET_SURFACES operation.
+ */
+BMTLSDOps *
+MTLRenderQueue_GetCurrentDestination()
+{
+    return dstOps;
+}
+
+/**
+ * Used to track whether we are within a series of simple primitive operations
+ * or texturing operations.  The op parameter determines the nature of the
+ * operation that is to follow.  Valid values for this op parameter are:
+ */
+void
+MTLRenderQueue_CheckPreviousOp(jint op)
+{
+    //TODO
+    previousOp = op;
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLRenderer_h_Included
+#define MTLRenderer_h_Included
+
+#include "sun_java2d_pipe_BufferedRenderPipe.h"
+#include "MTLContext.h"
+#include "MTLGraphicsConfig.h"
+#import "MTLLayer.h"
+
+#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
+
+void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint x1, jint y1, jint x2, jint y2);
+void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint x, jint y, jint w, jint h);
+void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint nPoints, jint isClosed,
+                          jint transX, jint transY,
+                          jint *xPoints, jint *yPoints);
+void MTLRenderer_DrawScanlines(MTLContext *mtlc, BMTLSDOps * dstOps,
+                               jint count, jint *scanlines);
+void MTLRenderer_DrawParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
+                                   jfloat fx11, jfloat fy11,
+                                   jfloat dx21, jfloat dy21,
+                                   jfloat dx12, jfloat dy12,
+                                   jfloat lw21, jfloat lw12);
+void MTLRenderer_DrawAAParallelogram(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                     jfloat fx11, jfloat fy11,
+                                     jfloat dx21, jfloat dy21,
+                                     jfloat dx12, jfloat dy12,
+                                     jfloat lw21, jfloat lw12);
+
+void MTLRenderer_FillRect(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint x, jint y, jint w, jint h);
+void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps,
+                           jint count, jint *spans);
+void MTLRenderer_FillParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
+                                   jfloat fx11, jfloat fy11,
+                                   jfloat dx21, jfloat dy21,
+                                   jfloat dx12, jfloat dy12);
+void MTLRenderer_FillAAParallelogram(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                     jfloat fx11, jfloat fy11,
+                                     jfloat dx21, jfloat dy21,
+                                     jfloat dx12, jfloat dy12);
+
+void MTLRenderer_EnableAAParallelogramProgram();
+void MTLRenderer_DisableAAParallelogramProgram();
+
+#endif /* MTLRenderer_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,645 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <jlong.h>
+#include <jni_util.h>
+#include <math.h>
+
+#include "sun_java2d_metal_MTLRenderer.h"
+
+#include "MTLRenderer.h"
+#include "MTLRenderQueue.h"
+#include "MTLSurfaceData.h"
+#include "MTLUtils.h"
+#import "MTLLayer.h"
+
+/**
+ * Note: Some of the methods in this file apply a "magic number"
+ * translation to line segments.  The OpenGL specification lays out the
+ * "diamond exit rule" for line rasterization, but it is loose enough to
+ * allow for a wide range of line rendering hardware.  (It appears that
+ * some hardware, such as the Nvidia GeForce2 series, does not even meet
+ * the spec in all cases.)  As such it is difficult to find a mapping
+ * between the Java2D and OpenGL line specs that works consistently across
+ * all hardware combinations.
+ *
+ * Therefore the "magic numbers" you see here have been empirically derived
+ * after testing on a variety of graphics hardware in order to find some
+ * reasonable middle ground between the two specifications.  The general
+ * approach is to apply a fractional translation to vertices so that they
+ * hit pixel centers and therefore touch the same pixels as in our other
+ * pipelines.  Emphasis was placed on finding values so that MTL lines with
+ * a slope of +/- 1 hit all the same pixels as our other (software) loops.
+ * The stepping in other diagonal lines rendered with MTL may deviate
+ * slightly from those rendered with our software loops, but the most
+ * important thing is that these magic numbers ensure that all MTL lines
+ * hit the same endpoints as our software loops.
+ *
+ * If you find it necessary to change any of these magic numbers in the
+ * future, just be sure that you test the changes across a variety of
+ * hardware to ensure consistent rendering everywhere.
+ */
+
+void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1, jint x2, jint y2) {
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawLine: dest is null");
+        return;
+    }
+
+    J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawLine (x1=%1.2f y1=%1.2f x2=%1.2f y2=%1.2f), dst tex=%p", x1, y1, x2, y2, dstOps->pTexture);
+
+    id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dstOps->pTexture];
+    if (mtlEncoder == nil)
+        return;
+
+    struct Vertex verts[2] = {
+            {{x1, y1, 0.0}},
+            {{x2, y2, 0.0}}
+    };
+
+    [mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
+    [mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2];
+    [mtlEncoder endEncoding];
+}
+
+void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, jint w, jint h) {
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawRect: dest is null");
+        return;
+    }
+
+    id<MTLTexture> dest = dstOps->pTexture;
+    J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
+
+    // TODO: use DrawParallelogram(x, y, w, h, lw=1, lh=1)
+    id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dest];
+    if (mtlEncoder == nil)
+        return;
+
+    const int verticesCount = 5;
+    struct Vertex vertices[5] = {
+            {{x, y, 0.0}},
+            {{x + w, y, 0.0}},
+            {{x + w, y + h, 0.0}},
+            {{x, y + h, 0.0}},
+            {{x, y, 0.0}},
+    };
+    [mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer];
+    [mtlEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:verticesCount];
+    [mtlEncoder endEncoding];
+}
+
+const int POLYLINE_BUF_SIZE = 64;
+
+static void fillVertex(struct Vertex * vertex, int x, int y) {
+    vertex->position[0] = x;
+    vertex->position[1] = y;
+    vertex->position[2] = 0;
+}
+
+void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps,
+                     jint nPoints, jint isClosed,
+                     jint transX, jint transY,
+                     jint *xPoints, jint *yPoints)
+{
+    // Note that BufferedRenderPipe.drawPoly() has already rejected polys
+    // with nPoints<2, so we can be certain here that we have nPoints>=2.
+    if (xPoints == NULL || yPoints == NULL || nPoints < 2) { // just for insurance
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawPoly: points array is empty");
+        return;
+    }
+
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawPoly: dest is null");
+        return;
+    }
+
+    J2dTraceLn4(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: %d points, transX=%d, transY=%d, dst tex=%p", nPoints, transX, transY, dstOps->pTexture);
+
+    __block struct {
+        struct Vertex verts[POLYLINE_BUF_SIZE];
+    } pointsChunk;
+
+    jint prevX = *(xPoints++);
+    jint prevY = *(yPoints++);
+    --nPoints;
+    const jint firstX = prevX;
+    const jint firstY = prevY;
+    while (nPoints > 0) {
+        fillVertex(pointsChunk.verts, prevX + transX, prevY + transY);
+
+        const bool isLastChunk = nPoints + 1 <= POLYLINE_BUF_SIZE;
+        __block int chunkSize = isLastChunk ? nPoints : POLYLINE_BUF_SIZE - 1;
+
+        for (int i = 1; i < chunkSize; i++) {
+            prevX = *(xPoints++);
+            prevY = *(yPoints++);
+            fillVertex(pointsChunk.verts + i, prevX + transX, prevY + transY);
+        }
+
+        bool drawCloseSegment = false;
+        if (isClosed && isLastChunk) {
+            if (chunkSize + 2 <= POLYLINE_BUF_SIZE) {
+                fillVertex(pointsChunk.verts + chunkSize, firstX + transX, firstY + transY);
+                ++chunkSize;
+            } else
+                drawCloseSegment = true;
+        }
+
+        nPoints -= chunkSize;
+        id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dstOps->pTexture];
+        if (mtlEncoder == nil)
+            return;
+
+        [mtlEncoder setVertexBytes:pointsChunk.verts length:sizeof(pointsChunk.verts) atIndex:MeshVertexBuffer];
+        [mtlEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:chunkSize + 1];
+        if (drawCloseSegment) {
+            struct Vertex vertices[2] = {
+                    {{prevX + transX, prevY + transY, 0.0}},
+                    {{firstX + transX, firstY + transY, 0.0}},
+            };
+            [mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer];
+            [mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2];
+        }
+
+        [mtlEncoder endEncoding];
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLRenderer_drawPoly
+    (JNIEnv *env, jobject mtlr,
+     jintArray xpointsArray, jintArray ypointsArray,
+     jint nPoints, jboolean isClosed,
+     jint transX, jint transY)
+{
+    jint *xPoints, *yPoints;
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_drawPoly");
+}
+
+void
+MTLRenderer_DrawScanlines(MTLContext *mtlc, BMTLSDOps * dstOps,
+                          jint scanlineCount, jint *scanlines)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines");
+}
+
+void
+MTLRenderer_FillRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, jint w, jint h)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_FillRect");
+
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillRect: current dest is null");
+        return;
+    }
+
+    struct Vertex verts[PGRAM_VERTEX_COUNT] = {
+            { {x, y, 0.0}},
+            { {x, y+h, 0.0}},
+            { {x+w, y+h, 0.0}},
+            { {x+w, y+h, 0.0}},
+            { {x+w, y, 0.0}},
+            { {x, y, 0.0},
+    }};
+
+
+    id<MTLTexture> dest = dstOps->pTexture;
+    J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_FillRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
+
+    // Encode render command.
+    id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dest];
+    if (mtlEncoder == nil)
+        return;
+
+    [mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
+    [mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: PGRAM_VERTEX_COUNT];
+    [mtlEncoder endEncoding];
+}
+
+const int SPAN_BUF_SIZE=64;
+
+void
+MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, jint *spans)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_FillSpans");
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillSpans: dest is null");
+        return;
+    }
+
+    while (spanCount > 0) {
+        __block struct {
+            jfloat spns[SPAN_BUF_SIZE*4];
+        } spanStruct;
+
+        __block jfloat sc = spanCount > SPAN_BUF_SIZE ? SPAN_BUF_SIZE : spanCount;
+
+        for (int i = 0; i < sc; i++) {
+            spanStruct.spns[i * 4] = *(spans++);
+            spanStruct.spns[i * 4 + 1] = *(spans++);
+            spanStruct.spns[i * 4 + 2] = *(spans++);
+            spanStruct.spns[i * 4 + 3] = *(spans++);
+        }
+
+        spanCount -= sc;
+
+        id<MTLTexture> dest = dstOps->pTexture;
+        id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dest];
+        if (mtlEncoder == nil)
+            return;
+
+        for (int i = 0; i < sc; i++) {
+            jfloat x1 = spanStruct.spns[i * 4];
+            jfloat y1 = spanStruct.spns[i * 4 + 1];
+            jfloat x2 = spanStruct.spns[i * 4 + 2];
+            jfloat y2 = spanStruct.spns[i * 4 + 3];
+
+            struct Vertex verts[PGRAM_VERTEX_COUNT] = {
+                {{x1, y1, 0.0}},
+                {{x2, y1, 0.0}},
+                {{x1, y2, 0.0}},
+                {{x2, y1, 0.0}},
+                {{x2, y2, 0.0}},
+                {{x1, y2, 0.0},
+            }};
+
+            [mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
+            [mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:PGRAM_VERTEX_COUNT];
+        }
+
+        [mtlEncoder endEncoding];
+        [mtlEncoder release];
+    }
+}
+
+void
+MTLRenderer_FillParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
+                              jfloat fx11, jfloat fy11,
+                              jfloat dx21, jfloat dy21,
+                              jfloat dx12, jfloat dy12)
+{
+
+    if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillParallelogram: current dest is null");
+        return;
+    }
+
+    id<MTLTexture> dest = dstOps->pTexture;
+    J2dTraceLn7(J2D_TRACE_INFO,
+                "MTLRenderer_FillParallelogram "
+                "(x=%6.2f y=%6.2f "
+                "dx1=%6.2f dy1=%6.2f "
+                "dx2=%6.2f dy2=%6.2f dst tex=%p)",
+                fx11, fy11,
+                dx21, dy21,
+                dx12, dy12, dest);
+
+    struct Vertex verts[PGRAM_VERTEX_COUNT] = {
+            { {fx11, fy11, 0.0}},
+            { {fx11+dx21, fy11+dy21, 0.0}},
+            { {fx11+dx12, fy11+dy12, 0.0}},
+            { {fx11+dx21, fy11+dy21, 0.0}},
+            { {fx11 + dx21 + dx12, fy11+ dy21 + dy12, 0.0}},
+            { {fx11+dx12, fy11+dy12, 0.0},
+            }};
+
+    // Encode render command.
+    id<MTLRenderCommandEncoder> mtlEncoder = [mtlc createRenderEncoderForDest:dest];
+    if (mtlEncoder == nil)
+        return;
+
+    [mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
+    [mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount: PGRAM_VERTEX_COUNT];
+    [mtlEncoder endEncoding];
+}
+
+void
+MTLRenderer_DrawParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
+                              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,
+                "MTLRenderer_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);
+
+
+    // 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;
+        MTLRenderer_FillParallelogram(mtlc, dstOps, 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;
+        MTLRenderer_FillParallelogram(mtlc, dstOps, 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;
+        MTLRenderer_FillParallelogram(mtlc, dstOps, 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;
+        MTLRenderer_FillParallelogram(mtlc, dstOps, 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;
+        MTLRenderer_FillParallelogram(mtlc, dstOps, ox11, oy11, dx21, dy21, dx12, dy12);
+    }
+}
+
+
+static GLhandleARB aaPgramProgram = 0;
+
+/*
+ * This shader fills the space between an outer and inner parallelogram.
+ * It can be used to draw an outline by specifying both inner and outer
+ * values.  It fills pixels by estimating what portion falls inside the
+ * outer shape, and subtracting an estimate of what portion falls inside
+ * the inner shape.  Specifying both inner and outer values produces a
+ * standard "wide outline".  Specifying an inner shape that falls far
+ * outside the outer shape allows the same shader to fill the outer
+ * shape entirely since pixels that fall within the outer shape are never
+ * inside the inner shape and so they are filled based solely on their
+ * coverage of the outer shape.
+ *
+ * The setup code renders this shader over the bounds of the outer
+ * shape (or the only shape in the case of a fill operation) and
+ * sets the texture 0 coordinates so that 0,0=>0,1=>1,1=>1,0 in those
+ * texture coordinates map to the four corners of the parallelogram.
+ * Similarly the texture 1 coordinates map the inner shape to the
+ * unit square as well, but in a different coordinate system.
+ *
+ * When viewed in the texture coordinate systems the parallelograms
+ * we are filling are unit squares, but the pixels have then become
+ * tiny parallelograms themselves.  Both of the texture coordinate
+ * systems are affine transforms so the rate of change in X and Y
+ * of the texture coordinates are essentially constants and happen
+ * to correspond to the size and direction of the slanted sides of
+ * the distorted pixels relative to the "square mapped" boundary
+ * of the parallelograms.
+ *
+ * The shader uses the dFdx() and dFdy() functions to measure the "rate
+ * of change" of these texture coordinates and thus gets an accurate
+ * measure of the size and shape of a pixel relative to the two
+ * parallelograms.  It then uses the bounds of the size and shape
+ * of a pixel to intersect with the unit square to estimate the
+ * coverage of the pixel.  Unfortunately, without a lot more work
+ * to calculate the exact area of intersection between a unit
+ * square (the original parallelogram) and a parallelogram (the
+ * distorted pixel), this shader only approximates the pixel
+ * coverage, but emperically the estimate is very useful and
+ * produces visually pleasing results, if not theoretically accurate.
+ */
+static const char *aaPgramShaderSource =
+    "void main() {"
+    // Calculate the vectors for the "legs" of the pixel parallelogram
+    // for the outer parallelogram.
+    "    vec2 oleg1 = dFdx(gl_TexCoord[0].st);"
+    "    vec2 oleg2 = dFdy(gl_TexCoord[0].st);"
+    // Calculate the bounds of the distorted pixel parallelogram.
+    "    vec2 corner = gl_TexCoord[0].st - (oleg1+oleg2)/2.0;"
+    "    vec2 omin = min(corner, corner+oleg1);"
+    "    omin = min(omin, corner+oleg2);"
+    "    omin = min(omin, corner+oleg1+oleg2);"
+    "    vec2 omax = max(corner, corner+oleg1);"
+    "    omax = max(omax, corner+oleg2);"
+    "    omax = max(omax, corner+oleg1+oleg2);"
+    // Calculate the vectors for the "legs" of the pixel parallelogram
+    // for the inner parallelogram.
+    "    vec2 ileg1 = dFdx(gl_TexCoord[1].st);"
+    "    vec2 ileg2 = dFdy(gl_TexCoord[1].st);"
+    // Calculate the bounds of the distorted pixel parallelogram.
+    "    corner = gl_TexCoord[1].st - (ileg1+ileg2)/2.0;"
+    "    vec2 imin = min(corner, corner+ileg1);"
+    "    imin = min(imin, corner+ileg2);"
+    "    imin = min(imin, corner+ileg1+ileg2);"
+    "    vec2 imax = max(corner, corner+ileg1);"
+    "    imax = max(imax, corner+ileg2);"
+    "    imax = max(imax, corner+ileg1+ileg2);"
+    // Clamp the bounds of the parallelograms to the unit square to
+    // estimate the intersection of the pixel parallelogram with
+    // the unit square.  The ratio of the 2 rectangle areas is a
+    // reasonable estimate of the proportion of coverage.
+    "    vec2 o1 = clamp(omin, 0.0, 1.0);"
+    "    vec2 o2 = clamp(omax, 0.0, 1.0);"
+    "    float oint = (o2.y-o1.y)*(o2.x-o1.x);"
+    "    float oarea = (omax.y-omin.y)*(omax.x-omin.x);"
+    "    vec2 i1 = clamp(imin, 0.0, 1.0);"
+    "    vec2 i2 = clamp(imax, 0.0, 1.0);"
+    "    float iint = (i2.y-i1.y)*(i2.x-i1.x);"
+    "    float iarea = (imax.y-imin.y)*(imax.x-imin.x);"
+    // Proportion of pixel in outer shape minus the proportion
+    // of pixel in the inner shape == the coverage of the pixel
+    // in the area between the two.
+    "    float coverage = oint/oarea - iint / iarea;"
+    "    gl_FragColor = gl_Color * coverage;"
+    "}";
+
+#define ADJUST_PGRAM(V1, DV, V2) \
+    do { \
+        if ((DV) >= 0) { \
+            (V2) += (DV); \
+        } else { \
+            (V1) += (DV); \
+        } \
+    } while (0)
+
+// Invert the following transform:
+// DeltaT(0, 0) == (0,       0)
+// DeltaT(1, 0) == (DX1,     DY1)
+// DeltaT(0, 1) == (DX2,     DY2)
+// DeltaT(1, 1) == (DX1+DX2, DY1+DY2)
+// TM00 = DX1,   TM01 = DX2,   (TM02 = X11)
+// TM10 = DY1,   TM11 = DY2,   (TM12 = Y11)
+// Determinant = TM00*TM11 - TM01*TM10
+//             =  DX1*DY2  -  DX2*DY1
+// Inverse is:
+// IM00 =  TM11/det,   IM01 = -TM01/det
+// IM10 = -TM10/det,   IM11 =  TM00/det
+// IM02 = (TM01 * TM12 - TM11 * TM02) / det,
+// IM12 = (TM10 * TM02 - TM00 * TM12) / det,
+
+#define DECLARE_MATRIX(MAT) \
+    jfloat MAT ## 00, MAT ## 01, MAT ## 02, MAT ## 10, MAT ## 11, MAT ## 12
+
+#define GET_INVERTED_MATRIX(MAT, X11, Y11, DX1, DY1, DX2, DY2, RET_CODE) \
+    do { \
+        jfloat det = DX1*DY2 - DX2*DY1; \
+        if (det == 0) { \
+            RET_CODE; \
+        } \
+        MAT ## 00 = DY2/det; \
+        MAT ## 01 = -DX2/det; \
+        MAT ## 10 = -DY1/det; \
+        MAT ## 11 = DX1/det; \
+        MAT ## 02 = (DX2 * Y11 - DY2 * X11) / det; \
+        MAT ## 12 = (DY1 * X11 - DX1 * Y11) / det; \
+    } while (0)
+
+#define TRANSFORM(MAT, TX, TY, X, Y) \
+    do { \
+        TX = (X) * MAT ## 00 + (Y) * MAT ## 01 + MAT ## 02; \
+        TY = (X) * MAT ## 10 + (Y) * MAT ## 11 + MAT ## 12; \
+    } while (0)
+
+void
+MTLRenderer_FillAAParallelogram(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                jfloat fx11, jfloat fy11,
+                                jfloat dx21, jfloat dy21,
+                                jfloat dx12, jfloat dy12)
+{
+    //TODO
+    DECLARE_MATRIX(om);
+    // parameters for parallelogram bounding box
+    jfloat bx11, by11, bx22, by22;
+    // parameters for uv texture coordinates of parallelogram corners
+    jfloat u11, v11, u12, v12, u21, v21, u22, v22;
+
+    J2dTraceLn6(J2D_TRACE_INFO,
+                "MTLRenderer_FillAAParallelogram "
+                "(x=%6.2f y=%6.2f "
+                "dx1=%6.2f dy1=%6.2f "
+                "dx2=%6.2f dy2=%6.2f)",
+                fx11, fy11,
+                dx21, dy21,
+                dx12, dy12);
+
+}
+
+void
+MTLRenderer_FillAAParallelogramInnerOuter(MTLContext *mtlc, MTLSDOps *dstOps,
+                                          jfloat ox11, jfloat oy11,
+                                          jfloat ox21, jfloat oy21,
+                                          jfloat ox12, jfloat oy12,
+                                          jfloat ix11, jfloat iy11,
+                                          jfloat ix21, jfloat iy21,
+                                          jfloat ix12, jfloat iy12)
+{
+    //TODO
+}
+
+void
+MTLRenderer_DrawAAParallelogram(MTLContext *mtlc, BMTLSDOps *dstOps,
+                                jfloat fx11, jfloat fy11,
+                                jfloat dx21, jfloat dy21,
+                                jfloat dx12, jfloat dy12,
+                                jfloat lwr21, jfloat lwr12)
+{
+    //TODO
+    // dx,dy for line width in the "21" and "12" directions.
+    jfloat ldx21, ldy21, ldx12, ldy12;
+    // parameters for "outer" parallelogram
+    jfloat ofx11, ofy11, odx21, ody21, odx12, ody12;
+    // parameters for "inner" parallelogram
+    jfloat ifx11, ify11, idx21, idy21, idx12, idy12;
+
+    J2dTraceLn8(J2D_TRACE_INFO,
+                "MTLRenderer_DrawAAParallelogram "
+                "(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);
+
+}
+
+void
+MTLRenderer_EnableAAParallelogramProgram()
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_EnableAAParallelogramProgram");
+}
+
+void
+MTLRenderer_DisableAAParallelogramProgram()
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DisableAAParallelogramProgram");
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLSurfaceData_h_Included
+#define MTLSurfaceData_h_Included
+
+#import "MTLSurfaceDataBase.h"
+#import "MTLGraphicsConfig.h"
+#import "AWTWindow.h"
+#import "MTLLayer.h"
+
+/**
+ * The CGLSDOps structure contains the CGL-specific information for a given
+ * MTLSurfaceData.  It is referenced by the native MTLSDOps structure.
+ */
+typedef struct _MTLSDOps {
+    AWTView               *peerData;
+    MTLLayer              *layer;
+    jint              argb[4]; // background clear color
+    MTLGraphicsConfigInfo *configInfo;
+} MTLSDOps;
+
+#endif /* MTLSurfaceData_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,454 @@
+/*
+ * 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.
+ */
+
+#import <stdlib.h>
+
+#import "sun_java2d_metal_MTLSurfaceData.h"
+
+#import "jni_util.h"
+#import "MTLRenderQueue.h"
+#import "MTLGraphicsConfig.h"
+#import "MTLSurfaceData.h"
+#import "ThreadUtilities.h"
+#include "jlong.h"
+
+/**
+ * The following methods are implemented in the windowing system (i.e. GLX
+ * and WGL) source files.
+ */
+extern jlong MTLSD_GetNativeConfigInfo(BMTLSDOps *mtlsdo);
+extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);
+extern void MTLSD_DestroyMTLSurface(JNIEnv *env, MTLSDOps *mtlsdo);
+
+void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo, jint w, jint h);
+
+/**
+ * This table contains the "pixel formats" for all system memory surfaces
+ * that OpenGL is capable of handling, indexed by the "PF_" constants defined
+ * in MTLSurfaceData.java.  These pixel formats contain information that is
+ * passed to OpenGL when copying from a system memory ("Sw") surface to
+ * an OpenGL "Surface" (via glDrawPixels()) or "Texture" (via glTexImage2D()).
+ */
+MTLPixelFormat MTPixelFormats[] = {};
+
+/**
+ * Given a starting value and a maximum limit, returns the first power-of-two
+ * greater than the starting value.  If the resulting value is greater than
+ * the maximum limit, zero is returned.
+ */
+jint
+MTLSD_NextPowerOfTwo(jint val, jint max)
+{
+    jint i;
+
+    if (val > max) {
+        return 0;
+    }
+
+    for (i = 1; i < val; i *= 2);
+
+    return i;
+}
+
+/**
+ * Returns true if both given dimensions are a power of two.
+ */
+static jboolean
+MTLSD_IsPowerOfTwo(jint width, jint height)
+{
+    return (((width & (width-1)) | (height & (height-1))) == 0);
+}
+
+/**
+ * Initializes an MTL texture, using the given width and height as
+ * a guide.
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_initTexture
+    (JNIEnv *env, jobject mtlsd,
+     jlong pData, jboolean isOpaque,
+     jboolean texNonPow2, jboolean texRect,
+     jint width, jint height)
+{
+    BMTLSDOps *bmtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
+    J2dTraceLn3(J2D_TRACE_INFO, "MTLSurfaceData_initTexture: w=%d h=%d p=%p", width, height, bmtlsdo);
+
+    if (bmtlsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: ops are null");
+        return JNI_FALSE;
+    }
+
+    if (width <= 0 || height <= 0) {
+        J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", width, height);
+        return JNI_FALSE;
+    }
+
+    MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
+    if (mtlsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps are null");
+        return JNI_FALSE;
+    }
+
+    if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps wasn't initialized (context is null)");
+        return JNI_FALSE;
+    }
+
+    MTLContext* ctx = mtlsdo->configInfo->context;
+
+    MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO];
+    bmtlsdo->pTexture = [[ctx.device newTextureWithDescriptor: textureDescriptor] retain];
+    bmtlsdo->isOpaque = isOpaque;
+    bmtlsdo->xOffset = 0;
+    bmtlsdo->yOffset = 0;
+    bmtlsdo->width = width;
+    bmtlsdo->height = height;
+    bmtlsdo->textureWidth = width;
+    bmtlsdo->textureHeight = height;
+    bmtlsdo->textureTarget = -1;
+    bmtlsdo->drawableType = MTLSD_TEXTURE;
+
+    MTLSD_SetNativeDimensions(env, bmtlsdo, width, width);
+    J2dTraceLn4(J2D_TRACE_VERBOSE, "\tcreated MTLTexture [texture]: w=%d h=%d bp=%p [tex=%p]", width, height, bmtlsdo, bmtlsdo->pTexture);
+
+    return JNI_TRUE;
+}
+
+/**
+ * Initializes a framebuffer object, using the given width and height as
+ * a guide.  See MTLSD_InitTextureObject() and MTLSD_initRTexture()
+ * for more information.
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_initRTexture
+    (JNIEnv *env, jobject mtlsd,
+     jlong pData, jboolean isOpaque,
+     jboolean texNonPow2, jboolean texRect,
+     jint width, jint height)
+{
+
+    BMTLSDOps *bmtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
+
+    if (bmtlsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+            "MTLSurfaceData_initRTexture: BMTLSDOps are null");
+        return JNI_FALSE;
+    }
+
+    MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
+
+    if (mtlsdo == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR,
+            "MTLSurfaceData_initRTexture: MTLSDOps are null");
+        return JNI_FALSE;
+    }
+
+    if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {
+        J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initRTexture: MTLSDOps wasn't initialized (context is null)");
+        return JNI_FALSE;
+    }
+
+    const MTLContext* ctx = mtlsdo->configInfo->context;
+    MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO];
+    bmtlsdo->pTexture = [[ctx.device newTextureWithDescriptor: textureDescriptor] retain];;
+
+    bmtlsdo->isOpaque = isOpaque;
+    bmtlsdo->xOffset = 0;
+    bmtlsdo->yOffset = 0;
+    bmtlsdo->width = width;
+    bmtlsdo->height = height;
+    bmtlsdo->textureWidth = width;
+    bmtlsdo->textureHeight = height;
+    bmtlsdo->textureTarget = -1;
+    bmtlsdo->drawableType = MTLSD_RT_TEXTURE;
+
+    MTLSD_SetNativeDimensions(env, bmtlsdo, width, width);
+    J2dTraceLn4(J2D_TRACE_VERBOSE, "\tcreated MTLTexture [FBObject]: w=%d h=%d bp=%p [tex=%p]", width, height, bmtlsdo, bmtlsdo->pTexture);
+
+    return JNI_TRUE;
+}
+
+/**
+ * Initializes a surface in the backbuffer of a given double-buffered
+ * onscreen window for use in a BufferStrategy.Flip situation.  The bounds of
+ * the backbuffer surface should always be kept in sync with the bounds of
+ * the underlying native window.
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_initFlipBackbuffer
+    (JNIEnv *env, jobject mtlsd,
+     jlong pData)
+{
+    //TODO
+    MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData);
+
+    J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_initFlipBackbuffer");
+    return JNI_TRUE;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_getTextureTarget
+    (JNIEnv *env, jobject mtlsd,
+     jlong pData)
+{
+    //TODO
+    MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData);
+
+    J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_getTextureTarget");
+
+    return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_getTextureID
+    (JNIEnv *env, jobject mtlsd,
+     jlong pData)
+{
+    //TODO
+    return 0;
+}
+
+/**
+ * Initializes nativeWidth/Height fields of the surfaceData object with
+ * passed arguments.
+ */
+void
+MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo,
+                          jint width, jint height)
+{
+    jobject sdObject;
+
+    sdObject = (*env)->NewLocalRef(env, mtlsdo->sdOps.sdObject);
+    if (sdObject == NULL) {
+        return;
+    }
+
+    JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width);
+    if (!((*env)->ExceptionOccurred(env))) {
+        JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height);
+    }
+
+    (*env)->DeleteLocalRef(env, sdObject);
+}
+
+/**
+ * Deletes native OpenGL resources associated with this surface.
+ */
+void
+MTLSD_Delete(JNIEnv *env, BMTLSDOps *mtlsdo)
+{
+    //TODO
+    J2dTraceLn1(J2D_TRACE_INFO, "MTLSD_Delete: type=%d",
+                mtlsdo->drawableType);
+}
+
+/**
+ * This is the implementation of the general DisposeFunc defined in
+ * SurfaceData.h and used by the Disposer mechanism.  It first flushes all
+ * native OpenGL resources and then frees any memory allocated within the
+ * native MTLSDOps structure.
+ */
+void
+MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
+{
+    MTLSDOps *mtlsdo = (MTLSDOps *)ops;
+    jlong pConfigInfo = MTLSD_GetNativeConfigInfo(mtlsdo);
+
+    JNU_CallStaticMethodByName(env, NULL, "sun/java2d/metal/MTLSurfaceData",
+                               "dispose", "(JJ)V",
+                               ptr_to_jlong(ops), pConfigInfo);
+}
+
+/**
+ * This is the implementation of the general surface LockFunc defined in
+ * SurfaceData.h.
+ */
+jint
+MTLSD_Lock(JNIEnv *env,
+           SurfaceDataOps *ops,
+           SurfaceDataRasInfo *pRasInfo,
+           jint lockflags)
+{
+    JNU_ThrowInternalError(env, "MTLSD_Lock not implemented!");
+    return SD_FAILURE;
+}
+
+/**
+ * This is the implementation of the general GetRasInfoFunc defined in
+ * SurfaceData.h.
+ */
+void
+MTLSD_GetRasInfo(JNIEnv *env,
+                 SurfaceDataOps *ops,
+                 SurfaceDataRasInfo *pRasInfo)
+{
+    JNU_ThrowInternalError(env, "MTLSD_GetRasInfo not implemented!");
+}
+
+/**
+ * This is the implementation of the general surface UnlockFunc defined in
+ * SurfaceData.h.
+ */
+void
+MTLSD_Unlock(JNIEnv *env,
+             SurfaceDataOps *ops,
+             SurfaceDataRasInfo *pRasInfo)
+{
+    JNU_ThrowInternalError(env, "MTLSD_Unlock not implemented!");
+}
+
+/**
+ * This function disposes of any native windowing system resources associated
+ * with this surface.
+ */
+void
+MTLSD_DestroyMTLSurface(JNIEnv *env, MTLSDOps *mtlsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
+}
+
+/**
+ * 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
+MTLSD_GetNativeConfigInfo(BMTLSDOps *mtlsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo");
+
+    return 0;
+}
+
+/**
+ * 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
+MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *oglsdo)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "MTLSD_InitMTLWindow");
+
+    return JNI_TRUE;
+}
+
+void
+MTLSD_SwapBuffers(JNIEnv *env, jlong pPeerData)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
+}
+
+#pragma mark -
+#pragma mark "--- CGLSurfaceData methods ---"
+
+extern LockFunc        MTLSD_Lock;
+extern GetRasInfoFunc  MTLSD_GetRasInfo;
+extern UnlockFunc      MTLSD_Unlock;
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_initOps
+    (JNIEnv *env, jobject cglsd,
+     jlong pConfigInfo, jlong pPeerData, jlong layerPtr,
+     jint xoff, jint yoff, jboolean isOpaque)
+{
+    BMTLSDOps *bmtlsdo = (BMTLSDOps *)SurfaceData_InitOps(env, cglsd, sizeof(BMTLSDOps));
+    MTLSDOps *mtlsdo = (MTLSDOps *)malloc(sizeof(MTLSDOps));
+
+    J2dTraceLn1(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo);
+    J2dTraceLn1(J2D_TRACE_INFO, "  pPeerData=%p", jlong_to_ptr(pPeerData));
+    J2dTraceLn1(J2D_TRACE_INFO, "  layerPtr=%p", jlong_to_ptr(layerPtr));
+    J2dTraceLn2(J2D_TRACE_INFO, "  xoff=%d, yoff=%d", (int)xoff, (int)yoff);
+
+    if (mtlsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "creating native cgl ops");
+        return;
+    }
+
+    bmtlsdo->privOps = mtlsdo;
+
+    bmtlsdo->sdOps.Lock               = MTLSD_Lock;
+    bmtlsdo->sdOps.GetRasInfo         = MTLSD_GetRasInfo;
+    bmtlsdo->sdOps.Unlock             = MTLSD_Unlock;
+    bmtlsdo->sdOps.Dispose            = MTLSD_Dispose;
+
+    bmtlsdo->drawableType = MTLSD_UNDEFINED;
+    bmtlsdo->needsInit = JNI_TRUE;
+    bmtlsdo->xOffset = xoff;
+    bmtlsdo->yOffset = yoff;
+    bmtlsdo->isOpaque = isOpaque;
+
+    mtlsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData);
+    mtlsdo->layer = (MTLLayer *)jlong_to_ptr(layerPtr);
+    mtlsdo->configInfo = (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+
+    if (mtlsdo->configInfo == NULL) {
+        free(mtlsdo);
+        JNU_ThrowNullPointerException(env, "Config info is null in initOps");
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_clearWindow
+(JNIEnv *env, jobject cglsd)
+{
+    J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_clearWindow");
+
+    BMTLSDOps *mtlsdo = (MTLSDOps*) SurfaceData_GetOps(env, cglsd);
+    MTLSDOps *cglsdo = (MTLSDOps*) mtlsdo->privOps;
+
+    cglsdo->peerData = NULL;
+    cglsdo->layer = NULL;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLSurfaceData_validate
+    (JNIEnv *env, jobject jsurfacedata,
+     jint xoff, jint yoff, jint width, jint height, jboolean isOpaque)
+{
+    J2dTraceLn2(J2D_TRACE_INFO, "MTLLSurfaceData_validate: w=%d h=%d", width, height);
+
+    BMTLSDOps *mtlsdo = (BMTLSDOps*)SurfaceData_GetOps(env, jsurfacedata);
+    mtlsdo->needsInit = JNI_TRUE;
+    mtlsdo->xOffset = xoff;
+    mtlsdo->yOffset = yoff;
+
+    mtlsdo->width = width;
+    mtlsdo->height = height;
+    mtlsdo->isOpaque = isOpaque;
+
+    if (mtlsdo->drawableType == MTLSD_WINDOW) {
+        // J2dTraceLn4(J2D_TRACE_INFO, "MTLContext_SetSurfaces: w=%d h=%d src=%p dst=%p", width, height, mtlsdo, mtlsdo);
+        [MTLContext setSurfacesEnv:env src:ptr_to_jlong(mtlsdo) dst:ptr_to_jlong(mtlsdo)];
+
+        // we have to explicitly tell the NSOpenGLContext that its target
+        // drawable has changed size
+        MTLSDOps *cglsdo = (MTLSDOps *)mtlsdo->privOps;
+        MTLContext *mtlc = cglsdo->configInfo->context;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceDataBase.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLSurfaceDataBase_h_Included
+#define MTLSurfaceDataBase_h_Included
+
+#include "java_awt_image_AffineTransformOp.h"
+#include "sun_java2d_metal_MTLSurfaceData.h"
+#include "sun_java2d_pipe_hw_AccelSurface.h"
+
+#include "SurfaceData.h"
+#include "Trace.h"
+#include "MTLFuncs.h"
+
+
+/**
+ * The MTLPixelFormat structure contains all the information OpenGL needs to
+ * know when copying from or into a particular system memory image buffer (via
+ * glDrawPixels(), glReadPixels, glTexSubImage2D(), etc).
+ *
+ *     GLenum format;
+ * The pixel format parameter used in glDrawPixels() and other similar calls.
+ * Indicates the component ordering for each pixel (e.g. GL_BGRA).
+ *
+ *     GLenum type;
+ * The pixel data type parameter used in glDrawPixels() and other similar
+ * calls.  Indicates the data type for an entire pixel or for each component
+ * in a pixel (e.g. GL_UNSIGNED_BYTE with GL_BGR means a pixel consists of
+ * 3 unsigned byte components, blue first, then green, then red;
+ * GL_UNSIGNED_INT_8_8_8_8_REV with GL_BGRA means a pixel consists of 1
+ * unsigned integer comprised of four byte components, alpha first, then red,
+ * then green, then blue).
+ *
+ *     jint alignment;
+ * The byte alignment parameter used in glPixelStorei(GL_UNPACK_ALIGNMENT).  A
+ * value of 4 indicates that each pixel starts on a 4-byte aligned region in
+ * memory, and so on.  This alignment parameter helps OpenGL speed up pixel
+ * transfer operations by transferring memory in aligned blocks.
+ *
+ *     jboolean hasAlpha;
+ * If true, indicates that this pixel format contains an alpha component.
+ *
+ *     jboolean isPremult;
+ * If true, indicates that this pixel format contains color components that
+ * have been pre-multiplied by their corresponding alpha component.
+ */
+typedef struct {
+    //GLenum   format;
+    //GLenum   type;
+    jint format;
+    jint type;
+    jint     alignment;
+    jboolean hasAlpha;
+    jboolean isPremult;
+} MTPixelFormat;
+
+/**
+ * The MTLSDOps structure describes a native OpenGL surface and contains all
+ * information pertaining to the native surface.  Some information about
+ * the more important/different fields:
+ *
+ *     void *privOps;
+ * Pointer to native-specific (GLX, WGL, etc.) SurfaceData info, such as the
+ * native Drawable handle and GraphicsConfig data.
+ *
+ *     jint drawableType;
+ * The surface type; can be any one of the surface type constants defined
+ * below (MTLSD_WINDOW, MTLSD_TEXTURE, etc).
+ *
+ *     GLenum activeBuffer;
+ * Can be either GL_FRONT if this is the front buffer surface of an onscreen
+ * window or a pbuffer surface, or GL_BACK if this is the backbuffer surface
+ * of an onscreen window.
+ *
+ *     jboolean isOpaque;
+ * If true, the surface should be treated as being fully opaque.  If
+ * the underlying surface (e.g. pbuffer) has an alpha channel and isOpaque
+ * is true, then we should take appropriate action (i.e. call glColorMask()
+ * to disable writes into the alpha channel) to ensure that the surface
+ * remains fully opaque.
+ *
+ *     jboolean needsInit;
+ * If true, the surface requires some one-time initialization, which should
+ * be performed after a context has been made current to the surface for
+ * the first time.
+ *
+ *     jint x/yOffset
+ * The offset in pixels of the OpenGL viewport origin from the lower-left
+ * corner of the heavyweight drawable.  For example, a top-level frame on
+ * Windows XP has lower-left insets of (4,4).  The OpenGL viewport origin
+ * would typically begin at the lower-left corner of the client region (inside
+ * the frame decorations), but AWT/Swing will take the insets into account
+ * when rendering into that window.  So in order to account for this, we
+ * need to adjust the OpenGL viewport origin by an x/yOffset of (-4,-4).  On
+ * X11, top-level frames typically don't have this insets issue, so their
+ * x/yOffset would be (0,0) (the same applies to pbuffers).
+ *
+ *     jint width/height;
+ * The cached surface bounds.  For offscreen surface types (MTLSD_FBOBJECT,
+ * MTLSD_TEXTURE, etc.) these values must remain constant.  Onscreen window
+ * surfaces (MTLSD_WINDOW, MTLSD_FLIP_BACKBUFFER, etc.) may have their
+ * bounds changed in response to a programmatic or user-initiated event, so
+ * these values represent the last known dimensions.  To determine the true
+ * current bounds of this surface, query the native Drawable through the
+ * privOps field.
+ *
+ *     GLuint textureID;
+ * The texture object handle, as generated by glGenTextures().  If this value
+ * is zero, the texture has not yet been initialized.
+ *
+ *     jint textureWidth/Height;
+ * The actual bounds of the texture object for this surface.  If the
+ * GL_ARB_texture_non_power_of_two extension is not present, the dimensions
+ * of an OpenGL texture object must be a power-of-two (e.g. 64x32 or 128x512).
+ * The texture image that we care about has dimensions specified by the width
+ * and height fields in this MTLSDOps structure.  For example, if the image
+ * to be stored in the texture has dimensions 115x47, the actual OpenGL
+ * texture we allocate will have dimensions 128x64 to meet the pow2
+ * restriction.  The image bounds within the texture can be accessed using
+ * floating point texture coordinates in the range [0.0,1.0].
+ *
+ *     GLenum textureTarget;
+ * The texture target of the texture object for this surface.  If this
+ * surface is not backed by a texture, this value is set to zero.  Otherwise,
+ * this value is GL_TEXTURE_RECTANGLE_ARB when the GL_ARB_texture_rectangle
+ * extension is in use; if not, it is set to GL_TEXTURE_2D.
+ *
+ *     GLint textureFilter;
+ * The current filter state for this texture object (can be either GL_NEAREST
+ * or GL_LINEAR).  We cache this value here and check it before updating
+ * the filter state to avoid redundant calls to glTexParameteri() when the
+ * filter state remains constant (see the MTLSD_UPDATE_TEXTURE_FILTER()
+ * macro below).
+ *
+ *     GLuint fbobjectID, depthID;
+ * The object handles for the framebuffer object and depth renderbuffer
+ * associated with this surface.  These fields are only used when
+ * drawableType is MTLSD_FBOBJECT, otherwise they are zero.
+ */
+typedef struct {
+    SurfaceDataOps               sdOps;
+    void                         *privOps;
+    jint                         drawableType;
+    jint                       activeBuffer;
+    jboolean                     isOpaque;
+    jboolean                     needsInit;
+    jint                         xOffset;
+    jint                         yOffset;
+    jint                         width;
+    jint                         height;
+    void*                        pTexture;
+    jint                         textureWidth;
+    jint                         textureHeight;
+   /* GLenum */ jint                      textureTarget;
+   /* GLint  */ jint                      textureFilter;
+   /* GLuint */ jint                      fbobjectID;
+   /* GLuint  */ jint                     depthID;
+} BMTLSDOps;
+
+#define MTLSD_UNDEFINED       sun_java2d_pipe_hw_AccelSurface_UNDEFINED
+#define MTLSD_WINDOW          sun_java2d_pipe_hw_AccelSurface_WINDOW
+#define MTLSD_TEXTURE         sun_java2d_pipe_hw_AccelSurface_TEXTURE
+#define MTLSD_FLIP_BACKBUFFER sun_java2d_pipe_hw_AccelSurface_FLIP_BACKBUFFER
+#define MTLSD_RT_TEXTURE        sun_java2d_pipe_hw_AccelSurface_RT_TEXTURE
+
+/**
+ * These are shorthand names for the filtering method constants used by
+ * image transform methods.
+ */
+#define MTLSD_XFORM_DEFAULT 0
+#define MTLSD_XFORM_NEAREST_NEIGHBOR \
+    java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR
+#define MTLSD_XFORM_BILINEAR \
+    java_awt_image_AffineTransformOp_TYPE_BILINEAR
+
+/**
+ * Exported methods.
+ */
+jint MTLSD_Lock(JNIEnv *env,
+                SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo,
+                jint lockflags);
+void MTLSD_GetRasInfo(JNIEnv *env,
+                      SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo);
+void MTLSD_Unlock(JNIEnv *env,
+                  SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo);
+void MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops);
+void MTLSD_Delete(JNIEnv *env, BMTLSDOps *mtlsdo);
+jint MTLSD_NextPowerOfTwo(jint val, jint max);
+
+#endif /* MTLSurfaceDataBase_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLTextRenderer_h_Included
+#define MTLTextRenderer_h_Included
+
+#include <jni.h>
+#include <jlong.h>
+#include "sun_java2d_pipe_BufferedTextPipe.h"
+#include "MTLContext.h"
+#include "MTLSurfaceData.h"
+
+#define BYTES_PER_GLYPH_IMAGE \
+    sun_java2d_pipe_BufferedTextPipe_BYTES_PER_GLYPH_IMAGE
+#define BYTES_PER_GLYPH_POSITION \
+    sun_java2d_pipe_BufferedTextPipe_BYTES_PER_GLYPH_POSITION
+#define BYTES_PER_POSITIONED_GLYPH \
+    (BYTES_PER_GLYPH_IMAGE + BYTES_PER_GLYPH_POSITION)
+
+#define OFFSET_CONTRAST  sun_java2d_pipe_BufferedTextPipe_OFFSET_CONTRAST
+#define OFFSET_RGBORDER  sun_java2d_pipe_BufferedTextPipe_OFFSET_RGBORDER
+#define OFFSET_SUBPIXPOS sun_java2d_pipe_BufferedTextPipe_OFFSET_SUBPIXPOS
+#define OFFSET_POSITIONS sun_java2d_pipe_BufferedTextPipe_OFFSET_POSITIONS
+
+void MTLTR_EnableGlyphVertexCache(MTLContext *mtlc);
+void MTLTR_DisableGlyphVertexCache(MTLContext *mtlc);
+
+void MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, MTLSDOps *dstOps,
+                         jint totalGlyphs, jboolean usePositions,
+                         jboolean subPixPos, jboolean rgbOrder,
+                         jint lcdContrast,
+                         jfloat glyphListOrigX, jfloat glyphListOrigY,
+                         unsigned char *images, unsigned char *positions);
+
+#endif /* MTLTextRenderer_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,366 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+#include <limits.h>
+#include <math.h>
+#include <jlong.h>
+
+#include "sun_java2d_metal_MTLTextRenderer.h"
+
+#include "SurfaceData.h"
+#include "MTLContext.h"
+#include "MTLRenderQueue.h"
+#include "MTLTextRenderer.h"
+#include "MTLVertexCache.h"
+#include "AccelGlyphCache.h"
+
+/**
+ * The following constants define the inner and outer bounds of the
+ * accelerated glyph cache.
+ */
+#define MTLTR_CACHE_WIDTH       1024
+#define MTLTR_CACHE_HEIGHT      1024
+#define MTLTR_CACHE_CELL_WIDTH  64
+#define MTLTR_CACHE_CELL_HEIGHT 64
+
+/**
+ * The current "glyph mode" state.  This variable is used to track the
+ * codepath used to render a particular glyph.  This variable is reset to
+ * MODE_NOT_INITED at the beginning of every call to MTLTR_DrawGlyphList().
+ * As each glyph is rendered, the glyphMode variable is updated to reflect
+ * the current mode, so if the current mode is the same as the mode used
+ * to render the previous glyph, we can avoid doing costly setup operations
+ * each time.
+ */
+typedef enum {
+    MODE_NOT_INITED,
+    MODE_USE_CACHE_GRAY,
+    MODE_USE_CACHE_LCD,
+    MODE_NO_CACHE_GRAY,
+    MODE_NO_CACHE_LCD,
+    MODE_NO_CACHE_COLOR
+} GlyphMode;
+static GlyphMode glyphMode = MODE_NOT_INITED;
+
+/**
+ * There are two separate glyph caches: for AA and for LCD.
+ * Once one of them is initialized as either GRAY or LCD, it
+ * stays in that mode for the duration of the application.  It should
+ * be safe to use this one glyph cache for all screens in a multimon
+ * environment, since the glyph cache texture is shared between all contexts,
+ * and (in theory) OpenGL drivers should be smart enough to manage that
+ * texture across all screens.
+ */
+
+static GlyphCacheInfo *glyphCacheLCD = NULL;
+static GlyphCacheInfo *glyphCacheAA = NULL;
+
+/**
+ * The handle to the LCD text fragment program object.
+ */
+static GLhandleARB lcdTextProgram = 0;
+
+/**
+ * This value tracks the previous LCD contrast setting, so if the contrast
+ * value hasn't changed since the last time the gamma uniforms were
+ * updated (not very common), then we can skip updating the unforms.
+ */
+static jint lastLCDContrast = -1;
+
+/**
+ * This value tracks the previous LCD rgbOrder setting, so if the rgbOrder
+ * value has changed since the last time, it indicates that we need to
+ * invalidate the cache, which may already store glyph images in the reverse
+ * order.  Note that in most real world applications this value will not
+ * change over the course of the application, but tests like Font2DTest
+ * allow for changing the ordering at runtime, so we need to handle that case.
+ */
+static jboolean lastRGBOrder = JNI_TRUE;
+
+/**
+ * This constant defines the size of the tile to use in the
+ * MTLTR_DrawLCDGlyphNoCache() method.  See below for more on why we
+ * restrict this value to a particular size.
+ */
+#define MTLTR_NOCACHE_TILE_SIZE 64
+
+/**
+ * These constants define the size of the "cached destination" texture.
+ * This texture is only used when rendering LCD-optimized text, as that
+ * codepath needs direct access to the destination.  There is no way to
+ * access the framebuffer directly from an OpenGL shader, so we need to first
+ * copy the destination region corresponding to a particular glyph into
+ * this cached texture, and then that texture will be accessed inside the
+ * shader.  Copying the destination into this cached texture can be a very
+ * expensive operation (accounting for about half the rendering time for
+ * LCD text), so to mitigate this cost we try to bulk read a horizontal
+ * region of the destination at a time.  (These values are empirically
+ * derived for the common case where text runs horizontally.)
+ *
+ * Note: It is assumed in various calculations below that:
+ *     (MTLTR_CACHED_DEST_WIDTH  >= MTLTR_CACHE_CELL_WIDTH)  &&
+ *     (MTLTR_CACHED_DEST_WIDTH  >= MTLTR_NOCACHE_TILE_SIZE) &&
+ *     (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_CACHE_CELL_HEIGHT) &&
+ *     (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_NOCACHE_TILE_SIZE)
+ */
+#define MTLTR_CACHED_DEST_WIDTH  1024
+#define MTLTR_CACHED_DEST_HEIGHT (MTLTR_CACHE_CELL_HEIGHT * 2)
+
+/**
+ * The handle to the "cached destination" texture object.
+ */
+static GLuint cachedDestTextureID = 0;
+
+/**
+ * The current bounds of the "cached destination" texture, in destination
+ * coordinate space.  The width/height of these bounds will not exceed the
+ * MTLTR_CACHED_DEST_WIDTH/HEIGHT values defined above.  These bounds are
+ * only considered valid when the isCachedDestValid flag is JNI_TRUE.
+ */
+static SurfaceDataBounds cachedDestBounds;
+
+/**
+ * This flag indicates whether the "cached destination" texture contains
+ * valid data.  This flag is reset to JNI_FALSE at the beginning of every
+ * call to MTLTR_DrawGlyphList().  Once we copy valid destination data
+ * into the cached texture, this flag is set to JNI_TRUE.  This way, we can
+ * limit the number of times we need to copy destination data, which is a
+ * very costly operation.
+ */
+static jboolean isCachedDestValid = JNI_FALSE;
+
+/**
+ * The bounds of the previously rendered LCD glyph, in destination
+ * coordinate space.  We use these bounds to determine whether the glyph
+ * currently being rendered overlaps the previously rendered glyph (i.e.
+ * its bounding box intersects that of the previously rendered glyph).  If
+ * so, we need to re-read the destination area associated with that previous
+ * glyph so that we can correctly blend with the actual destination data.
+ */
+static SurfaceDataBounds previousGlyphBounds;
+
+/**
+ * Initializes the one glyph cache (texture and data structure).
+ * If lcdCache is JNI_TRUE, the texture will contain RGB data,
+ * otherwise we will simply store the grayscale/monochrome glyph images
+ * as intensity values (which work well with the GL_MODULATE function).
+ */
+static jboolean
+MTLTR_InitGlyphCache(jboolean lcdCache)
+{
+    //TODO
+
+    return JNI_TRUE;
+}
+
+/**
+ * Adds the given glyph to the glyph cache (texture and data structure)
+ * associated with the given MTLContext.
+ */
+static void
+MTLTR_AddTmTLyphCache(GlyphInfo *glyph, GLenum pixelFormat)
+{
+    //TODO
+
+    CacheCellInfo *ccinfo;
+    GlyphCacheInfo *gcinfo;
+
+    J2dTraceLn(J2D_TRACE_INFO, "MTLTR_AddTmTLyphCache");
+    //J2dTracePrimitive("MTLTR_InitGlyphCache");
+}
+
+/**
+ * (Re)Initializes the gamma related uniforms.
+ *
+ * The given contrast value is an int in the range [100, 250] which we will
+ * then scale to fit in the range [1.0, 2.5].
+ */
+static jboolean
+MTLTR_UpdateLCDTextContrast(jint contrast)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+/**
+ * Updates the current gamma-adjusted source color ("src_adj") of the LCD
+ * text shader program.  Note that we could calculate this value in the
+ * shader (e.g. just as we do for "dst_adj"), but would be unnecessary work
+ * (and a measurable performance hit, maybe around 5%) since this value is
+ * constant over the entire glyph list.  So instead we just calculate the
+ * gamma-adjusted value once and update the uniform parameter of the LCD
+ * shader as needed.
+ */
+static jboolean
+MTLTR_UpdateLCDTextColor(jint contrast)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+/**
+ * Enables the LCD text shader and updates any related state, such as the
+ * gamma lookup table textures.
+ */
+static jboolean
+MTLTR_EnableLCDGlyphModeState(GLuint glyphTextureID,
+                              GLuint dstTextureID,
+                              jint contrast)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+void
+MTLTR_EnableGlyphVertexCache(MTLContext *mtlc)
+{
+    //TODO
+}
+
+void
+MTLTR_DisableGlyphVertexCache(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DisableGlyphVertexCache");
+
+}
+
+/**
+ * Disables any pending state associated with the current "glyph mode".
+ */
+void
+MTLTR_DisableGlyphModeState()
+{
+    //TODO
+    J2dTraceLn1(J2D_TRACE_VERBOSE,
+                "MTLTR_DisableGlyphModeState: mode=%d", glyphMode);
+}
+
+static jboolean
+MTLTR_DrawGrayscaleGlyphViaCache(MTLContext *mtlc,
+                                 GlyphInfo *ginfo, jint x, jint y)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+/**
+ * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 is
+ * inside outerBounds.
+ */
+#define INSIDE(gx1, gy1, gx2, gy2, outerBounds) \
+    (((gx1) >= outerBounds.x1) && ((gy1) >= outerBounds.y1) && \
+     ((gx2) <= outerBounds.x2) && ((gy2) <= outerBounds.y2))
+
+/**
+ * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 intersects
+ * the rectangle defined by bounds.
+ */
+#define INTERSECTS(gx1, gy1, gx2, gy2, bounds) \
+    ((bounds.x2 > (gx1)) && (bounds.y2 > (gy1)) && \
+     (bounds.x1 < (gx2)) && (bounds.y1 < (gy2)))
+
+/**
+ * This method checks to see if the given LCD glyph bounds fall within the
+ * cached destination texture bounds.  If so, this method can return
+ * immediately.  If not, this method will copy a chunk of framebuffer data
+ * into the cached destination texture and then update the current cached
+ * destination bounds before returning.
+ */
+static void
+MTLTR_UpdateCachedDestination(MTLSDOps *dstOps, GlyphInfo *ginfo,
+                              jint gx1, jint gy1, jint gx2, jint gy2,
+                              jint glyphIndex, jint totalGlyphs)
+{
+    //TODO
+}
+
+static jboolean
+MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, MTLSDOps *dstOps,
+                           GlyphInfo *ginfo, jint x, jint y,
+                           jint glyphIndex, jint totalGlyphs,
+                           jboolean rgbOrder, jint contrast,
+                           jint dstTextureID, jboolean * opened)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+static jboolean
+MTLTR_DrawGrayscaleGlyphNoCache(MTLContext *mtlc,
+                                GlyphInfo *ginfo, jint x, jint y)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+static jboolean
+MTLTR_DrawLCDGlyphNoCache(MTLContext *mtlc, MTLSDOps *dstOps,
+                          GlyphInfo *ginfo, jint x, jint y,
+                          jint rowBytesOffset,
+                          jboolean rgbOrder, jint contrast,
+                          jint dstTextureID)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+static jboolean
+MTLTR_DrawColorGlyphNoCache(MTLContext *mtlc, GlyphInfo *ginfo, jint x, jint y)
+{
+    //TODO
+    return JNI_TRUE;
+}
+
+
+// see DrawGlyphList.c for more on this macro...
+#define FLOOR_ASSIGN(l, r) \
+    if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r))
+
+void
+MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, MTLSDOps *dstOps,
+                    jint totalGlyphs, jboolean usePositions,
+                    jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
+                    jfloat glyphListOrigX, jfloat glyphListOrigY,
+                    unsigned char *images, unsigned char *positions)
+{
+    //TODO
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_metal_MTLTextRenderer_drawGlyphList
+    (JNIEnv *env, jobject self,
+     jint numGlyphs, jboolean usePositions,
+     jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
+     jfloat glyphListOrigX, jfloat glyphListOrigY,
+     jlongArray imgArray, jfloatArray posArray)
+{
+    //TODO
+}
+
+#endif /* !HEADLESS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexturePool.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,37 @@
+#ifndef MTLTexturePool_h_Included
+#define MTLTexturePool_h_Included
+#import <Metal/Metal.h>
+
+@interface MTLTexturePoolItem : NSObject
+{
+@private
+
+id<MTLTexture> texture;
+bool isBusy;
+}
+
+@property (readwrite, retain) id<MTLTexture> texture;
+@property (readwrite, assign) bool isBusy;
+
+- (id) initWithTexture:(id<MTLTexture>)tex;
+@end
+
+// NOTE: owns all MTLTexture objects
+@interface MTLTexturePool : NSObject
+{
+@private
+
+id<MTLDevice> device;
+NSMutableArray<MTLTexturePoolItem*> * pool;
+}
+
+@property (readwrite, assign) id<MTLDevice> device;
+@property (readwrite, retain) NSMutableArray<MTLTexturePoolItem*> * pool;
+
+- (id) initWithDevice:(id<MTLDevice>)device;
+- (id<MTLTexture>) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format;
+- (void) markTextureFree:(id<MTLTexture>)texture;
+- (void) markAllTexturesFree;
+@end
+
+#endif /* MTLTexturePool_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,92 @@
+#import "MTLTexturePool.h"
+#import "Trace.h"
+
+@implementation MTLTexturePoolItem
+
+@synthesize texture;
+@synthesize isBusy;
+
+- (id) initWithTexture:(id<MTLTexture>)tex {
+    self = [super init];
+    if (self == nil) return self;
+    self.texture = tex;
+    isBusy = NO;
+    return self;
+}
+@end
+
+@implementation MTLTexturePool
+
+@synthesize device;
+@synthesize pool;
+
+- (id) initWithDevice:(id<MTLDevice>)dev {
+    self = [super init];
+    if (self == nil) return self;
+
+    self.device = dev;
+    self.pool = [NSMutableArray arrayWithCapacity:10];
+    return self;
+}
+
+// NOTE: called from RQ-thread (on blit operations)
+- (id<MTLTexture>) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format {
+    @synchronized (self) {
+        // 1. find free item
+        // TODO: optimize search, use Map<(w,h,pf), TexPoolItem>
+        const int count = [self.pool count];
+        for (int c = 0; c < count; ++c) {
+            MTLTexturePoolItem *tpi = [self.pool objectAtIndex:c];
+            if (tpi == nil)
+                continue;
+            // TODO: use checks tpi.texture.width <= width && tpi.texture.height <= height
+            if (tpi.texture.width == width && tpi.texture.height == height && tpi.texture.pixelFormat == format &&
+                !tpi.isBusy) {
+                tpi.isBusy = YES;
+                return tpi.texture;
+            }
+        }
+
+        // 2. create
+        MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format width:width height:height mipmapped:NO];
+        id <MTLTexture> tex = [self.device newTextureWithDescriptor:textureDescriptor];
+        MTLTexturePoolItem *tpi = [[MTLTexturePoolItem alloc] initWithTexture:tex];
+        [self.pool addObject:tpi];
+        J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLTexturePool: created pool item: tex=%p, w=%d h=%d, pf=%d", tex, width, height, format);
+        return tpi.texture;
+    }
+};
+
+// NOTE: called from completion-handler (pooled thread)
+- (void) markTextureFree:(id<MTLTexture>)texture {
+    // TODO: optimize search, use Map<(w,h,pf), TexPoolItem>
+    @synchronized (self) {
+        const int count = [self.pool count];
+        for (int c = 0; c < count; ++c) {
+            MTLTexturePoolItem * tpi = [self.pool objectAtIndex:c];
+            if (tpi == nil)
+                continue;
+            if (tpi.texture == texture) {
+                tpi.isBusy = NO;
+                return;
+            }
+        }
+        J2dTraceLn1(J2D_TRACE_ERROR, "MTLTexturePool: can't find item with texture %p", texture);
+    }
+}
+
+// NOTE: called from completion-handler (pooled thread)
+- (void) markAllTexturesFree {
+    @synchronized (self) {
+        const int count = [self.pool count];
+        for (int c = 0; c < count; ++c) {
+            MTLTexturePoolItem *tpi = [self.pool objectAtIndex:c];
+            if (tpi == nil)
+                continue;
+            tpi.isBusy = NO;
+        }
+    }
+}
+
+
+@end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLUtils.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,6 @@
+#ifndef MTLUtils_h_Included
+#define MTLUtils_h_Included
+
+#import <Metal/Metal.h>
+
+#endif /* MTLUtils_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLUtils.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,47 @@
+#include "MTLUtils.h"
+
+#include <jni.h>
+#include <simd/simd.h>
+#include "common.h"
+#include "Trace.h"
+
+extern void J2dTraceImpl(int level, jboolean cr, const char *string, ...);
+void J2dTraceTraceVector(simd_float4 pt) {
+    J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, "[%lf %lf %lf %lf]", pt.x, pt.y, pt.z, pt.w);
+}
+
+void checkTransform(float * position, simd_float4x4 transform4x4) {
+    J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, "check transform: ");
+
+    simd_float4 fpt = simd_make_float4(position[0], position[1], position[2], 1.f);
+    simd_float4 fpt_trans = simd_mul(transform4x4, fpt);
+    J2dTraceTraceVector(fpt);
+    J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, "  ===>>>  ");
+    J2dTraceTraceVector(fpt_trans);
+    J2dTraceLn(J2D_TRACE_VERBOSE, " ");
+}
+
+static void traceMatrix(simd_float4x4 * mtx) {
+    for (int row = 0; row < 4; ++row) {
+        J2dTraceLn4(J2D_TRACE_VERBOSE, "  [%lf %lf %lf %lf]",
+                    mtx->columns[0][row], mtx->columns[1][row], mtx->columns[2][row], mtx->columns[3][row]);
+    }
+}
+
+void traceRaster(char * p, int width, int height, int stride) {
+    for (int y = 0; y < height; ++y) {
+        for (int x = 0; x < width; ++x) {
+            char pix0 = p[y*stride + x*4];
+            char pix1 = p[y*stride + x*4 + 1];
+            char pix2 = p[y*stride + x*4 + 2];
+            char pix3 = p[y*stride + x*4 + 3];
+            J2dTrace4(J2D_TRACE_INFO, "[%d,%d,%d,%d], ", pix0, pix1, pix2, pix3);
+        }
+        J2dTraceLn(J2D_TRACE_INFO, "");
+    }
+}
+
+void tracePoints(jint nPoints, jint *xPoints, jint *yPoints) {
+    for (int i = 0; i < nPoints; i++)
+        J2dTraceLn2(J2D_TRACE_INFO, "\t(%d, %d)", *(xPoints++), *(yPoints++));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.h	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef MTLVertexCache_h_Included
+#define MTLVertexCache_h_Included
+
+#include "j2d_md.h"
+#include "MTLContext.h"
+
+/**
+ * Constants that control the size of the vertex cache.
+ */
+#define MTLVC_MAX_INDEX         1024
+
+/**
+ * Constants that control the size of the texture tile cache used for
+ * mask operations.
+ */
+#define MTLVC_MASK_CACHE_TILE_WIDTH       32
+#define MTLVC_MASK_CACHE_TILE_HEIGHT      32
+#define MTLVC_MASK_CACHE_TILE_SIZE \
+   (MTLVC_MASK_CACHE_TILE_WIDTH * MTLVC_MASK_CACHE_TILE_HEIGHT)
+
+#define MTLVC_MASK_CACHE_WIDTH_IN_TILES   8
+#define MTLVC_MASK_CACHE_HEIGHT_IN_TILES  4
+
+#define MTLVC_MASK_CACHE_WIDTH_IN_TEXELS \
+   (MTLVC_MASK_CACHE_TILE_WIDTH * MTLVC_MASK_CACHE_WIDTH_IN_TILES)
+#define MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS \
+   (MTLVC_MASK_CACHE_TILE_HEIGHT * MTLVC_MASK_CACHE_HEIGHT_IN_TILES)
+
+/*
+ * We reserve one (fully opaque) tile in the upper-right corner for
+ * operations where the mask is null.
+ */
+#define MTLVC_MASK_CACHE_MAX_INDEX \
+   ((MTLVC_MASK_CACHE_WIDTH_IN_TILES * MTLVC_MASK_CACHE_HEIGHT_IN_TILES) - 1)
+#define MTLVC_MASK_CACHE_SPECIAL_TILE_X \
+   (MTLVC_MASK_CACHE_WIDTH_IN_TEXELS - MTLVC_MASK_CACHE_TILE_WIDTH)
+#define MTLVC_MASK_CACHE_SPECIAL_TILE_Y \
+   (MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS - MTLVC_MASK_CACHE_TILE_HEIGHT)
+
+/**
+ * Exported methods.
+ */
+jboolean MTLVertexCache_InitVertexCache(MTLContext *mtlc);
+void MTLVertexCache_FlushVertexCache();
+void MTLVertexCache_RestoreColorState(MTLContext *mtlc);
+
+void MTLVertexCache_EnableMaskCache(MTLContext *mtlc);
+void MTLVertexCache_DisableMaskCache(MTLContext *mtlc);
+void MTLVertexCache_AddMaskQuad(MTLContext *mtlc,
+                                jint srcx, jint srcy,
+                                jint dstx, jint dsty,
+                                jint width, jint height,
+                                jint maskscan, void *mask);
+
+void MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
+                                 jfloat tx1, jfloat ty1,
+                                 jfloat tx2, jfloat ty2,
+                                 jfloat dx1, jfloat dy1,
+                                 jfloat dx2, jfloat dy2);
+
+#endif /* MTLVertexCache_h_Included */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m	Fri Jun 21 12:08:37 2019 +0530
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#ifndef HEADLESS
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "sun_java2d_SunGraphics2D.h"
+
+#include "MTLPaints.h"
+#include "MTLVertexCache.h"
+
+typedef struct _J2DVertex {
+    jfloat tx, ty;
+    jubyte r, g, b, a;
+    jfloat dx, dy;
+} J2DVertex;
+
+static J2DVertex *vertexCache = NULL;
+static jint vertexCacheIndex = 0;
+
+static jint maskCacheTexID = 0;
+static jint maskCacheIndex = 0;
+
+#define MTLVC_ADD_VERTEX(TX, TY, R, G, B, A, DX, DY) \
+    do { \
+        J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
+        v->tx = TX; \
+        v->ty = TY; \
+        v->r  = R;  \
+        v->g  = G;  \
+        v->b  = B;  \
+        v->a  = A;  \
+        v->dx = DX; \
+        v->dy = DY; \
+    } while (0)
+
+#define MTLVC_ADD_QUAD(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2, R, G, B, A) \
+    do { \
+        MTLVC_ADD_VERTEX(TX1, TY1, R, G, B, A, DX1, DY1); \
+        MTLVC_ADD_VERTEX(TX2, TY1, R, G, B, A, DX2, DY1); \
+        MTLVC_ADD_VERTEX(TX2, TY2, R, G, B, A, DX2, DY2); \
+        MTLVC_ADD_VERTEX(TX1, TY2, R, G, B, A, DX1, DY2); \
+    } while (0)
+
+jboolean
+MTLVertexCache_InitVertexCache(MTLContext *mtlc)
+{
+    //TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitVertexCache");
+    return JNI_TRUE;
+}
+
+void
+MTLVertexCache_FlushVertexCache()
+{
+    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache");
+    vertexCacheIndex = 0;
+}
+
+/**
+ * This method is somewhat hacky, but necessary for the foreseeable future.
+ * The problem is the way OpenGL handles color values in vertex arrays.  When
+ * a vertex in a vertex array contains a color, and then the vertex array
+ * is rendered via glDrawArrays(), the global OpenGL color state is actually
+ * modified each time a vertex is rendered.  This means that after all
+ * vertices have been flushed, the global OpenGL color state will be set to
+ * the color of the most recently rendered element in the vertex array.
+ *
+ * The reason this is a problem for us is that we do not want to flush the
+ * vertex array (in the case of mask/glyph operations) or issue a glEnd()
+ * (in the case of non-antialiased primitives) everytime the current color
+ * changes, which would defeat any benefit from batching in the first place.
+ * We handle this in practice by not calling CHECK/RESET_PREVIOUS_OP() when
+ * the simple color state is changing in MTLPaints_SetColor().  This is
+ * problematic for vertex caching because we may end up with the following
+ * situation, for example:
+ *   SET_COLOR (orange)
+ *   MASK_FILL
+ *   MASK_FILL
+ *   SET_COLOR (blue; remember, this won't cause a flush)
+ *   FILL_RECT (this will cause the vertex array to be flushed)
+ *
+ * In this case, we would actually end up rendering an orange FILL_RECT,
+ * not a blue one as intended, because flushing the vertex cache flush would
+ * override the color state from the most recent SET_COLOR call.
+ *
+ * Long story short, the easiest way to resolve this problem is to call
+ * this method just after disabling the mask/glyph cache, which will ensure
+ * that the appropriate color state is restored.
+ */
+void
+MTLVertexCache_RestoreColorState(MTLContext *mtlc)
+{
+    // TODO
+    if (mtlc.paintState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) {
+        [mtlc setColor:mtlc.pixel];
+    }
+}
+
+static jboolean
+MTLVertexCache_InitMaskCache()
+{
+    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitMaskCache");
+    return JNI_TRUE;
+}
+
+void
+MTLVertexCache_EnableMaskCache(MTLContext *mtlc)
+{
+    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_EnableMaskCache");
+}
+
+void
+MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
+{
+    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache");
+    maskCacheIndex = 0;
+}
+
+void
+MTLVertexCache_AddMaskQuad(MTLContext *mtlc,
+                           jint srcx, jint srcy,
+                           jint dstx, jint dsty,
+                           jint width, jint height,
+                           jint maskscan, void *mask)
+{
+    // TODO
+}
+
+void
+MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
+                            jfloat tx1, jfloat ty1, jfloat tx2, jfloat ty2,
+                            jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2)
+{
+    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphQuad");
+}
+
+#endif /* !HEADLESS */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalGraphicsConfig.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,454 +0,0 @@
-/*
- * 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;
-}*/
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalLayer.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,385 +0,0 @@
-/*
- * 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);
-}
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * 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*/
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderQueue.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,832 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalRenderer.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,514 +0,0 @@
-/*
- * 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
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MetalSurfaceData.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,532 +0,0 @@
-/*
- * 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;
-}
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * 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
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/VertexDataManager.m	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/BaseShader.metal	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * 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;
-}
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders/MetalShaderTypes.h	Mon Jun 10 14:13:09 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-// 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 */