diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java
index 4481b6b3ce..04ece49a74 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java
@@ -572,7 +572,20 @@ public final class QuantumToolkit extends Toolkit {
         pulse(true);
     }
 
+    long lastUpdate;
+    long calcVsync = 13333333L;
+
     void pulse(boolean collect) {
+        if (isVsyncEnabled()) {
+            if (lastUpdate == 0 || lastUpdate + calcVsync > System.nanoTime()) {
+                runInRenderThreadAndWait(()->{
+                    pipeline.vsync();
+                    lastUpdate = System.nanoTime();
+                });
+            } else {
+                lastUpdate = System.nanoTime();
+            }
+        }
         try {
             inPulse++;
             if (PULSE_LOGGING_ENABLED) {
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/GraphicsPipeline.java b/modules/javafx.graphics/src/main/java/com/sun/prism/GraphicsPipeline.java
index 48cc62d85f..120eac624f 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/GraphicsPipeline.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/GraphicsPipeline.java
@@ -116,6 +116,9 @@ public abstract class GraphicsPipeline {
 
     public abstract boolean isVsyncSupported();
 
+    public void vsync() {
+    }
+
     /**
      * Returns true iff the graphics objects from this pipeline support
      * the indicated {@link ShaderType}.
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Pipeline.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Pipeline.java
index e0601840e9..3d1e8dc083 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Pipeline.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Pipeline.java
@@ -211,6 +211,13 @@ public class ES2Pipeline extends GraphicsPipeline {
         return true;
     }
 
+    @Override
+    public void vsync() {
+        if (getDeviceDetails().get("contextPtr") instanceof GLContext syncContext) {
+            syncContext.waitVideoSync(1, 0);
+        }
+    }
+
     @Override
     public boolean supportsShaderType(ShaderType type) {
         switch (type) {
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java
index b7b074d72b..f680fa1b15 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java
@@ -184,7 +184,7 @@ class ES2SwapChain implements ES2RenderTarget, Presentable, GraphicsResource {
     @Override
     public boolean present() {
         boolean presented = drawable.swapBuffers(context.getGLContext());
-        context.makeCurrent(null);
+        //context.makeCurrent(null);
         return presented;
     }
 
@@ -308,6 +308,7 @@ class ES2SwapChain implements ES2RenderTarget, Presentable, GraphicsResource {
         }
 
         if (drawable != null) {
+            context.makeCurrent(null);
             drawable.dispose();
             drawable = null;
         }
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
index 1bcf9dbc68..71dcfe2bc6 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
@@ -529,6 +529,10 @@ abstract class GLContext {
 
     abstract void makeCurrent(GLDrawable drawable);
 
+	int waitVideoSync(int divisor, int remainder) {
+		return 0;
+	}
+
     void pixelStorei(int pname, int param) {
         nPixelStorei(pname, param);
     }
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLContext.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLContext.java
index 4d8b54bb6d..9dd00ca39d 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLContext.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLContext.java
@@ -33,6 +33,7 @@ class X11GLContext extends GLContext {
             boolean vSyncRequest);
     private static native long nGetNativeHandle(long nativeCtxInfo);
     private static native void nMakeCurrent(long nativeCtxInfo, long nativeDInfo);
+    private static native int nWaitVideoSync(long nativeCtxInfo, int divisor, int remainder);
 
     X11GLContext(long nativeCtxInfo) {
         this.nativeCtxInfo = nativeCtxInfo;
@@ -68,4 +69,9 @@ class X11GLContext extends GLContext {
     void makeCurrent(GLDrawable drawable) {
         nMakeCurrent(nativeCtxInfo, drawable.getNativeDrawableInfo());
     }
+
+    @Override
+    int waitVideoSync(int divisor, int remainder) {
+        return nWaitVideoSync(nativeCtxInfo, divisor, remainder);
+    }
 }
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLFactory.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLFactory.java
index 10ad94a691..f167a6e17a 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLFactory.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/X11GLFactory.java
@@ -111,7 +111,13 @@ class X11GLFactory extends GLFactory {
     GLContext createGLContext(GLDrawable drawable, GLPixelFormat pixelFormat,
             GLContext shareCtx, boolean vSyncRequest) {
         // No need to pass down shareCtx as we don't use shared ctx on X11
-        return new X11GLContext(drawable, pixelFormat, vSyncRequest);
+        X11GLContext prismCtx = new X11GLContext(drawable, pixelFormat, vSyncRequest);
+
+        // This is only used for glXWaitVideoSyncSGI
+        HashMap deviceDetails = (HashMap) ES2Pipeline.getInstance().getDeviceDetails();
+        deviceDetails.put("contextPtr", prismCtx);
+
+        return prismCtx;
     }
 
     @Override
@@ -171,4 +177,4 @@ class X11GLFactory extends GLFactory {
         deviceDetails.put("XDisplay", Long.valueOf(nGetDisplay(nativeCtxInfo)));
         deviceDetails.put("XScreenID", Integer.valueOf(nGetDefaultScreen(nativeCtxInfo)));
     }
-}
+}
\ No newline at end of file
diff --git a/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h b/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
index aa43478e35..2b5289f2da 100644
--- a/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
+++ b/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
@@ -263,6 +263,8 @@ struct ContextInfoRec {
 #ifdef UNIX /* LINUX || SOLARIS */
     char *glxExtensionStr;
     PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
+    PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI;
+    PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI;
 #endif /* LINUX || SOLARIS */
 
     /* gl function pointers */
diff --git a/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLContext.c b/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLContext.c
index fde0bf5745..2a75b60ca5 100644
--- a/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLContext.c
+++ b/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLContext.c
@@ -278,7 +278,23 @@ JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_X11GLContext_nInitialize
             ctxInfo->glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
                 glXGetProcAddress((const GLubyte *)"glXSwapIntervalSGI");
         }
+    }
+
+    if (isExtensionSupported(ctxInfo->glxExtensionStr,
+            "GLX_SGI_video_sync")) {
+        ctxInfo->glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)
+                dlsym(RTLD_DEFAULT, "glXGetVideoSyncSGI");
+        ctxInfo->glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)
+                dlsym(RTLD_DEFAULT, "glXWaitVideoSyncSGI");
 
+        if (ctxInfo->glXGetVideoSyncSGI == NULL) {
+            ctxInfo->glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)
+                glXGetProcAddress((const GLubyte *)"glXGetVideoSyncSGI");
+        }
+        if (ctxInfo->glXWaitVideoSyncSGI == NULL) {
+            ctxInfo->glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)
+                glXGetProcAddress((const GLubyte *)"glXWaitVideoSyncSGI");
+        }
     }
 
     // initialize platform states and properties to match
@@ -286,6 +302,11 @@ JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_X11GLContext_nInitialize
     if (ctxInfo->glXSwapIntervalSGI != NULL) {
         ctxInfo->glXSwapIntervalSGI(0);
     }
+    if (ctxInfo->glXGetVideoSyncSGI != NULL) {
+        unsigned int count;
+        ctxInfo->glXGetVideoSyncSGI(&count);
+    }
+
     ctxInfo->state.vSyncEnabled = JNI_FALSE;
     ctxInfo->vSyncRequested = vSyncRequested;
 
@@ -324,7 +345,7 @@ JNIEXPORT void JNICALL Java_com_sun_prism_es2_X11GLContext_nMakeCurrent
     jboolean vSyncNeeded;
 
     if (!glXMakeCurrent(ctxInfo->display, dInfo->win, ctxInfo->context)) {
-        fprintf(stderr, "Failed in glXMakeCurrent");
+        fprintf(stderr, "Failed in glXMakeCurrent\n");
     }
 
     vSyncNeeded = ctxInfo->vSyncRequested && dInfo->onScreen;
@@ -337,3 +358,24 @@ JNIEXPORT void JNICALL Java_com_sun_prism_es2_X11GLContext_nMakeCurrent
         ctxInfo->glXSwapIntervalSGI(interval);
     }
 }
+
+/*
+ * Class:     com_sun_prism_es2_X11GLContext
+ * Method:    nWaitVideoSync
+ * Signature: I(JII)V
+ */
+JNIEXPORT jint JNICALL Java_com_sun_prism_es2_X11GLContext_nWaitVideoSync
+(JNIEnv *env, jclass class, jlong nativeCtxInfo, jint divisor, jint remainder) {
+    ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
+    unsigned int count = 0;
+
+    if (ctxInfo->state.vSyncEnabled && ctxInfo->glXWaitVideoSyncSGI != NULL) {
+        int res;
+
+        if ((res = ctxInfo->glXWaitVideoSyncSGI(divisor, remainder, &count))) {
+            fprintf(stderr, "Failed in glXWaitVideoSync: %d\n", res);
+        }
+    }
+
+    return count;
+}
diff --git a/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLFactory.c b/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLFactory.c
index 07e5d57df7..77e3aa745e 100644
--- a/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLFactory.c
+++ b/modules/javafx.graphics/src/main/native-prism-es2/x11/X11GLFactory.c
@@ -156,6 +156,7 @@ static int x11errorhit = 0;
 static int x11errorDetector (Display *dpy, XErrorEvent *error)
 {
     x11errorhit = JNI_TRUE;
+    return 0;
 }
 
 /*
