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);
320 switch ((
int)
e->type()) {
362 wm->m_lockedForSync =
true;
368 Q_ASSERT_X(!wme->
inDestructor || !
active,
"QSGRenderThread::invalidateGraphics()",
"Thread's active state is not set to false when shutting down");
372 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- not releasing because window is still active");
375 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- requesting external renderers such as Quick 3D to release cached resources");
376 emit d->context->releaseCachedResourcesRequested();
378 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- requesting renderer to release cached resources");
379 d->renderer->releaseCachedResources();
381#if QT_CONFIG(quick_shadereffect)
387 wm->m_lockedForSync =
false;
464 qCWarning(QSG_LOG_RENDERLOOP,
"QSGThreadedRenderLoop:QSGRenderThread: no window to make current...");
468 bool wipeSG = inDestructor || !
window->isPersistentSceneGraph();
469 bool wipeGraphics = inDestructor || (wipeSG && !
window->isPersistentGraphics());
478#if QT_CONFIG(quick_shadereffect)
501 qWarning(
"QSGThreadedRenderLoop cleanup with QQuickWindow %p swapchain %p still alive, this should not happen.",
524 Q_ASSERT_X(
wm->m_lockedForSync,
"QSGRenderThread::sync()",
"sync triggered on bad terms as gui is not already locked...");
545 bool hadRenderer =
d->renderer !=
nullptr;
549 d->renderer->clearChangedFlag();
552 if (!hadRenderer &&
d->renderer) {
583 qWarning(
"Graphics device lost, cleaning up scenegraph and releasing RHI");
596 const bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
598 qint64 syncTime = 0, renderTime = 0;
609 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][render thread %p] syncAndRender: start, elapsed since last call: %d ms",
612 int(elapsedSinceLastMs));
628 if (hasValidSwapChain) {
635 if (effectiveOutputSize.
isEmpty())
654 qWarning(
"Failed to build or resize swapchain");
675 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"- bailing out due to failed beginFrame, wake Gui");
688 sync(exposeRequested);
690#ifndef QSG_NO_RENDER_TIMING
696 QQuickProfiler::SceneGraphRenderLoopSync);
721 d->animationController->lock();
723 d->animationController->unlock();
728 const bool canRender =
d->renderer && hasValidSwapChain;
729 double lastCompletedGpuTime = 0;
734 d->renderSceneGraph();
740 QQuickProfiler::SceneGraphRenderLoopRender);
753 d->fireFrameSwapped();
757 QQuickProfiler::SceneGraphRenderLoopSync, 1);
771 if (hasValidSwapChain)
779 if (exposeRequested) {
794 qCDebug(QSG_LOG_TIME_RENDERLOOP,
795 "[window %p][render thread %p] syncAndRender: frame rendered in %dms, sync=%d, render=%d, swap=%d",
799 int((syncTime/1000000)),
800 int((renderTime - syncTime) / 1000000),
801 int((threadTimer.
nsecsElapsed() - renderTime) / 1000000));
803 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][render thread %p] syncAndRender: last retrieved GPU frame time was %.4f ms",
806 lastCompletedGpuTime * 1000.0);
812 QQuickProfiler::SceneGraphRenderLoopSwap);
837 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"--- begin processEventsAndWaitForMore()");
844 qCDebug(QSG_LOG_RENDERLOOP,
QSG_RT_PAD,
"--- done processEventsAndWaitForMore()");
862 qWarning(
"Failed to create QRhi on the render thread; scenegraph is not functional");
897 qCDebug(QSG_LOG_INFO,
"Swap interval is 0, attempting to disable vsync when presenting.");
903 if (depthBufferEnabled) {
913 qCDebug(QSG_LOG_INFO,
"MSAA sample count for the swapchain is %d. Alpha channel requested = %s.",
927 if (QQmlDebugConnector::service<QQmlProfilerService>())
967 Q_ASSERT_X(!
rhi,
"QSGRenderThread::run()",
"The graphics context should be cleaned up before exiting the render thread...");
980 , m_animation_timer(0)
1003void QSGThreadedRenderLoop::postUpdateRequest(
Window *
w)
1005 w->window->requestUpdate();
1010 return m_animation_driver;
1018bool QSGThreadedRenderLoop::anyoneShowing()
const
1020 for (
int i=0;
i<m_windows.
size(); ++
i) {
1022 if (
c->isVisible() &&
c->isExposed())
1030 return m_animation_driver->
isRunning() && anyoneShowing();
1035 qCDebug(QSG_LOG_RENDERLOOP,
"- animationStarted()");
1036 startOrStopAnimationTimer();
1038 for (
int i=0;
i<m_windows.
size(); ++
i)
1039 postUpdateRequest(
const_cast<Window *
>(&m_windows.
at(
i)));
1044 qCDebug(QSG_LOG_RENDERLOOP,
"- animationStopped()");
1045 startOrStopAnimationTimer();
1049void QSGThreadedRenderLoop::startOrStopAnimationTimer()
1054 int exposedWindows = 0;
1055 int unthrottledWindows = 0;
1057 const Window *theOne =
nullptr;
1058 for (
int i=0;
i<m_windows.
size(); ++
i) {
1060 if (
w.window->isVisible() &&
w.window->isExposed()) {
1063 if (
w.actualWindowFormat.swapInterval() == 0)
1064 ++unthrottledWindows;
1090 const bool canUseVSyncBasedAnimation = exposedWindows == 1 && unthrottledWindows == 0 && badVSync == 0;
1092 if (m_animation_timer != 0 && (canUseVSyncBasedAnimation || !m_animation_driver->
isRunning())) {
1093 qCDebug(QSG_LOG_RENDERLOOP,
"*** Stopping system (not vsync-based) animation timer (exposedWindows=%d unthrottledWindows=%d badVSync=%d)",
1094 exposedWindows, unthrottledWindows, badVSync);
1096 m_animation_timer = 0;
1099 postUpdateRequest(
const_cast<Window *
>(theOne));
1100 }
else if (m_animation_timer == 0 && !canUseVSyncBasedAnimation && m_animation_driver->
isRunning()) {
1101 qCDebug(QSG_LOG_RENDERLOOP,
"*** Starting system (not vsync-based) animation timer (exposedWindows=%d unthrottledWindows=%d badVSync=%d)",
1102 exposedWindows, unthrottledWindows, badVSync);
1123 handleObscurity(windowFor(
window));
1136 w->psTimeAccumulator = 0.0f;
1137 w->psTimeSampleCount = 0;
1147 qCDebug(QSG_LOG_RENDERLOOP) <<
"begin windowDestroyed()" <<
window;
1162 for (
int i=0;
i<m_windows.
size(); ++
i) {
1172 startOrStopAnimationTimer();
1174 qCDebug(QSG_LOG_RENDERLOOP) <<
"done windowDestroyed()" <<
window;
1191 qCDebug(QSG_LOG_RENDERLOOP) <<
"exposureChanged()" <<
window;
1200 if (!
window->isExposed())
1203 bool skipThisExpose =
false;
1206 skipThisExpose =
true;
1216 if (
window->isExposed()) {
1217 if (!skipThisExpose)
1232 qCDebug(QSG_LOG_RENDERLOOP) <<
"handleExposure()" <<
window;
1236 qCDebug(QSG_LOG_RENDERLOOP,
"- adding window to list");
1239 win.actualWindowFormat =
window->format();
1242 pendingRenderContexts.
remove(renderContext);
1244 win.updateDuringSync =
false;
1245 win.forceRenderPass =
true;
1246 win.badVSync =
false;
1247 win.timeBetweenPolishAndSyncs.start();
1248 win.psTimeAccumulator = 0.0f;
1249 win.psTimeSampleCount = 0;
1251 w = &m_windows.
last();
1254 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1264 if (
w->window->width() <= 0 ||
w->window->height() <= 0
1265 || (
w->window->isTopLevel() && !
w->window->geometry().intersects(
w->window->screen()->availableGeometry()))) {
1266 qWarning().noquote().nospace() <<
"QSGThreadedRenderLoop: expose event received for window "
1267 <<
w->window <<
" with invalid geometry: " <<
w->window->geometry()
1268 <<
" on " <<
w->window->screen();
1274 if (!
w->window->handle())
1275 w->window->create();
1278 if (!
w->thread->isRunning()) {
1279 qCDebug(QSG_LOG_RENDERLOOP,
"- starting render thread");
1281 if (!
w->thread->rhi) {
1283 if (!
w->thread->offscreenSurface)
1286 window->installEventFilter(
this);
1294 w->thread->active =
true;
1296 w->thread->sgrc->moveToThread(
w->thread);
1297 w->thread->moveToThread(
w->thread);
1300 if (!
w->thread->isRunning())
1301 qFatal(
"Render thread failed to start, aborting application.");
1304 qCDebug(QSG_LOG_RENDERLOOP,
"- render thread already running");
1307 polishAndSync(
w,
true);
1308 qCDebug(QSG_LOG_RENDERLOOP,
"- done with handleExposure()");
1310 startOrStopAnimationTimer();
1320void QSGThreadedRenderLoop::handleObscurity(
Window *
w)
1325 qCDebug(QSG_LOG_RENDERLOOP) <<
"handleObscurity()" <<
w->window;
1326 if (
w->thread->isRunning()) {
1328 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1331 w->thread->mutex.lock();
1333 w->thread->waitCondition.wait(&
w->thread->mutex);
1334 w->thread->mutex.unlock();
1336 startOrStopAnimationTimer();
1341 switch (
event->type()) {
1348 if (
w &&
w->thread->isRunning()) {
1349 w->thread->mutex.lock();
1351 w->thread->waitCondition.wait(&
w->thread->mutex);
1352 w->thread->mutex.unlock();
1367 qCDebug(QSG_LOG_RENDERLOOP) <<
"- update request" <<
window;
1369 qCDebug(QSG_LOG_RENDERLOOP,
"- updatesEnabled is false, abort");
1393 if (!
w || !
w->thread->isRunning())
1397 if (current ==
w->thread &&
w->thread->rhi &&
w->thread->rhi->isDeviceLost())
1400 qWarning() <<
"Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()";
1404 qCDebug(QSG_LOG_RENDERLOOP) <<
"update from item" <<
w->window;
1408 if (current ==
w->thread) {
1409 qCDebug(QSG_LOG_RENDERLOOP,
"- on render thread");
1410 w->updateDuringSync =
true;
1421 postUpdateRequest(
w);
1436 qCDebug(QSG_LOG_RENDERLOOP) <<
"update on window - on render thread" <<
w->window;
1437 w->thread->requestRepaint();
1441 qCDebug(QSG_LOG_RENDERLOOP) <<
"update on window" <<
w->window;
1444 w->forceRenderPass =
true;
1462 qCDebug(QSG_LOG_RENDERLOOP) <<
"releaseResources()" << (inDestructor ?
"in destructor" :
"in api-call") <<
w->window;
1464 w->thread->mutex.lock();
1465 if (
w->thread->isRunning() &&
w->thread->active) {
1473 qCDebug(QSG_LOG_RENDERLOOP,
"- posting release request to render thread");
1475 w->thread->waitCondition.wait(&
w->thread->mutex);
1483 if (!
w->thread->active) {
1484 qCDebug(QSG_LOG_RENDERLOOP) <<
" - waiting for render thread to exit" <<
w->window;
1486 qCDebug(QSG_LOG_RENDERLOOP) <<
" - render thread finished" <<
w->window;
1489 w->thread->mutex.unlock();
1496void QSGThreadedRenderLoop::polishAndSync(
Window *
w,
bool inExpose)
1498 qCDebug(QSG_LOG_RENDERLOOP) <<
"polishAndSync" << (inExpose ?
"(in expose)" :
"(normal)") <<
w->window;
1501 if (!
w->thread || !
w->thread->window) {
1502 qCDebug(QSG_LOG_RENDERLOOP,
"- not exposed, abort");
1510 if (!
w || !
w->thread || !
w->thread->window) {
1511 qCDebug(QSG_LOG_RENDERLOOP,
"- removed after event flushing, abort");
1521 const qint64 elapsedSinceLastMs =
w->timeBetweenPolishAndSyncs.restart();
1523 if (
w->actualWindowFormat.swapInterval() != 0 && sg->
isVSyncDependent(m_animation_driver)) {
1524 w->psTimeAccumulator += elapsedSinceLastMs;
1525 w->psTimeSampleCount += 1;
1527 static const int PS_TIME_SAMPLE_LENGTH = 20;
1528 if (
w->psTimeSampleCount > PS_TIME_SAMPLE_LENGTH) {
1529 const float t =
w->psTimeAccumulator /
w->psTimeSampleCount;
1550 const float threshold = vsyncRate * 0.5f;
1551 const bool badVSync =
t < threshold;
1552 if (badVSync && !
w->badVSync) {
1563 qCDebug(QSG_LOG_INFO,
"Window %p is determined to have broken vsync throttling (%f < %f) "
1564 "switching to system timer to drive gui thread animations to remedy this "
1565 "(however, render thread animators will likely advance at an incorrect rate).",
1566 w->window,
t, threshold);
1567 startOrStopAnimationTimer();
1570 w->psTimeAccumulator = 0.0f;
1571 w->psTimeSampleCount = 0;
1575 const bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
1576 if (profileFrames) {
1578 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][gui thread] polishAndSync: start, elapsed since last call: %d ms",
1580 int(elapsedSinceLastMs));
1583 Q_TRACE(QSG_polishItems_entry);
1591 polishTime =
timer.nsecsElapsed();
1592 Q_TRACE(QSG_polishItems_exit);
1594 QQuickProfiler::SceneGraphPolishAndSyncPolish);
1597 w->updateDuringSync =
false;
1604 qCDebug(QSG_LOG_RENDERLOOP,
"- lock for sync");
1605 w->thread->mutex.lock();
1606 m_lockedForSync =
true;
1608 w->forceRenderPass =
false;
1610 qCDebug(QSG_LOG_RENDERLOOP,
"- wait for sync");
1612 waitTime =
timer.nsecsElapsed();
1615 QQuickProfiler::SceneGraphPolishAndSyncWait);
1618 w->thread->waitCondition.wait(&
w->thread->mutex);
1619 m_lockedForSync =
false;
1620 w->thread->mutex.unlock();
1621 qCDebug(QSG_LOG_RENDERLOOP,
"- unlock after sync");
1624 syncTime =
timer.nsecsElapsed();
1627 QQuickProfiler::SceneGraphPolishAndSyncSync);
1628 Q_TRACE(QSG_animations_entry);
1637 if (m_animation_timer == 0 && m_animation_driver->
isRunning()) {
1638 qCDebug(QSG_LOG_RENDERLOOP,
"- advancing animations");
1639 m_animation_driver->
advance();
1640 qCDebug(QSG_LOG_RENDERLOOP,
"- animations done..");
1654 postUpdateRequest(
w);
1657 }
else if (
w->updateDuringSync) {
1658 postUpdateRequest(
w);
1661 if (profileFrames) {
1662 qCDebug(QSG_LOG_TIME_RENDERLOOP,
"[window %p][gui thread] Frame prepared, polish=%d ms, lock=%d ms, blockedForSync=%d ms, animations=%d ms",
1664 int(polishTime / 1000000),
1665 int((waitTime - polishTime) / 1000000),
1666 int((syncTime - waitTime) / 1000000),
1667 int((
timer.nsecsElapsed() - syncTime) / 1000000));
1672 QQuickProfiler::SceneGraphPolishAndSyncAnimations);
1677 switch ((
int)
e->type()) {
1682 if (te->
timerId() == m_animation_timer) {
1683 qCDebug(QSG_LOG_RENDERLOOP,
"- ticking non-render thread timer");
1684 m_animation_driver->
advance();
1716 if (!
w->thread->isRunning())
1722 qCDebug(QSG_LOG_RENDERLOOP,
"- polishing items");
1729 w->thread->mutex.lock();
1730 m_lockedForSync =
true;
1731 qCDebug(QSG_LOG_RENDERLOOP,
"- posting grab event");
1733 w->thread->waitCondition.wait(&
w->thread->mutex);
1734 m_lockedForSync =
false;
1735 w->thread->mutex.unlock();
1737 qCDebug(QSG_LOG_RENDERLOOP,
"- grab complete");
1749 if (
w &&
w->thread &&
w->thread->window)
1757#include "qsgthreadedrenderloop.moc"
1758#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 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
qint64 restart() noexcept
Restarts the timer and returns the number of milliseconds elapsed since the previous start.
void start() noexcept
Starts this timer.
qint64 nsecsElapsed() const noexcept
Type
This enum type defines the valid event types in Qt.
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the image.
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...
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
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.
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.
void flushFrameSynchronousEvents(QQuickWindow *win)
bool isTimestampsEnabled() const
QRhiRenderPassDescriptor * rpDescForSwapchain
@ TriggerContextCreationFailure
QQuickGraphicsConfiguration graphicsConfig
static QQuickWindowPrivate * get(QQuickWindow *c)
QSGRenderContext * context
uint swapchainJustBecameRenderable
QRhiRenderBuffer * depthStencilForSwapchain
void cleanupNodesOnShutdown()
QQuickDeliveryAgentPrivate * deliveryAgentPrivate() const
QScopedPointer< QQuickAnimatorController > animationController
QRhiSwapChain * swapchain
uint hasRenderableSwapchain
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
double lastCompletedGpuTime()
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.
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
virtual void run()=0
Implement this pure virtual function in your subclass.
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
QSGRenderThread(QSGThreadedRenderLoop *w, QSGRenderContext *renderContext)
QWaitCondition waitCondition
static void garbageCollectMaterialTypeCache(void *materialTypeCacheKey)
static void resetMaterialTypeCache(void *materialTypeCacheKey)
QOffscreenSurface * maybeCreateOffscreenSurface(QWindow *window)
void applySwapChainFormat(QRhiSwapChain *scWithWindowSet, QQuickWindow *window)
static int chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
static QImage grabAndBlockInCurrentFrame(QRhi *rhi, QRhiCommandBuffer *cb, QRhiTexture *src=nullptr)
QRhi::Implementation rhiBackend() const
void destroyRhi(QRhi *rhi, const QQuickGraphicsConfiguration &config)
static QSGRhiSupport * instance()
RhiCreateResult createRhi(QQuickWindow *window, QSurface *offscreenSurface)
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.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
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)
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
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()
QSize initialSurfacePixelSize