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