diff --git a/.gitattributes b/.gitattributes
index 0909f7a01df6d400f7b8fd5ad41c4eb68d29efc7..018cf2cbcb93d7f02744f707f325802bd3b5a364 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,3 @@
 .tag                    export-subst
+.gitignore              export-ignore
 .gitattributes          export-ignore
diff --git a/src/imports/qtcanvas3d/canvas3d.cpp b/src/imports/qtcanvas3d/canvas3d.cpp
index d7de4931bc68c833226efccc2713bf5941950c41..39acb80f18c17df34aab76cd1d20c087b93d43ca 100644
--- a/src/imports/qtcanvas3d/canvas3d.cpp
+++ b/src/imports/qtcanvas3d/canvas3d.cpp
@@ -160,7 +160,6 @@ void Canvas::setWidth(int width)
                                              << maxWidth;
         newWidth = maxWidth;
     }
-
     QQuickItem::setWidth(qreal(newWidth));
 }
 
@@ -454,7 +453,6 @@ void Canvas::setPixelSize(QSize pixelSize)
     qCDebug(canvas3drendering).nospace() << "Canvas3D::" << __FUNCTION__
                                          << "(pixelSize:" << pixelSize
                                          << ")";
-
     if (pixelSize.width() > m_maxSize.width()) {
         qCDebug(canvas3drendering).nospace() << "Canvas3D::" << __FUNCTION__
                                              << "():"
@@ -471,6 +469,11 @@ void Canvas::setPixelSize(QSize pixelSize)
         pixelSize.setHeight(m_maxSize.height());
     }
 
+    if (pixelSize.width() <= 0)
+        pixelSize.setWidth(1);
+    if (pixelSize.height() <= 0)
+        pixelSize.setHeight(1);
+
     if (m_fboSize == pixelSize)
         return;
 
@@ -583,6 +586,10 @@ bool Canvas::firstSync()
     if (!m_renderer->qtContextResolved()) {
         m_firstSync = false;
         QSize initializedSize = boundingRect().size().toSize();
+        if (initializedSize.width() <= 0)
+            initializedSize.setWidth(1);
+        if (initializedSize.height() <= 0)
+            initializedSize.setHeight(1);
         m_renderer->resolveQtContext(window(), initializedSize, m_renderTarget);
         m_isOpenGLES2 = m_renderer->isOpenGLES2();
 
@@ -757,9 +764,9 @@ void Canvas::queueNextRender()
     updateWindowParameters();
 
     // Don't try to do anything before the renderer/node are ready
-    if (!m_rendererReady) {
+    if (!m_rendererReady || !window()) {
         qCDebug(canvas3drendering).nospace() << "Canvas3D::" << __FUNCTION__
-                                             << " Renderer not ready, returning";
+                                             << " Renderer or window not ready, returning";
         return;
     }
 
diff --git a/src/imports/qtcanvas3d/context3d.cpp b/src/imports/qtcanvas3d/context3d.cpp
index 1592dc3f2ccc462ea275d6333432fa6c8467097e..829d5a90bed6e293f8b629435327946c8d6e036b 100644
--- a/src/imports/qtcanvas3d/context3d.cpp
+++ b/src/imports/qtcanvas3d/context3d.cpp
@@ -5754,19 +5754,25 @@ void CanvasContext::scheduleSyncCommand(GlSyncCommand *command)
     if (m_canvas->window() && m_canvas->renderer()) {
         QOpenGLContext *ctx = m_canvas->window()->openglContext();
         if (ctx) {
+            bool jobDeleted = false;
             if (ctx->thread() != QThread::currentThread()) {
                 // In case of threaded renderer, we block the main thread until the job is done
                 CanvasRenderJob *syncJob = new CanvasRenderJob(command, &m_renderJobMutex,
                                                                &m_renderJobCondition,
-                                                               m_canvas->renderer());
+                                                               m_canvas->renderer(),
+                                                               &jobDeleted);
                 m_renderJobMutex.lock();
                 m_canvas->window()->scheduleRenderJob(syncJob, QQuickWindow::NoStage);
-                m_renderJobCondition.wait(&m_renderJobMutex);
+                // scheduleRenderJob will delete the job if the window is not exposed
+                if (!jobDeleted)
+                    m_renderJobCondition.wait(&m_renderJobMutex);
                 m_renderJobMutex.unlock();
+
             } else {
                 // In case of non-threaded renderer, scheduling a job executes it immediately,
                 // so we don't need synchronization.
-                CanvasRenderJob *syncJob = new CanvasRenderJob(command, 0, 0, m_canvas->renderer());
+                CanvasRenderJob *syncJob = new CanvasRenderJob(command, 0, 0, m_canvas->renderer(),
+                                                               &jobDeleted);
                 m_canvas->window()->scheduleRenderJob(syncJob, QQuickWindow::NoStage);
             }
         }
diff --git a/src/imports/qtcanvas3d/renderjob.cpp b/src/imports/qtcanvas3d/renderjob.cpp
index dfb891b7a222b87d5093f55405f448cfe11bcbfb..754aacb0f91f27832e275fe05befd037bc41b777 100644
--- a/src/imports/qtcanvas3d/renderjob.cpp
+++ b/src/imports/qtcanvas3d/renderjob.cpp
@@ -49,14 +49,26 @@ QT_CANVAS3D_BEGIN_NAMESPACE
  */
 CanvasRenderJob::CanvasRenderJob(GlSyncCommand *command,
                                  QMutex *mutex, QWaitCondition *condition,
-                                 CanvasRenderer *renderer)
-    : m_command(command), m_mutex(mutex), m_condition(condition), m_renderer(renderer)
+                                 CanvasRenderer *renderer, bool *deleted)
+    : m_command(command),
+      m_mutex(mutex),
+      m_condition(condition),
+      m_renderer(renderer),
+      m_deleted(deleted),
+      m_creationThread(QThread::currentThread())
 {
 }
 
 CanvasRenderJob::~CanvasRenderJob()
 {
-    notifyGuiThread();
+    if (m_creationThread != QThread::currentThread()) {
+        notifyGuiThread();
+    } else {
+        // If the job is deleted in the thread it was created in, we can assume the scheduling
+        // failed and notify the context that we got deleted via the m_deleted flag,
+        // so it won't start waiting for job to complete.
+        *m_deleted = true;
+    }
 }
 
 void CanvasRenderJob::run()
diff --git a/src/imports/qtcanvas3d/renderjob_p.h b/src/imports/qtcanvas3d/renderjob_p.h
index 7d0e50ba531c317415f1d4284df9b4026d843841..e4c0ff1703ce5c8ae603ce37d034515140e362ec 100644
--- a/src/imports/qtcanvas3d/renderjob_p.h
+++ b/src/imports/qtcanvas3d/renderjob_p.h
@@ -53,6 +53,7 @@
 #include <QtCore/QWaitCondition>
 #include <QtCore/QMutex>
 #include <QtCore/QRunnable>
+#include <QtCore/QThread>
 
 QT_BEGIN_NAMESPACE
 QT_CANVAS3D_BEGIN_NAMESPACE
@@ -63,7 +64,8 @@ class CanvasRenderJob : public QRunnable
 {
 public:
     CanvasRenderJob(GlSyncCommand *command, QMutex *mutex,
-                    QWaitCondition *condition, QtCanvas3D::CanvasRenderer *renderer);
+                    QWaitCondition *condition, QtCanvas3D::CanvasRenderer *renderer,
+                    bool *deleted);
     ~CanvasRenderJob();
 
     void run();
@@ -76,6 +78,8 @@ private:
     QMutex *m_mutex;
     QWaitCondition *m_condition;
     CanvasRenderer *m_renderer;
+    bool *m_deleted;
+    QThread *m_creationThread;
 };
 
 QT_CANVAS3D_END_NAMESPACE
diff --git a/tests/auto/qmltest/canvas3d/tst_render_dynamic.qml b/tests/auto/qmltest/canvas3d/tst_render_dynamic.qml
index 80b9e3aa58b99a490eccdde389b5d5dcd298add3..2f4da23839d2bafbb3d2c8f57be486505bf08ca3 100644
--- a/tests/auto/qmltest/canvas3d/tst_render_dynamic.qml
+++ b/tests/auto/qmltest/canvas3d/tst_render_dynamic.qml
@@ -72,6 +72,7 @@ Item {
         import QtCanvas3D 1.0
         import QtQuick.Window 2.0
         Window {
+            property alias windowCanvas: theCanvas
             visible: true
             width: 300
             height: 300
@@ -151,20 +152,28 @@ Item {
             tryCompare(top, "initOk", true)
             tryCompare(top, "renderOk", true)
             tryCompare(top, "windowHidden", false)
+            canvasWindow.destroy()
+            tryCompare(top, "canvasWindow", null)
         }
 
         function test_render_5_dynamic_window_hide_and_reshow() {
-            verify(canvasWindow !== null)
+            initOk = false
+            renderOk = false
+            verify(canvasWindow === null)
             verify(windowHidden === false)
+            createCanvasWindow()
+            verify(canvasWindow !== null)
+            tryCompare(top, "initOk", true)
+            tryCompare(top, "renderOk", true)
+            tryCompare(top, "windowHidden", false)
+            waitForRendering(canvasWindow.windowCanvas)
             canvasWindow.hide()
             tryCompare(top, "windowHidden", true)
             renderOk = false
             canvasWindow.show()
+            waitForRendering(canvasWindow.windowCanvas)
             tryCompare(top, "renderOk", true)
             tryCompare(top, "windowHidden", false)
-        }
-        function test_render_6_dynamic_window_destroy() {
-            verify(canvasWindow !== null)
             canvasWindow.destroy()
             tryCompare(top, "canvasWindow", null)
         }
diff --git a/tests/auto/qmltest/canvas3d/tst_render_simple.js b/tests/auto/qmltest/canvas3d/tst_render_simple.js
index e8565ab56cf969e8f00a7e68d0ad63c2c2ee36a1..cd2c840f937fd31df6a37486fef3f111342c0c44 100644
--- a/tests/auto/qmltest/canvas3d/tst_render_simple.js
+++ b/tests/auto/qmltest/canvas3d/tst_render_simple.js
@@ -82,6 +82,28 @@ function initializeGL(canvas) {
 function paintGL(canvas) {
     gl.clear(gl.COLOR_BUFFER_BIT);
     gl.drawArrays(gl.TRIANGLES, 0, 3);
+    return (gl.getError() === 0);
+}
+
+function resizeGL(canvas)
+{
+    var pixelRatio = canvas.devicePixelRatio;
+    canvas.pixelSize = Qt.size(canvas.width * pixelRatio,
+                               canvas.height * pixelRatio);
+
+    if (gl) {
+        gl.viewport(0, 0,
+                    canvas.width * canvas.devicePixelRatio,
+                    canvas.height * canvas.devicePixelRatio);
+    }
+}
+
+function getWidth() {
+    return gl.drawingBufferWidth
+}
+
+function getHeight() {
+    return gl.drawingBufferHeight
 }
 
 function initShaders()
diff --git a/tests/auto/qmltest/canvas3d/tst_render_simple.qml b/tests/auto/qmltest/canvas3d/tst_render_simple.qml
index 9d25dd3dbefab606113cbe308983c3e9bfd1166c..3a714082e8756ba93a1ec0a81181e4c16f2e08a7 100644
--- a/tests/auto/qmltest/canvas3d/tst_render_simple.qml
+++ b/tests/auto/qmltest/canvas3d/tst_render_simple.qml
@@ -51,12 +51,13 @@ Item {
         property bool widthChanged: false
         property bool initOk: false
         property bool renderOk: false
-        anchors.fill: parent
+        height: 300
+        width: 300
         onInitializeGL: initOk = Content.initializeGL(render_simple)
         onPaintGL: {
-            Content.paintGL(render_simple)
-            renderOk = true
+            renderOk = Content.paintGL(render_simple)
         }
+        onResizeGL: Content.resizeGL(render_simple)
         onHeightChanged: heightChanged = true
         onWidthChanged: widthChanged = true
     }
@@ -75,18 +76,42 @@ Item {
             render_simple.heightChanged = false
             render_simple.widthChanged = false
             render_simple.renderOk = false
-            top.height = 200
+            render_simple.height = 200
             waitForRendering(render_simple)
             verify(render_simple.heightChanged === true)
             verify(render_simple.widthChanged === false)
             tryCompare(render_simple, "renderOk", true)
+            var fboHeight = Content.getHeight()
+            var fboWidth = Content.getWidth()
+            verify(fboHeight === render_simple.height)
+            verify(fboWidth === render_simple.width)
 
             render_simple.renderOk = false
-            top.width = 200
+            render_simple.width = 200
             waitForRendering(render_simple)
             verify(render_simple.heightChanged === true)
             verify(render_simple.widthChanged === true)
             tryCompare(render_simple, "renderOk", true)
+            fboHeight = Content.getHeight()
+            fboWidth = Content.getWidth()
+            verify(fboHeight === render_simple.height)
+            verify(fboWidth === render_simple.width)
+
+            render_simple.heightChanged = false
+            render_simple.widthChanged = false
+            render_simple.width = 0
+            render_simple.height = 0
+            waitForRendering(render_simple)
+            verify(render_simple.heightChanged === true)
+            verify(render_simple.widthChanged === true)
+            render_simple.renderOk = false
+            waitForRendering(render_simple)
+            tryCompare(render_simple, "renderOk", true)
+            fboHeight = Content.getHeight()
+            fboWidth = Content.getWidth()
+            // Zero size canvas will still create 1x1 fbo
+            verify(fboHeight === 1)
+            verify(fboWidth === 1)
         }
     }
 }