6#include <QtCore/QMutex>
7#include <QtCore/QWaitCondition>
8#include <QtCore/QAnimationDriver>
9#include <QtCore/QQueue>
10#include <QtCore/QTime>
12#include <QtGui/QGuiApplication>
13#include <QtGui/QScreen>
14#include <QtGui/QOffscreenSurface>
16#include <qpa/qwindowsysteminterface.h>
18#include <QtQuick/QQuickWindow>
19#include <private/qquickwindow_p.h>
20#include <private/qquickitem_p.h>
22#include <QtQuick/private/qsgrenderer_p.h>
26#include <private/qquickanimatorcontroller_p.h>
28#include <private/qquickprofiler_p.h>
29#include <private/qqmldebugserviceinterfaces_p.h>
30#include <private/qqmldebugconnector_p.h>
32#include <private/qsgrhishadereffectnode_p.h>
33#include <private/qsgdefaultrendercontext_p.h>
35#include <qtquick_tracepoints_p.h>
38#include <QtCore/private/qcore_mac_p.h>
97#define QSG_RT_PAD " (RT) %s"
107 for (
const auto &
t :
std::as_const(m_windows)) {
109 return const_cast<Window *
>(&
t);
140 ,
dpr(float(
c->effectiveDevicePixelRatio()))
195 if (
size() == 0 && wait) {
237#if (defined(Q_OS_QNX) && defined(Q_PROCESSOR_X86)) || defined(Q_OS_INTEGRITY)
255 void sync(
bool inExpose);
322 switch ((
int) e->
type()) {
351 if (se->syncInExpose) {
355 if (se->forceRenderPass) {
364 wm->m_lockedForSync =
true;
366 if (!
window || wme->inDestructor) {
370 Q_ASSERT_X(!wme->inDestructor || !
active,
"QSGRenderThread::invalidateGraphics()",
"Thread's active state is not set to false when shutting down");
374 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- not releasing because window is still active");
377 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- requesting external renderers such as Quick 3D to release cached resources");
378 emit d->context->releaseCachedResourcesRequested();
380 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- requesting renderer to release cached resources");
381 d->renderer->releaseCachedResources();
383#if QT_CONFIG(quick_shadereffect)
389 wm->m_lockedForSync =
false;
414 ce->image->setDevicePixelRatio(ce->window->effectiveDevicePixelRatio());
444 wm->releaseSwapchain(ce->window);
466 qCWarning(QSG_LOG_RENDERLOOP,
"QSGThreadedRenderLoop:QSGRenderThread: no window to make current...");
470 bool wipeSG = inDestructor || !
window->isPersistentSceneGraph();
471 bool wipeGraphics = inDestructor || (wipeSG && !
window->isPersistentGraphics());
480#if QT_CONFIG(quick_shadereffect)
503 qWarning(
"QSGThreadedRenderLoop cleanup with QQuickWindow %p swapchain %p still alive, this should not happen.",
526 Q_ASSERT_X(
wm->m_lockedForSync,
"QSGRenderThread::sync()",
"sync triggered on bad terms as gui is not already locked...");
547 bool hadRenderer =
d->renderer !=
nullptr;
551 d->renderer->clearChangedFlag();
554 if (!hadRenderer &&
d->renderer) {
596 qWarning(
"Graphics device lost, cleaning up scenegraph and releasing RHI");
603 const bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
605 qint64 syncTime = 0, renderTime = 0;
616 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][render thread %p] syncAndRender: start, elapsed since last call: %d ms",
619 int(elapsedSinceLastMs));
636 if (hasValidSwapChain) {
643 if (effectiveOutputSize.isEmpty())
653 bool bailOut =
false;
658 qWarning(
"Failed to create swapchain."
659 " Retrying by requesting a software rasterizer, if applicable for the 3D API implementation.");
668 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- bailing out due to failed swapchain init, wake Gui");
681 qWarning(
"Failed to build or resize swapchain");
702 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- bailing out due to failed beginFrame, wake Gui");
715 sync(exposeRequested);
717#ifndef QSG_NO_RENDER_TIMING
719 syncTime = threadTimer.nsecsElapsed();
723 QQuickProfiler::SceneGraphRenderLoopSync);
748 d->animationController->lock();
750 d->animationController->unlock();
755 const bool canRender =
d->renderer && hasValidSwapChain;
756 double lastCompletedGpuTime = 0;
761 d->renderSceneGraph();
764 renderTime = threadTimer.nsecsElapsed();
767 QQuickProfiler::SceneGraphRenderLoopRender);
781 d->fireFrameSwapped();
785 QQuickProfiler::SceneGraphRenderLoopSync, 1);
799 if (hasValidSwapChain)
807 if (exposeRequested) {
822 qCDebug(QSG_LOG_TIME_RENDERLOOP,
823 "[window %p][render thread %p] syncAndRender: frame rendered in %dms, sync=%d, render=%d, swap=%d",
826 int(threadTimer.elapsed()),
827 int((syncTime/1000000)),
828 int((renderTime - syncTime) / 1000000),
829 int((threadTimer.nsecsElapsed() - renderTime) / 1000000));
831 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][render thread %p] syncAndRender: last retrieved GPU frame time was %.4f ms",
834 lastCompletedGpuTime * 1000.0);
840 QQuickProfiler::SceneGraphRenderLoopSwap);
865 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"--- begin processEventsAndWaitForMore()");
872 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"--- done processEventsAndWaitForMore()");
891 qWarning(
"Failed to create QRhi on the render thread; scenegraph is not functional");
905 rcParams.maybeSurface =
window;
926 qCDebug(QSG_LOG_INFO,
"Swap interval is 0, attempting to disable vsync when presenting.");
932 if (depthBufferEnabled) {
942 qCDebug(QSG_LOG_INFO,
"MSAA sample count for the swapchain is %d. Alpha channel requested = %s.",
956 if (QQmlDebugConnector::service<QQmlProfilerService>())
996 Q_ASSERT_X(!
rhi,
"QSGRenderThread::run()",
"The graphics context should be cleaned up before exiting the render thread...");
1009 , m_animation_timer(0)
1016 m_animation_driver->
install();
1032void QSGThreadedRenderLoop::postUpdateRequest(
Window *
w)
1034 w->window->requestUpdate();
1039 return m_animation_driver;
1047bool QSGThreadedRenderLoop::anyoneShowing()
const
1049 for (
int i=0;
i<m_windows.
size(); ++
i) {
1051 if (
c->isVisible() &&
c->isExposed())
1059 return m_animation_driver->
isRunning() && anyoneShowing();
1064 qCDebug(QSG_LOG_RENDERLOOP,
"- animationStarted()");
1065 startOrStopAnimationTimer();
1067 for (
int i=0;
i<m_windows.
size(); ++
i)
1068 postUpdateRequest(
const_cast<Window *
>(&m_windows.
at(
i)));
1073 qCDebug(QSG_LOG_RENDERLOOP,
"- animationStopped()");
1074 startOrStopAnimationTimer();
1078void QSGThreadedRenderLoop::startOrStopAnimationTimer()
1083 int exposedWindows = 0;
1084 int unthrottledWindows = 0;
1086 const Window *theOne =
nullptr;
1087 for (
int i=0;
i<m_windows.
size(); ++
i) {
1089 if (
w.window->isVisible() &&
w.window->isExposed()) {
1092 if (
w.actualWindowFormat.swapInterval() == 0)
1093 ++unthrottledWindows;
1119 const bool canUseVSyncBasedAnimation = exposedWindows == 1 && unthrottledWindows == 0 && badVSync == 0;
1121 if (m_animation_timer != 0 && (canUseVSyncBasedAnimation || !m_animation_driver->
isRunning())) {
1122 qCDebug(QSG_LOG_RENDERLOOP,
"*** Stopping system (not vsync-based) animation timer (exposedWindows=%d unthrottledWindows=%d badVSync=%d)",
1123 exposedWindows, unthrottledWindows, badVSync);
1125 m_animation_timer = 0;
1128 postUpdateRequest(
const_cast<Window *
>(theOne));
1129 }
else if (m_animation_timer == 0 && !canUseVSyncBasedAnimation && m_animation_driver->
isRunning()) {
1130 qCDebug(QSG_LOG_RENDERLOOP,
"*** Starting system (not vsync-based) animation timer (exposedWindows=%d unthrottledWindows=%d badVSync=%d)",
1131 exposedWindows, unthrottledWindows, badVSync);
1152 handleObscurity(windowFor(
window));
1161 Window *
w = windowFor(
window);
1165 w->psTimeAccumulator = 0.0f;
1166 w->psTimeSampleCount = 0;
1176 qCDebug(QSG_LOG_RENDERLOOP) <<
"begin windowDestroyed()" <<
window;
1178 Window *
w = windowFor(
window);
1191 for (
int i=0;
i<m_windows.
size(); ++
i) {
1201 startOrStopAnimationTimer();
1203 qCDebug(QSG_LOG_RENDERLOOP) <<
"done windowDestroyed()" <<
window;
1220 qCDebug(QSG_LOG_RENDERLOOP) <<
"exposureChanged()" <<
window;
1229 if (!
window->isExposed())
1232 bool skipThisExpose =
false;
1235 skipThisExpose =
true;
1245 if (
window->isExposed()) {
1246 if (!skipThisExpose)
1249 Window *
w = windowFor(
window);
1261 qCDebug(QSG_LOG_RENDERLOOP) <<
"handleExposure()" <<
window;
1265 qCDebug(QSG_LOG_RENDERLOOP,
"- adding window to list");
1268 win.actualWindowFormat =
window->format();
1271 pendingRenderContexts.
remove(renderContext);
1273 win.updateDuringSync =
false;
1274 win.forceRenderPass =
true;
1275 win.badVSync =
false;
1276 win.timeBetweenPolishAndSyncs.start();
1277 win.psTimeAccumulator = 0.0f;
1278 win.psTimeSampleCount = 0;
1280 w = &m_windows.
last();
1283 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1293 if (
w->window->width() <= 0 ||
w->window->height() <= 0
1294 || (
w->window->isTopLevel() && !
w->window->geometry().intersects(
w->window->screen()->availableGeometry()))) {
1295 qWarning().noquote().nospace() <<
"QSGThreadedRenderLoop: expose event received for window "
1296 <<
w->window <<
" with invalid geometry: " <<
w->window->geometry()
1297 <<
" on " <<
w->window->screen();
1303 if (!
w->window->handle())
1304 w->window->create();
1307 if (!
w->thread->isRunning()) {
1308 qCDebug(QSG_LOG_RENDERLOOP,
"- starting render thread");
1310 if (!
w->thread->rhi) {
1312 if (!
w->thread->offscreenSurface)
1315 window->installEventFilter(
this);
1323 w->thread->active =
true;
1325 w->thread->sgrc->moveToThread(
w->thread);
1326 w->thread->moveToThread(
w->thread);
1329 if (!
w->thread->isRunning())
1330 qFatal(
"Render thread failed to start, aborting application.");
1333 qCDebug(QSG_LOG_RENDERLOOP,
"- render thread already running");
1336 polishAndSync(
w,
true);
1337 qCDebug(QSG_LOG_RENDERLOOP,
"- done with handleExposure()");
1339 startOrStopAnimationTimer();
1349void QSGThreadedRenderLoop::handleObscurity(
Window *
w)
1354 qCDebug(QSG_LOG_RENDERLOOP) <<
"handleObscurity()" <<
w->window;
1355 if (
w->thread->isRunning()) {
1357 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1360 w->thread->mutex.lock();
1362 w->thread->waitCondition.wait(&
w->thread->mutex);
1363 w->thread->mutex.unlock();
1365 startOrStopAnimationTimer();
1370 switch (
event->type()) {
1376 Window *
w = windowFor(
window);
1377 if (
w &&
w->thread->isRunning()) {
1378 w->thread->mutex.lock();
1380 w->thread->waitCondition.wait(&
w->thread->mutex);
1381 w->thread->mutex.unlock();
1396 qCDebug(QSG_LOG_RENDERLOOP) <<
"- update request" <<
window;
1398 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1401 Window *
w = windowFor(
window);
1408 Window *
w = windowFor(
window);
1422 if (!
w || !
w->thread->isRunning())
1426 if (current ==
w->thread &&
w->thread->rhi &&
w->thread->rhi->isDeviceLost())
1429 qWarning() <<
"Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
1433 qCDebug(QSG_LOG_RENDERLOOP) <<
"update from item" <<
w->window;
1437 if (current ==
w->thread) {
1438 qCDebug(QSG_LOG_RENDERLOOP,
"- on render thread");
1439 w->updateDuringSync =
true;
1450 postUpdateRequest(
w);
1460 Window *
w = windowFor(
window);
1465 qCDebug(QSG_LOG_RENDERLOOP) <<
"update on window - on render thread" <<
w->window;
1466 w->thread->requestRepaint();
1470 qCDebug(QSG_LOG_RENDERLOOP) <<
"update on window" <<
w->window;
1473 w->forceRenderPass =
true;
1480 Window *
w = windowFor(
window);
1491 qCDebug(QSG_LOG_RENDERLOOP) <<
"releaseResources()" << (inDestructor ?
"in destructor" :
"in api-call") <<
w->window;
1493 w->thread->mutex.lock();
1494 if (
w->thread->isRunning() &&
w->thread->active) {
1502 qCDebug(QSG_LOG_RENDERLOOP,
"- posting release request to render thread");
1504 w->thread->waitCondition.wait(&
w->thread->mutex);
1512 if (!
w->thread->active) {
1513 qCDebug(QSG_LOG_RENDERLOOP) <<
" - waiting for render thread to exit" <<
w->window;
1515 qCDebug(QSG_LOG_RENDERLOOP) <<
" - render thread finished" <<
w->window;
1518 w->thread->mutex.unlock();
1525void QSGThreadedRenderLoop::polishAndSync(
Window *
w,
bool inExpose)
1527 qCDebug(QSG_LOG_RENDERLOOP) <<
"polishAndSync" << (inExpose ?
"(in expose)" :
"(normal)") <<
w->window;
1530 if (!
w->thread || !
w->thread->window) {
1531 qCDebug(QSG_LOG_RENDERLOOP,
"- not exposed, abort");
1539 if (!
w || !
w->thread || !
w->thread->window) {
1540 qCDebug(QSG_LOG_RENDERLOOP,
"- removed after event flushing, abort");
1550 const qint64 elapsedSinceLastMs =
w->timeBetweenPolishAndSyncs.restart();
1552 if (
w->actualWindowFormat.swapInterval() != 0 && sg->
isVSyncDependent(m_animation_driver)) {
1553 w->psTimeAccumulator += elapsedSinceLastMs;
1554 w->psTimeSampleCount += 1;
1556 static const int PS_TIME_SAMPLE_LENGTH = 20;
1557 if (
w->psTimeSampleCount > PS_TIME_SAMPLE_LENGTH) {
1558 const float t =
w->psTimeAccumulator /
w->psTimeSampleCount;
1579 const float threshold = vsyncRate * 0.5f;
1580 const bool badVSync =
t < threshold;
1581 if (badVSync && !
w->badVSync) {
1592 qCDebug(QSG_LOG_INFO,
"Window %p is determined to have broken vsync throttling (%f < %f) "
1593 "switching to system timer to drive gui thread animations to remedy this "
1594 "(however, render thread animators will likely advance at an incorrect rate).",
1595 w->window,
t, threshold);
1596 startOrStopAnimationTimer();
1599 w->psTimeAccumulator = 0.0f;
1600 w->psTimeSampleCount = 0;
1604 const bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
1605 if (profileFrames) {
1607 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][gui thread] polishAndSync: start, elapsed since last call: %d ms",
1609 int(elapsedSinceLastMs));
1612 Q_TRACE(QSG_polishItems_entry);
1620 polishTime =
timer.nsecsElapsed();
1621 Q_TRACE(QSG_polishItems_exit);
1623 QQuickProfiler::SceneGraphPolishAndSyncPolish);
1626 w->updateDuringSync =
false;
1633 qCDebug(QSG_LOG_RENDERLOOP,
"- lock for sync");
1634 w->thread->mutex.lock();
1635 m_lockedForSync =
true;
1637 w->forceRenderPass =
false;
1639 qCDebug(QSG_LOG_RENDERLOOP,
"- wait for sync");
1641 waitTime =
timer.nsecsElapsed();
1644 QQuickProfiler::SceneGraphPolishAndSyncWait);
1647 w->thread->waitCondition.wait(&
w->thread->mutex);
1648 m_lockedForSync =
false;
1649 w->thread->mutex.unlock();
1650 qCDebug(QSG_LOG_RENDERLOOP,
"- unlock after sync");
1653 syncTime =
timer.nsecsElapsed();
1656 QQuickProfiler::SceneGraphPolishAndSyncSync);
1657 Q_TRACE(QSG_animations_entry);
1666 if (m_animation_timer == 0 && m_animation_driver->
isRunning()) {
1667 qCDebug(QSG_LOG_RENDERLOOP,
"- advancing animations");
1668 m_animation_driver->
advance();
1669 qCDebug(QSG_LOG_RENDERLOOP,
"- animations done..");
1683 postUpdateRequest(
w);
1686 }
else if (
w->updateDuringSync) {
1687 postUpdateRequest(
w);
1690 if (profileFrames) {
1691 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][gui thread] Frame prepared, polish=%d ms, lock=%d ms, blockedForSync=%d ms, animations=%d ms",
1693 int(polishTime / 1000000),
1694 int((waitTime - polishTime) / 1000000),
1695 int((syncTime - waitTime) / 1000000),
1696 int((
timer.nsecsElapsed() - syncTime) / 1000000));
1701 QQuickProfiler::SceneGraphPolishAndSyncAnimations);
1706 switch ((
int) e->
type()) {
1711 if (te->timerId() == m_animation_timer) {
1712 qCDebug(QSG_LOG_RENDERLOOP,
"- ticking non-render thread timer");
1713 m_animation_driver->
advance();
1743 Window *
w = windowFor(
window);
1746 if (!
w->thread->isRunning())
1752 qCDebug(QSG_LOG_RENDERLOOP,
"- polishing items");
1759 w->thread->mutex.lock();
1760 m_lockedForSync =
true;
1761 qCDebug(QSG_LOG_RENDERLOOP,
"- posting grab event");
1763 w->thread->waitCondition.wait(&
w->thread->mutex);
1764 m_lockedForSync =
false;
1765 w->thread->mutex.unlock();
1767 qCDebug(QSG_LOG_RENDERLOOP,
"- grab complete");
1778 Window *
w = windowFor(
window);
1779 if (
w &&
w->thread &&
w->thread->window)
1787#include "qsgthreadedrenderloop.moc"
1788#include "moc_qsgthreadedrenderloop_p.cpp"
void install()
Installs this animation driver.
virtual void advance()
Advances the animation.
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Processes some pending events for the calling thread according to the specified flags.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
qint64 restart() noexcept
Restarts the timer and returns the number of milliseconds elapsed since the previous start.
void start() noexcept
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
Type
This enum type defines the valid event types in Qt.
Type type() const
Returns the event type.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
const_reference at(qsizetype i) const noexcept
void unlock() noexcept
Unlocks the mutex.
void lock() noexcept
Locks the mutex.
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
virtual bool eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
QThread * thread() const
Returns the thread in which the object lives.
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
void killTimer(int id)
Kills the timer with timer identifier, id.
void enqueue(const QEvent * &t)
Adds value t to the tail of the queue.
QEvent * dequeue()
Removes the head item in the queue and returns it.
bool timestampsEnabled() const
QRhiRenderPassDescriptor * rpDescForSwapchain
@ TriggerContextCreationFailure
QQuickGraphicsConfiguration graphicsConfig
static QQuickWindowPrivate * get(QQuickWindow *c)
uint swapchainJustBecameRenderable
QRhiRenderBuffer * depthStencilForSwapchain
void cleanupNodesOnShutdown()
QScopedPointer< QQuickAnimatorController > animationController
QRhiSwapChain * swapchain
uint hasRenderableSwapchain
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
QSize currentPixelSize() const
void setDepthStencil(QRhiRenderBuffer *ds)
Sets the renderbuffer ds for use as a depth-stencil buffer.
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor()=0
virtual bool createOrResize()=0
Creates the swapchain if not already done and resizes the swapchain buffers to match the current size...
virtual QSize surfacePixelSize()=0
void setSampleCount(int samples)
Sets the sample count.
void setFlags(Flags f)
Sets the flags f.
void setWindow(QWindow *window)
Sets the window.
void setProxyData(const QRhiSwapChainProxyData &d)
Sets the proxy data d.
virtual QRhiCommandBuffer * currentFrameCommandBuffer()=0
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the QRhiRenderPassDescriptor desc.
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool makeThreadLocalNativeContextCurrent()
With OpenGL this makes the OpenGL context current on the current thread.
static QRhiSwapChainProxyData updateSwapChainProxyData(Implementation impl, QWindow *window)
Generates and returns a QRhiSwapChainProxyData struct containing opaque data specific to the backend ...
QRhiRenderBuffer * newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount=1, QRhiRenderBuffer::Flags flags={}, QRhiTexture::Format backingFormatHint=QRhiTexture::UnknownFormat)
FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags={})
Starts a new frame targeting the next available buffer of swapChain.
QRhiSwapChain * newSwapChain()
bool isRecordingFrame() const
FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags={})
Ends, commits, and presents a frame that was started in the last beginFrame() on swapChain.
FrameOpResult
Describes the result of operations that can have a soft failure.
@ FrameOpSwapChainOutOfDate
bool isDeviceLost() const
The QSGContext holds the scene graph entry points for one QML engine.
virtual float vsyncIntervalForAnimationDriver(QAnimationDriver *driver)
virtual bool isVSyncDependent(QAnimationDriver *driver)
virtual QAnimationDriver * createAnimationDriver(QObject *parent)
Creates a new animation driver.
virtual QSGRenderContext * createRenderContext()=0
void initialize(const QSGRenderContext::InitParams *params) override
Initializes the scene graph render context with the GL context context.
void invalidate() override
QRhi * rhi() const override
QSGContext * sceneGraphContext() const
QSGRenderThreadEventQueue()
QEvent * takeEvent(bool wait)
QElapsedTimer m_threadTimeBetweenRenders
QOffscreenSurface * offscreenSurface
QSGRenderThreadEventQueue eventQueue
bool event(QEvent *) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void postEvent(QEvent *e)
void invalidateGraphics(QQuickWindow *window, bool inDestructor)
QAnimationDriver * animatorDriver
void processEventsAndWaitForMore()
bool syncResultedInChanges
QRhiSwapChainProxyData scProxyData
bool guiNotifiedAboutRhiFailure
QSGThreadedRenderLoop * wm
QSGDefaultRenderContext * sgrc
bool swRastFallbackDueToSwapchainFailure
QSGRenderThread(QSGThreadedRenderLoop *w, QSGRenderContext *renderContext)
QWaitCondition waitCondition
static void garbageCollectMaterialTypeCache(void *materialTypeCacheKey)
static void resetMaterialTypeCache(void *materialTypeCacheKey)
QOffscreenSurface * maybeCreateOffscreenSurface(QWindow *window)
static int chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
bool attemptReinitWithSwRastUponFail() const
RhiCreateResult createRhi(QQuickWindow *window, QSurface *offscreenSurface, bool forcePreferSwRenderer=false)
QRhi::Implementation rhiBackend() const
static QSGRhiSupport * instance()
bool interleaveIncubation() const override
bool event(QEvent *) override
This virtual function receives events to an object and should return true if the event e was recogniz...
QImage grab(QQuickWindow *) override
QSGRenderContext * createRenderContext(QSGContext *) const override
bool eventFilter(QObject *watched, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.
void postJob(QQuickWindow *window, QRunnable *job) override
QSGContext * sceneGraphContext() const override
void resize(QQuickWindow *window) override
void update(QQuickWindow *window) override
void handleUpdateRequest(QQuickWindow *window) override
QAnimationDriver * animationDriver() const override
friend class QSGRenderThread
void maybeUpdate(QQuickWindow *window) override
void exposureChanged(QQuickWindow *window) override
void releaseResources(QQuickWindow *window) override
void hide(QQuickWindow *) override
void windowDestroyed(QQuickWindow *window) override
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
bool remove(const T &value)
iterator insert(const T &value)
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
bool event(QEvent *event) override
This virtual function receives events to an object and should return true if the event e was recogniz...
static QThread * currentThread()
static void yieldCurrentThread()
void setStackSize(uint stackSize)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
WMGrabEvent(QQuickWindow *c, QImage *result)
WMJobEvent(QQuickWindow *c, QRunnable *postedJob)
WMReleaseSwapchainEvent(QQuickWindow *c)
WMSyncEvent(QQuickWindow *c, bool inExpose, bool force, const QRhiSwapChainProxyData &scProxyData)
QRhiSwapChainProxyData scProxyData
WMTryReleaseEvent(QQuickWindow *win, bool destroy, bool needsFallbackSurface)
WMWindowEvent(QQuickWindow *c, QEvent::Type type)
[Window class with invokable method]
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
bool qFuzzyIsNull(qfloat16 f) noexcept
#define qCWarning(category,...)
#define qCDebug(category,...)
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat GLfloat alpha
#define Q_QUICK_SG_PROFILE_END(Type, position)
#define Q_QUICK_SG_PROFILE_SKIP(Type, position, Skip)
#define Q_QUICK_SG_PROFILE_RECORD(Type, position)
#define Q_QUICK_SG_PROFILE_START(Type)
#define Q_ASSERT_X(cond, x, msg)
Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
#define Q_TRACE_SCOPE(x,...)
#define Q_TRACE_POINT(provider, tracepoint,...)
static void registerAnimationCallback()