diff options
author | Andy Nichols <andy.nichols@theqtcompany.com> | 2015-08-10 14:57:09 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@theqtcompany.com> | 2015-08-12 11:14:36 +0300 |
commit | a5cd1eed98473e73d89acb73c841e18a17ca8c01 (patch) | |
tree | 3721ad63fa53f6f5f84ff626ed3ee10c9dd268e6 | |
parent | 1d925ee4518ccaa7181bcf96fedcffcb34eeeb1b (diff) |
Update Qt Quick 2D Renderer to work with Qt 5.6
Change-Id: Ifa2493f773b2c94fcfc1d58229f26864b08019bc
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/plugins/scenegraph/softwarecontext/context.cpp | 8 | ||||
-rw-r--r-- | src/plugins/scenegraph/softwarecontext/context.h | 3 | ||||
-rw-r--r-- | src/plugins/scenegraph/softwarecontext/renderloop.cpp | 30 | ||||
-rw-r--r-- | src/plugins/scenegraph/softwarecontext/threadedrenderloop.cpp | 188 | ||||
-rw-r--r-- | src/plugins/scenegraph/softwarecontext/threadedrenderloop.h | 7 |
6 files changed, 142 insertions, 96 deletions
diff --git a/.qmake.conf b/.qmake.conf index 42a8dd9960..66a0241ed2 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.4.1 +MODULE_VERSION = 5.6.0 diff --git a/src/plugins/scenegraph/softwarecontext/context.cpp b/src/plugins/scenegraph/softwarecontext/context.cpp index f107290f62..a6526335b0 100644 --- a/src/plugins/scenegraph/softwarecontext/context.cpp +++ b/src/plugins/scenegraph/softwarecontext/context.cpp @@ -223,13 +223,9 @@ void RenderContext::invalidate() QSGRenderContext::invalidate(); } -QSGTexture *RenderContext::createTexture(const QImage &image) const -{ - return new PixmapTexture(image); -} - -QSGTexture *RenderContext::createTextureNoAtlas(const QImage &image) const +QSGTexture *RenderContext::createTexture(const QImage &image, uint flags) const { + Q_UNUSED(flags) return new PixmapTexture(image); } diff --git a/src/plugins/scenegraph/softwarecontext/context.h b/src/plugins/scenegraph/softwarecontext/context.h index 92a0f31d8a..deebfa4292 100644 --- a/src/plugins/scenegraph/softwarecontext/context.h +++ b/src/plugins/scenegraph/softwarecontext/context.h @@ -78,8 +78,7 @@ public: void initializeIfNeeded(); void invalidate(); void renderNextFrame(QSGRenderer *renderer, GLuint fbo); - QSGTexture *createTexture(const QImage &image) const; - QSGTexture *createTextureNoAtlas(const QImage &image) const; + QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const; QSGRenderer *createRenderer(); QWindow *currentWindow; diff --git a/src/plugins/scenegraph/softwarecontext/renderloop.cpp b/src/plugins/scenegraph/softwarecontext/renderloop.cpp index f765e15d63..be52383f16 100644 --- a/src/plugins/scenegraph/softwarecontext/renderloop.cpp +++ b/src/plugins/scenegraph/softwarecontext/renderloop.cpp @@ -49,25 +49,18 @@ void RenderLoop::show(QQuickWindow *window) void RenderLoop::hide(QQuickWindow *window) { - if (!m_windows.contains(window)) - return; - - m_windows.remove(window); QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); cd->fireAboutToStop(); - cd->cleanupNodesOnShutdown(); - - if (m_windows.size() == 0) { - if (!cd->persistentSceneGraph) { - rc->invalidate(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } - } } void RenderLoop::windowDestroyed(QQuickWindow *window) { + m_windows.remove(window); hide(window); + + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + d->cleanupNodesOnShutdown(); + if (m_windows.size() == 0) { rc->invalidate(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); @@ -98,15 +91,17 @@ void RenderLoop::renderWindow(QQuickWindow *window) } QElapsedTimer renderTimer; qint64 renderTime = 0, syncTime = 0, polishTime = 0; - bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::featuresEnabled; + bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled(); if (profileFrames) renderTimer.start(); + Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame); cd->polishItems(); - if (profileFrames) { + if (profileFrames) polishTime = renderTimer.nsecsElapsed(); - } + Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame, + QQuickProfiler::SceneGraphRenderLoopFrame); emit window->afterAnimating(); @@ -114,14 +109,16 @@ void RenderLoop::renderWindow(QQuickWindow *window) if (profileFrames) syncTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame); cd->renderSceneGraph(window->size()); if (profileFrames) renderTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame); if (data.grabOnly) { - // #### grabContent = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); + // #### grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false); data.grabOnly = false; } @@ -133,6 +130,7 @@ void RenderLoop::renderWindow(QQuickWindow *window) qint64 swapTime = 0; if (profileFrames) swapTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame); if (QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled()) { static QTime lastFrameTime = QTime::currentTime(); diff --git a/src/plugins/scenegraph/softwarecontext/threadedrenderloop.cpp b/src/plugins/scenegraph/softwarecontext/threadedrenderloop.cpp index 8ed5a84bc8..2022c8a8bb 100644 --- a/src/plugins/scenegraph/softwarecontext/threadedrenderloop.cpp +++ b/src/plugins/scenegraph/softwarecontext/threadedrenderloop.cpp @@ -41,7 +41,8 @@ #include <private/qquickanimatorcontroller_p.h> #include <private/qquickprofiler_p.h> -#include <private/qqmldebugservice_p.h> +#include <private/qqmldebugserviceinterfaces_p.h> +#include <private/qqmldebugconnector_p.h> #include "context.h" /* @@ -93,16 +94,6 @@ QT_BEGIN_NAMESPACE #define QSG_RT_PAD " (RT)" -static int get_env_int(const char *name, int defaultValue) -{ - QByteArray content = qgetenv(name); - - bool ok = false; - int value = content.toInt(&ok); - return ok ? value : defaultValue; -} - - static inline int qsgrl_animation_interval() { qreal refreshRate = QGuiApplication::primaryScreen()->refreshRate(); // To work around that some platforms wrongfully return 0 or something @@ -143,7 +134,10 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4); // called. const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5); -template <typename T> T *windowFor(const QList<T> list, QQuickWindow *window) +// Passed by the window when there is a render job to run +const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6); + +template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window) { for (int i=0; i<list.size(); ++i) { const T &t = list.at(i); @@ -177,9 +171,15 @@ public: class WMSyncEvent : public WMWindowEvent { public: - WMSyncEvent(QQuickWindow *c, bool inExpose) : WMWindowEvent(c, WM_RequestSync), size(c->size()), syncInExpose(inExpose) { } + WMSyncEvent(QQuickWindow *c, bool inExpose, bool force) + : WMWindowEvent(c, WM_RequestSync) + , size(c->size()) + , syncInExpose(inExpose) + , forceRenderPass(force) + {} QSize size; bool syncInExpose; + bool forceRenderPass; }; @@ -190,6 +190,14 @@ public: QImage *image; }; +class WMJobEvent : public WMWindowEvent +{ +public: + WMJobEvent(QQuickWindow *c, QRunnable *postedJob) + : WMWindowEvent(c, WM_PostJob), job(postedJob) {} + ~WMJobEvent() { delete job; } + QRunnable *job; +}; class RenderThreadEventQueue : public QQueue<QEvent *> { @@ -350,6 +358,10 @@ bool RenderThread::event(QEvent *e) qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- triggered from expose"; pendingUpdate |= ExposeRequest; } + if (se->forceRenderPass) { + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- repaint regardless"; + pendingUpdate |= RepaintRequest; + } return true; } case WM_TryRelease: { @@ -375,7 +387,8 @@ bool RenderThread::event(QEvent *e) case WM_Grab: { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab"; WMGrabEvent *ce = static_cast<WMGrabEvent *>(e); - Q_ASSERT(ce->window == window); + Q_ASSERT(ce->window); + Q_ASSERT(ce->window == window || !window); mutex.lock(); if (window) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph"; @@ -395,6 +408,19 @@ bool RenderThread::event(QEvent *e) return true; } + case WM_PostJob: { + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob"; + WMJobEvent *ce = static_cast<WMJobEvent *>(e); + Q_ASSERT(ce->window == window); + if (window) { + ce->job->run(); + delete ce->job; + ce->job = 0; + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done"; + } + return true; + } + case WM_RequestRepaint: qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint"; // When GUI posts this event, it is followed by a polishAndSync, so we mustn't @@ -454,11 +480,12 @@ void RenderThread::sync(bool inExpose) void RenderThread::syncAndRender() { - bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::featuresEnabled; + bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled(); if (profileFrames) { sinceLastTime = threadTimer.nsecsElapsed(); threadTimer.start(); } + Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRenderLoopFrame); QElapsedTimer waitTimer; waitTimer.start(); @@ -466,16 +493,24 @@ void RenderThread::syncAndRender() qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "syncAndRender()"; syncResultedInChanges = false; + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - uint pending = pendingUpdate; + bool repaintRequested = (pendingUpdate & RepaintRequest) || d->customRenderStage; + bool syncRequested = pendingUpdate & SyncRequest; + bool exposeRequested = (pendingUpdate & ExposeRequest) == ExposeRequest; pendingUpdate = 0; - if (pending & SyncRequest) { + if (syncRequested) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- updatePending, doing sync"; - sync(pending == ExposeRequest); + sync(exposeRequested); } +#ifndef QSG_NO_RENDER_TIMING + if (profileFrames) + syncTime = threadTimer.nsecsElapsed(); +#endif + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame); - if (!syncResultedInChanges && ((pending & RepaintRequest) == 0)) { + if (!syncResultedInChanges && !repaintRequested) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted"; int waitTime = vsyncDelta - (int) waitTimer.elapsed(); if (waitTime > 0) @@ -483,12 +518,8 @@ void RenderThread::syncAndRender() return; } - if (profileFrames) - syncTime = threadTimer.nsecsElapsed(); - qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering started"; - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); if (animatorDriver->isRunning()) { d->animationController->lock(); @@ -507,6 +538,7 @@ void RenderThread::syncAndRender() // ### used to be swappBuffers here d->fireFrameSwapped(); } else { + Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1); qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render"; } @@ -517,7 +549,7 @@ void RenderThread::syncAndRender() // that to avoid blocking the GUI thread in the case where it // has started rendering with a bad window, causing makeCurrent to // fail or if the window has a bad size. - if (pending == ExposeRequest) { + if (exposeRequested) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "- wake Gui after initial expose"; waitCondition.wakeOne(); mutex.unlock(); @@ -530,6 +562,8 @@ void RenderThread::syncAndRender() int((renderTime - syncTime) / 1000000), int(threadTimer.elapsed() - renderTime / 1000000)); + + Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame); } @@ -569,7 +603,7 @@ void RenderThread::run() qCDebug(QSG_RASTER_LOG_RENDERLOOP) << QSG_RT_PAD << "run()"; animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0); animatorDriver->install(); - if (QQmlDebugService::isDebuggingEnabled()) + if (QQmlDebugConnector::service<QQmlProfilerService>()) QQuickProfiler::registerAnimationCallback(); while (active) { @@ -609,8 +643,6 @@ ThreadedRenderLoop::ThreadedRenderLoop() m_animation_driver = sg->createAnimationDriver(this); - m_exhaust_delay = get_env_int("QML_EXHAUST_DELAY", 5); - connect(m_animation_driver, SIGNAL(started()), this, SLOT(animationStarted())); connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped())); @@ -624,10 +656,7 @@ QSGRenderContext *ThreadedRenderLoop::createRenderContext(QSGContext *sg) const void ThreadedRenderLoop::maybePostPolishRequest(Window *w) { - if (w->timerId == 0) { - qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- posting update"; - w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer); - } + w->window->requestUpdate(); } QAnimationDriver *ThreadedRenderLoop::animationDriver() const @@ -674,9 +703,9 @@ void ThreadedRenderLoop::animationStopped() void ThreadedRenderLoop::startOrStopAnimationTimer() { int exposedWindows = 0; - Window *theOne = 0; + const Window *theOne = 0; for (int i=0; i<m_windows.size(); ++i) { - Window &w = m_windows[i]; + const Window &w = m_windows.at(i); if (w.window->isVisible() && w.window->isExposed()) { ++exposedWindows; theOne = &w; @@ -688,7 +717,7 @@ void ThreadedRenderLoop::startOrStopAnimationTimer() m_animation_timer = 0; // If animations are running, make sure we keep on animating if (m_animation_driver->isRunning()) - maybePostPolishRequest(theOne); + maybePostPolishRequest(const_cast<Window *>(theOne)); } else if (m_animation_timer == 0 && exposedWindows != 1 && m_animation_driver->isRunning()) { m_animation_timer = startTimer(qsgrl_animation_interval()); @@ -777,8 +806,8 @@ void ThreadedRenderLoop::handleExposure(QQuickWindow *window) win.window = window; win.actualWindowFormat = window->format(); win.thread = new RenderThread(this, QQuickWindowPrivate::get(window)->context); - win.timerId = 0; win.updateDuringSync = false; + win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt m_windows << win; w = &m_windows.last(); } @@ -788,9 +817,11 @@ void ThreadedRenderLoop::handleExposure(QQuickWindow *window) w->thread->window = window; if (w->window->width() <= 0 || w->window->height() <= 0 - || !w->window->geometry().intersects(w->window->screen()->availableGeometry())) { + || (w->window->isTopLevel() && !w->window->geometry().intersects(w->window->screen()->availableGeometry()))) { #ifndef QT_NO_DEBUG - qWarning("ThreadedRenderLoop: expose event received for window with invalid geometry."); + qWarning().noquote().nospace() << "ThreadedRenderLoop: expose event received for window " + << w->window << " with invalid geometry: " << w->window->geometry() + << " on " << w->window->screen(); #endif } @@ -814,6 +845,8 @@ void ThreadedRenderLoop::handleExposure(QQuickWindow *window) w->thread->moveToThread(w->thread); } w->thread->start(); + if (!w->thread->isRunning()) + qFatal("Render thread failed to start, aborting application."); } else { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- render thread already running"; @@ -845,6 +878,14 @@ void ThreadedRenderLoop::handleObscurity(Window *w) } +void ThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window) +{ + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- polish and sync update request"; + Window *w = windowFor(m_windows, window); + if (w) + polishAndSync(w); +} + void ThreadedRenderLoop::maybeUpdate(QQuickWindow *window) { Window *w = windowFor(m_windows, window); @@ -861,6 +902,9 @@ void ThreadedRenderLoop::maybeUpdate(Window *w) if (!QCoreApplication::instance()) return; + if (!w || !w->thread->isRunning()) + return; + QThread *current = QThread::currentThread(); if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) { qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()"; @@ -874,7 +918,7 @@ void ThreadedRenderLoop::maybeUpdate(Window *w) // Call this function from the Gui thread later as startTimer cannot be // called from the render thread. - if (QThread::currentThread() == w->thread) { + if (current == w->thread) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- on render thread"; w->updateDuringSync = true; return; @@ -901,7 +945,9 @@ void ThreadedRenderLoop::update(QQuickWindow *window) } qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "update on window" << w->window; - w->thread->postEvent(new QEvent(WM_RequestRepaint)); + // We set forceRenderPass because we want to make sure the QQuickWindow + // actually does a full render pass after the next sync. + w->forceRenderPass = true; maybeUpdate(w); } @@ -943,6 +989,18 @@ void ThreadedRenderLoop::releaseResources(Window *w, bool inDestructor) w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback)); w->thread->waitCondition.wait(&w->thread->mutex); delete fallback; + + // Avoid a shutdown race condition. + // If SG is invalidated and 'active' becomes false, the thread's run() + // method will exit. handleExposure() relies on QThread::isRunning() (because it + // potentially needs to start the thread again) and our mutex cannot be used to + // track the thread stopping, so we wait a few nanoseconds extra so the thread + // can exit properly. + if (!w->thread->active) { + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << " - waiting for render thread to exit" << w->window; + w->thread->wait(); + qCDebug(QSG_RASTER_LOG_RENDERLOOP) << " - render thread finished" << w->window; + } } w->thread->mutex.unlock(); } @@ -958,8 +1016,6 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) QQuickWindow *window = w->window; if (!w->thread || !w->thread->window) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- not exposed, abort"; - killTimer(w->timerId); - w->timerId = 0; return; } @@ -969,8 +1025,6 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) w = windowFor(m_windows, window); if (!w || !w->thread || !w->thread->window) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- removed after event flushing, abort"; - killTimer(w->timerId); - w->timerId = 0; return; } @@ -979,15 +1033,17 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) qint64 polishTime = 0; qint64 waitTime = 0; qint64 syncTime = 0; - bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::featuresEnabled; + bool profileFrames = QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled(); if (profileFrames) timer.start(); + Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishAndSync); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->polishItems(); if (profileFrames) polishTime = timer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync); w->updateDuringSync = false; @@ -996,11 +1052,13 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- lock for sync"; w->thread->mutex.lock(); m_lockedForSync = true; - w->thread->postEvent(new WMSyncEvent(window, inExpose)); + w->thread->postEvent(new WMSyncEvent(window, inExpose, w->forceRenderPass)); + w->forceRenderPass = false; qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- wait for sync"; if (profileFrames) waitTime = timer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync); w->thread->waitCondition.wait(&w->thread->mutex); m_lockedForSync = false; w->thread->mutex.unlock(); @@ -1008,9 +1066,7 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) if (profileFrames) syncTime = timer.nsecsElapsed(); - - killTimer(w->timerId); - w->timerId = 0; + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync); if (m_animation_timer == 0 && m_animation_driver->isRunning()) { qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- advancing animations"; @@ -1030,17 +1086,8 @@ void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) << ", blockedForSync=" << (syncTime - waitTime) / 1000000 << ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000 << " - (on Gui thread) " << window; -} -ThreadedRenderLoop::Window *ThreadedRenderLoop::windowForTimer(int timerId) const -{ - for (int i=0; i<m_windows.size(); ++i) { - if (m_windows.at(i).timerId == timerId) { - return const_cast<Window *>(&m_windows.at(i)); - break; - } - } - return 0; + Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync); } bool ThreadedRenderLoop::event(QEvent *e) @@ -1053,15 +1100,8 @@ bool ThreadedRenderLoop::event(QEvent *e) qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- ticking non-visual timer"; m_animation_driver->advance(); emit timeToIncubate(); - } else { - qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- polish and sync timer"; - Window *w = windowForTimer(te->timerId()); - if (w) - polishAndSync(w); - else - killTimer(te->timerId()); + return true; } - return true; } default: @@ -1108,12 +1148,24 @@ QImage ThreadedRenderLoop::grab(QQuickWindow *window) w->thread->waitCondition.wait(&w->thread->mutex); m_lockedForSync = false; w->thread->mutex.unlock(); - qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "- grab complete"; return result; } -QT_END_NAMESPACE +/*! + * Posts a new job event to the render thread. + * Returns true if posting succeeded. + */ +void ThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job) +{ + Window *w = windowFor(m_windows, window); + if (w && w->thread && w->thread->window) + w->thread->postEvent(new WMJobEvent(window, job)); + else + delete job; +} #include "threadedrenderloop.moc" + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/softwarecontext/threadedrenderloop.h b/src/plugins/scenegraph/softwarecontext/threadedrenderloop.h index f5c640bb76..9058e8879b 100644 --- a/src/plugins/scenegraph/softwarecontext/threadedrenderloop.h +++ b/src/plugins/scenegraph/softwarecontext/threadedrenderloop.h @@ -43,6 +43,8 @@ public: void update(QQuickWindow *window); void maybeUpdate(QQuickWindow *window); + void handleUpdateRequest(QQuickWindow *window); + QSGContext *sceneGraphContext() const; QSGRenderContext *createRenderContext(QSGContext *) const; @@ -51,6 +53,7 @@ public: void releaseResources(QQuickWindow *window); bool event(QEvent *); + void postJob(QQuickWindow *window, QRunnable *job); bool interleaveIncubation() const; @@ -63,15 +66,14 @@ private: QQuickWindow *window; RenderThread *thread; QSurfaceFormat actualWindowFormat; - int timerId; uint updateDuringSync : 1; + uint forceRenderPass : 1; }; friend class RenderThread; void releaseResources(Window *window, bool inDestructor); bool checkAndResetForceUpdate(QQuickWindow *window); - Window *windowForTimer(int timerId) const; bool anyoneShowing() const; void initialize(); @@ -91,7 +93,6 @@ private: QList<Window> m_windows; int m_animation_timer; - int m_exhaust_delay; bool m_lockedForSync; }; |