diff --git a/interface/src/ui/ResourceImageItem.cpp b/interface/src/ui/ResourceImageItem.cpp
index 6a5f4a431c..9051305a2e 100644
--- a/interface/src/ui/ResourceImageItem.cpp
+++ b/interface/src/ui/ResourceImageItem.cpp
@@ -10,11 +10,15 @@
 
 #include "Application.h"
 #include "ResourceImageItem.h"
+
 #include <QOpenGLFramebufferObjectFormat>
+#include <QOpenGLFunctions>
+#include <QOpenGLExtraFunctions>
+#include <QOpenGLContext>
+
 #include <DependencyManager.h>
 #include <TextureCache.h>
 
-
 ResourceImageItem::ResourceImageItem(QQuickItem* parent) : QQuickFramebufferObject(parent) {
     connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
 }
@@ -55,26 +59,49 @@ void ResourceImageItemRenderer::synchronize(QQuickFramebufferObject* item) {
     }
 
     _window = resourceImageItem->window();
+    _window->setClearBeforeRendering(true);
     if (_ready && !_url.isNull() && !_url.isEmpty() && (urlChanged || readyChanged || !_networkTexture)) {
         _networkTexture = DependencyManager::get<TextureCache>()->getTexture(_url);
     }
 
     if (_ready && _networkTexture && _networkTexture->isLoaded()) {
         if(_fboMutex.tryLock()) {
-            qApp->getActiveDisplayPlugin()->copyTextureToQuickFramebuffer(_networkTexture, framebufferObject());
+            qApp->getActiveDisplayPlugin()->copyTextureToQuickFramebuffer(_networkTexture, _copyFbo, &_fenceSync);
             _fboMutex.unlock();
         }
     }
+    glFlush();
+
 }
 
 QOpenGLFramebufferObject* ResourceImageItemRenderer::createFramebufferObject(const QSize& size) {
     QOpenGLFramebufferObjectFormat format;
     format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+    _copyFbo = new QOpenGLFramebufferObject(size, format);
     return new QOpenGLFramebufferObject(size, format);
 }
 
 void ResourceImageItemRenderer::render() {
+    qDebug() << "initial error" << glGetError();
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
+    QOpenGLExtraFunctions* extras = QOpenGLContext::currentContext()->extraFunctions();
     _fboMutex.lock();
-    _window->resetOpenGLState();
+    if (_fenceSync) {
+        extras->glWaitSync(_fenceSync, 0, GL_TIMEOUT_IGNORED);
+        qDebug() << "wait error" << glGetError();
+        qDebug() << "waited on fence";
+    }
+    if (_ready) {
+        QOpenGLFramebufferObject::blitFramebuffer(framebufferObject(), _copyFbo, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+        /*f->glBindTexture(GL_TEXTURE_2D, _copyFbo->texture());
+        qDebug() << "bind tex error" << f->glGetError() << "texture" << _copyFbo->texture();
+        f->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _copyFbo->width(), _copyFbo->height());*/
+        qDebug() << "copy error" << f->glGetError();
+    } else {
+        framebufferObject()->release();
+    }
     _fboMutex.unlock();
+    update();
 }
diff --git a/interface/src/ui/ResourceImageItem.h b/interface/src/ui/ResourceImageItem.h
index bf3c44e205..9b1d685ee1 100644
--- a/interface/src/ui/ResourceImageItem.h
+++ b/interface/src/ui/ResourceImageItem.h
@@ -27,8 +27,9 @@ private:
 
     NetworkTexturePointer _networkTexture;
     QQuickWindow* _window;
-    QOpenGLFramebufferObject* _copyFbo;
     QMutex _fboMutex;
+    QOpenGLFramebufferObject* _copyFbo;
+    GLsync _fenceSync { 0 };
 };
 
 class ResourceImageItem : public QQuickFramebufferObject {
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
index 6050211eba..e028fd14c1 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp
@@ -823,32 +823,37 @@ void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
     }
 }
 
-void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target) {
+void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) {
     auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
     withMainThreadContext([&] {
         GLuint sourceTexture = glBackend->getTextureID(networkTexture->getGPUTexture());
         GLuint targetTexture = target->texture();
         GLuint fbo[2] {0, 0};
-
+        qDebug() << "initial" << glGetError();
         // need mipmaps for blitting texture
         glGenerateTextureMipmap(sourceTexture);
 
         // create 2 fbos (one for initial texture, second for scaled one)
         glCreateFramebuffers(2, fbo);
+        qDebug() << "error" << glGetError();
 
         // setup source fbo
         glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture, 0);
+        qDebug() << "error" << glGetError();
 
         // setup destination fbo
         glBindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture, 0);
+        qDebug() << "error" << glGetError();
 
         glBlitNamedFramebuffer(fbo[0], fbo[1], 0, 0, networkTexture->getWidth(), networkTexture->getHeight(), 0, 0, target->width(), target->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
+        qDebug() << "error" << glGetError();
 
         // don't delete the textures!
         glDeleteFramebuffers(2, fbo);
-        glFinish();
+        qDebug() << "error" << glGetError();
+        *fenceSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
     });
 }
 
diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
index d9e810bf97..dc2e251d65 100644
--- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h
@@ -79,7 +79,7 @@ public:
     // Three threads, one for rendering, one for texture transfers, one reserved for the GL driver
     int getRequiredThreadCount() const override { return 3; }
 
-    void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target);
+    void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync);
 
 protected:
     friend class PresentThread;
diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h
index e9b31b5c35..481a2609fc 100644
--- a/libraries/plugins/src/plugins/DisplayPlugin.h
+++ b/libraries/plugins/src/plugins/DisplayPlugin.h
@@ -63,6 +63,7 @@ namespace gpu {
 
 class NetworkTexture;
 using NetworkTexturePointer = QSharedPointer<NetworkTexture>;
+typedef struct __GLsync *GLsync;
 
 // Stereo display functionality
 // TODO move out of this file don't derive DisplayPlugin from this.  Instead use dynamic casting when
@@ -212,7 +213,7 @@ public:
     // Hardware specific stats
     virtual QJsonObject getHardwareStats() const { return QJsonObject(); }
 
-    virtual void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target) = 0;
+    virtual void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) = 0;
 
     uint32_t presentCount() const { return _presentedFrameIndex; }
     // Time since last call to incrementPresentCount (only valid if DEBUG_PAINT_DELAY is defined)