diff options
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 141 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 20 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetrepaintmanager.cpp | 109 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetrepaintmanager_p.h | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 22 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 9 |
6 files changed, 131 insertions, 176 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0a0957bf5e..1527ec679f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -77,9 +77,6 @@ #include "qscopeguard.h" #include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/qinputmethod.h> -#include <QtGui/qopenglcontext.h> -#include <QtGui/private/qopenglcontext_p.h> -#include <QtGui/qoffscreensurface.h> #if QT_CONFIG(graphicseffect) #include <private/qgraphicseffect_p.h> @@ -178,10 +175,8 @@ QWidgetPrivate::QWidgetPrivate(int version) #ifndef QT_NO_IM , inheritsInputMethodHints(0) #endif -#ifndef QT_NO_OPENGL , renderToTextureReallyDirty(1) - , renderToTextureComposeActive(0) -#endif + , usesRhiFlush(0) , childrenHiddenByWState(0) , childrenShownByExpose(0) #if defined(Q_OS_WIN) @@ -1114,6 +1109,47 @@ QScreen *QWidgetPrivate::associatedScreen() const return nullptr; } +// finds the first rhiconfig in the hierarchy that has enable==true +static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType) +{ + QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig(); + if (config.isEnabled()) { + if (outConfig) + *outConfig = config; + if (outType) + *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config); + return true; + } + QObjectList children = w->children(); + for (int i = 0; i < children.size(); i++) { + if (children.at(i)->isWidgetType()) { + const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i)); + if (childWidget) { + if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType)) + return true; + } + } + } + return false; +} + +// First tries q_evaluateRhiConfigRecursive, then if that did not indicate that rhi is wanted, +// then checks env.vars or something else to see if we need to force using rhi-based composition. +bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType) +{ + if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) { + qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi"; + return true; + } + + if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) { + qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi"; + return true; + } + + return false; +} + // ### fixme: Qt 6: Remove parameter window from QWidget::create() /*! @@ -1336,14 +1372,21 @@ void QWidgetPrivate::create() #endif QBackingStore *store = q->backingStore(); + usesRhiFlush = false; if (!store) { if (q->windowType() != Qt::Desktop) { - if (q->isWindow()) + if (q->isWindow()) { q->setBackingStore(new QBackingStore(win)); + QPlatformBackingStoreRhiConfig rhiConfig; + usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr); + topData()->backingStore->handle()->setRhiConfig(rhiConfig); + } } else { q->setAttribute(Qt::WA_PaintOnScreen, true); } + } else if (win->handle()) { + usesRhiFlush = q_evaluateRhiConfig(q, nullptr, nullptr); } setWindowModified_helper(); @@ -1685,10 +1728,7 @@ void QWidgetPrivate::deleteTLSysExtra() extra->topextra->repaintManager.reset(nullptr); deleteBackingStore(this); -#ifndef QT_NO_OPENGL extra->topextra->widgetTextures.clear(); - extra->topextra->shareContext.reset(); -#endif //the toplevel might have a context with a "qglcontext associated with it. We need to //delete the qglcontext before we delete the qplatformopenglcontext. @@ -5538,30 +5578,22 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //paint the background if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground)) && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { -#ifndef QT_NO_OPENGL beginBackingStorePainting(); -#endif QPainter p(q); paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags()); -#ifndef QT_NO_OPENGL endBackingStorePainting(); -#endif } if (!sharedPainter) setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset)); if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) { -#ifndef QT_NO_OPENGL beginBackingStorePainting(); -#endif QPainter p(q); QColor tint = q->palette().window().color(); tint.setAlphaF(.6f); p.fillRect(toBePainted.boundingRect(), tint); -#ifndef QT_NO_OPENGL endBackingStorePainting(); -#endif } } @@ -5572,7 +5604,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP #endif bool skipPaintEvent = false; -#ifndef QT_NO_OPENGL if (renderToTexture) { // This widget renders into a texture which is composed later. We just need to // punch a hole in the backingstore, so the texture will be visible. @@ -5598,7 +5629,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP else skipPaintEvent = true; } -#endif // QT_NO_OPENGL if (!skipPaintEvent) { //actually send the paint event @@ -5654,10 +5684,8 @@ void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted) QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); -#ifndef QT_NO_OPENGL if (renderToTexture) resolveSamples(); -#endif // QT_NO_OPENGL } void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, @@ -9232,9 +9260,7 @@ bool QWidget::event(QEvent *event) } if (d->data.fnt.d->dpi != logicalDpiY()) d->updateFont(d->data.fnt); -#ifndef QT_NO_OPENGL d->renderToTextureReallyDirty = 1; -#endif break; case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); @@ -10511,22 +10537,20 @@ void QWidget::setParent(QWidget *parent) setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask); } -#ifndef QT_NO_OPENGL -static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget) +static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType) { QWidgetPrivate *d = QWidgetPrivate::get(widget); if (d->renderToTexture) { - QEvent e(QEvent::WindowChangeInternal); + QEvent e(eventType); QCoreApplication::sendEvent(widget, &e); } for (int i = 0; i < d->children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(d->children.at(i)); if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen) - sendWindowChangeToTextureChildrenRecursively(w); + sendWindowChangeToTextureChildrenRecursively(w, eventType); } } -#endif /*! \overload @@ -10582,6 +10606,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) QCoreApplication::sendEvent(this, &e); } } + + // texture-based widgets need a pre-notification when their associated top-level window changes + // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget. + if (d->textureChildSeen && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw))) + sendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal); + // If we get parented into another window, children will be folded // into the new parent's focus chain, so clear focus now. if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window)) @@ -10592,12 +10622,10 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) if (desktopWidget) parent = nullptr; -#ifndef QT_NO_OPENGL if (d->textureChildSeen && parent) { // set the textureChildSeen flag up the whole parent chain QWidgetPrivate::get(parent)->setTextureChildSeen(); } -#endif if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) { if (newParent) @@ -10659,12 +10687,11 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) QEvent e(QEvent::ParentChange); QCoreApplication::sendEvent(this, &e); } -#ifndef QT_NO_OPENGL - //renderToTexture widgets also need to know when their top-level window changes - if (d->textureChildSeen && oldtlw != window()) { - sendWindowChangeToTextureChildrenRecursively(this); - } -#endif + + // texture-based widgets need another event when their top-level window + // changes (more precisely, has already changed at this point) + if (d->textureChildSeen && oldtlw != window()) + sendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal); if (!wasCreated) { if (isWindow() || parentWidget()->isVisible()) @@ -10690,6 +10717,20 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) if (d->extra && d->extra->hasWindowContainer) QWindowContainer::parentWasChanged(this); + + QWidget *newtlw = window(); + if (oldtlw != newtlw) { + QSurface::SurfaceType surfaceType = QSurface::RasterSurface; + if (q_evaluateRhiConfig(this, nullptr, &surfaceType)) { + newtlw->d_func()->usesRhiFlush = true; + if (QWindow *w = newtlw->windowHandle()) { + if (w->surfaceType() != surfaceType) { + newtlw->destroy(); + newtlw->create(); + } + } + } + } } void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) @@ -10947,7 +10988,7 @@ void QWidgetPrivate::repaint(T r) return; QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && tlwExtra->backingStore) + if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager) tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow); } @@ -11022,7 +11063,7 @@ void QWidgetPrivate::update(T r) } QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && tlwExtra->backingStore) + if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager) tlwExtra->repaintManager->markDirty(clipped, q); } @@ -12158,27 +12199,6 @@ void QWidgetPrivate::adjustQuitOnCloseAttribute() } } -QOpenGLContext *QWidgetPrivate::shareContext() const -{ -#ifdef QT_NO_OPENGL - return nullptr; -#else - if (!extra || !extra->topextra || !extra->topextra->window) - return nullptr; - - if (!extra->topextra->shareContext) { - auto ctx = std::make_unique<QOpenGLContext>(); - ctx->setShareContext(qt_gl_global_share_context()); - ctx->setFormat(extra->topextra->window->format()); - ctx->setScreen(extra->topextra->window->screen()); - ctx->create(); - extra->topextra->shareContext = std::move(ctx); - } - return extra->topextra->shareContext.get(); -#endif // QT_NO_OPENGL -} - -#ifndef QT_NO_OPENGL void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end) { QWidgetPrivate *wd = QWidgetPrivate::get(w); @@ -12194,7 +12214,6 @@ void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end) sendComposeStatus(w, end); } } -#endif // QT_NO_OPENGL Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget) { diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 41f343dfec..b8a30fde25 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -61,7 +61,6 @@ #include "QtCore/qset.h" #include "QtGui/qregion.h" #include "QtGui/qinputmethod.h" -#include "QtGui/qopengl.h" #include "QtGui/qsurfaceformat.h" #include "QtGui/qscreen.h" #include "QtWidgets/qsizepolicy.h" @@ -77,6 +76,7 @@ #endif #include <private/qgesture_p.h> #include <qpa/qplatformbackingstore.h> +#include <QtGui/private/qbackingstorerhisupport_p.h> #include <vector> #include <memory> @@ -94,7 +94,6 @@ class QPixmap; class QWidgetRepaintManager; class QGraphicsProxyWidget; class QWidgetItemV2; -class QOpenGLContext; class QStyle; @@ -130,9 +129,6 @@ struct QTLWExtra { QBackingStore *backingStore; QPainter *sharedPainter; QWidgetWindow *window; -#ifndef QT_NO_OPENGL - mutable std::unique_ptr<QOpenGLContext> shareContext; -#endif // Implicit pointers (shared_null). QString caption; // widget caption @@ -149,9 +145,7 @@ struct QTLWExtra { Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen QScreen *initialScreen; // Screen when passing a QDesktop[Screen]Widget as parent. -#ifndef QT_NO_OPENGL std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures; -#endif // *************************** Cross-platform bit fields **************************** uint opacity : 8; @@ -627,12 +621,11 @@ public: inline QRect mapFromWS(const QRect &r) const { return r.translated(data.wrect.topLeft()); } - QOpenGLContext *shareContext() const; - virtual QObject *focusObject() { return nullptr; } -#ifndef QT_NO_OPENGL - virtual GLuint textureId() const { return 0; } + virtual QPlatformBackingStoreRhiConfig rhiConfig() const { return {}; } + + virtual QRhiTexture *texture() const { return nullptr; } virtual QPlatformTextureList::Flags textureListFlags() { Q_Q(QWidget); return q->testAttribute(Qt::WA_AlwaysStackOnTop) @@ -667,7 +660,6 @@ public: virtual void resizeViewportFramebuffer() { } // Called after each paint event. virtual void resolveSamples() { } -#endif static void setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent); @@ -758,10 +750,8 @@ public: #ifndef QT_NO_IM uint inheritsInputMethodHints : 1; #endif -#ifndef QT_NO_OPENGL uint renderToTextureReallyDirty : 1; - uint renderToTextureComposeActive : 1; -#endif + uint usesRhiFlush : 1; uint childrenHiddenByWState : 1; uint childrenShownByExpose : 1; diff --git a/src/widgets/kernel/qwidgetrepaintmanager.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp index 16ff8ea721..1094c2c3b0 100644 --- a/src/widgets/kernel/qwidgetrepaintmanager.cpp +++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp @@ -65,12 +65,11 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_OPENGL Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList) // Watches one or more QPlatformTextureLists for changes in the lock state and // triggers a backingstore sync when all the registered lists turn into -// unlocked state. This is essential when a custom composeAndFlush() +// unlocked state. This is essential when a custom rhiFlush() // implementation in a platform plugin is not synchronous and keeps // holding on to the textures for some time even after returning from there. class QPlatformTextureListWatcher : public QObject @@ -105,7 +104,6 @@ private: QHash<QPlatformTextureList *, bool> m_locked; QWidgetRepaintManager *m_repaintManager; }; -#endif // --------------------------------------------------------------------------- @@ -374,7 +372,6 @@ void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime update qCInfo(lcWidgetPainting) << "Sending update request to" << widget << "with" << updateTime; -#ifndef QT_NO_OPENGL // Having every repaint() leading to a sync/flush is bad as it causes // compositing and waiting for vsync each and every time. Change to // UpdateLater, except for approx. once per frame to prevent starvation in @@ -392,7 +389,6 @@ void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime update updateTime = UpdateLater; } } -#endif switch (updateTime) { case UpdateLater: @@ -571,7 +567,6 @@ bool QWidgetRepaintManager::bltRect(const QRect &rect, int dx, int dy, QWidget * // --------------------------------------------------------------------------- -#ifndef QT_NO_OPENGL static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QList<QWidget *> *nativeChildren) @@ -580,7 +575,7 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, if (wd->renderToTexture) { QPlatformTextureList::Flags flags = wd->textureListFlags(); const QRect rect(widget->mapTo(tlw, QPoint()), widget->size()); - widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); + widgetTextures->appendTexture(widget, wd->texture(), rect, wd->clipRect(), flags); } for (int i = 0; i < wd->children.size(); ++i) { @@ -624,33 +619,12 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) } } - if (QWidgetPrivate::get(widget)->textureChildSeen) { - // No render-to-texture widgets in the (sub-)tree due to hidden or native - // children. Returning null results in using the normal backingstore flush path - // without OpenGL-based compositing. This is very desirable normally. However, - // some platforms cannot handle switching between the non-GL and GL paths for - // their windows so it has to be opt-in. - static bool switchableWidgetComposition = - QGuiApplicationPrivate::instance()->platformIntegration() - ->hasCapability(QPlatformIntegration::SwitchableWidgetComposition); - if (!switchableWidgetComposition) - return qt_dummy_platformTextureList(); - } + if (QWidgetPrivate::get(widget)->textureChildSeen) + return qt_dummy_platformTextureList(); return nullptr; } -#else - -static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) -{ - Q_UNUSED(tlw); - Q_UNUSED(widget); - return nullptr; -} - -#endif // QT_NO_OPENGL - // --------------------------------------------------------------------------- /*! @@ -725,7 +699,6 @@ bool QWidgetPrivate::shouldDiscardSyncRequest() const bool QWidgetRepaintManager::syncAllowed() { -#ifndef QT_NO_OPENGL QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (textureListWatcher && !textureListWatcher->isLocked()) { textureListWatcher->deleteLater(); @@ -744,7 +717,6 @@ bool QWidgetRepaintManager::syncAllowed() if (skipSync) // cannot compose due to widget textures being in use return false; } -#endif return true; } @@ -857,7 +829,6 @@ void QWidgetRepaintManager::paintAndFlush() } dirtyWidgets.clear(); -#ifndef QT_NO_OPENGL // Find all render-to-texture child widgets (including self). // The search is cut at native widget boundaries, meaning that each native child widget // has its own list for the subtree below it. @@ -865,13 +836,12 @@ void QWidgetRepaintManager::paintAndFlush() tlwExtra->widgetTextures.clear(); findAllTextureWidgetsRecursively(tlw, tlw); qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in flush() -#endif if (toClean.isEmpty()) { // Nothing to repaint. However renderToTexture widgets are handled // specially, they are not in the regular dirty list, in order to // prevent triggering unnecessary backingstore painting when only the - // OpenGL content changes. Check if we have such widgets in the special + // texture content changes. Check if we have such widgets in the special // dirty list. QVarLengthArray<QWidget *, 16> paintPending; const int numPaintPending = dirtyRenderToTextureWidgets.count(); @@ -903,7 +873,6 @@ void QWidgetRepaintManager::paintAndFlush() return; } -#ifndef QT_NO_OPENGL for (const auto &tl : tlwExtra->widgetTextures) { for (int i = 0; i < tl->count(); ++i) { QWidget *w = static_cast<QWidget *>(tl->source(i)); @@ -920,7 +889,6 @@ void QWidgetRepaintManager::paintAndFlush() for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) resetWidget(dirtyRenderToTextureWidgets.at(i)); dirtyRenderToTextureWidgets.clear(); -#endif #if QT_CONFIG(graphicsview) if (tlw->d_func()->extra->proxyWidget) { @@ -1046,12 +1014,10 @@ void QWidgetRepaintManager::flush() // Render-to-texture widgets are not in topLevelNeedsFlush so flush if we have not done it above. if (!flushed && !hasNeedsFlushWidgets) { -#ifndef QT_NO_OPENGL if (!tlw->d_func()->topData()->widgetTextures.empty()) { if (QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, tlw)) flush(tlw, QRegion(), widgetTextures); } -#endif } if (!hasNeedsFlushWidgets) @@ -1073,12 +1039,7 @@ void QWidgetRepaintManager::flush() */ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion ®ion, QPlatformTextureList *widgetTextures) { -#ifdef QT_NO_OPENGL - Q_UNUSED(widgetTextures); - Q_ASSERT(!region.isEmpty()); -#else Q_ASSERT(!region.isEmpty() || widgetTextures); -#endif Q_ASSERT(widget); Q_ASSERT(tlw); @@ -1091,8 +1052,6 @@ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion ®ion, QPlatf return; } - qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget; - static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS"); if (fpsDebug) { if (!perfFrames++) @@ -1108,40 +1067,37 @@ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion ®ion, QPlatf if (widget != tlw) offset += widget->mapTo(tlw, QPoint()); - QRegion effectiveRegion = region; -#ifndef QT_NO_OPENGL - const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive; - if (!widgetTextures) { - widget->d_func()->renderToTextureComposeActive = false; - // Detect the case of falling back to the normal flush path when no - // render-to-texture widgets are visible anymore. We will force one - // last flush to go through the OpenGL-based composition to prevent - // artifacts. The next flush after this one will use the normal path. - if (compositionWasActive) + if (widget->d_func()->usesRhiFlush) { + QRhi *rhi = store->handle()->rhi(); + qCDebug(lcWidgetPainting) << "Flushing" << region << "of" << widget + << "with QRhi" << rhi + << "to window" << widget->windowHandle(); + if (!widgetTextures) widgetTextures = qt_dummy_platformTextureList; - } else { - widget->d_func()->renderToTextureComposeActive = true; - } - // When changing the composition status, make sure the dirty region covers - // the entire widget. Just having e.g. the shown/hidden render-to-texture - // widget's area marked as dirty is incorrect when changing flush paths. - if (compositionWasActive != widget->d_func()->renderToTextureComposeActive) - effectiveRegion = widget->rect(); - - // re-test since we may have been forced to this path via the dummy texture list above - if (widgetTextures) { + qt_window_private(tlw->windowHandle())->compositing = true; - widget->window()->d_func()->sendComposeStatus(widget->window(), false); + QWidgetPrivate *widgetWindowPrivate = widget->window()->d_func(); + widgetWindowPrivate->sendComposeStatus(widget->window(), false); // A window may have alpha even when the app did not request // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends // to rely on translucency, in order to decide if it should clear to transparent or opaque. const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); - store->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, - widgetTextures, translucentBackground); - widget->window()->d_func()->sendComposeStatus(widget->window(), true); - } else -#endif - store->flush(effectiveRegion, widget->windowHandle(), offset); + + QPlatformBackingStore::FlushResult flushResult; + flushResult = store->handle()->rhiFlush(widget->windowHandle(), + region, + offset, + widgetTextures, + translucentBackground); + widgetWindowPrivate->sendComposeStatus(widget->window(), true); + if (flushResult == QPlatformBackingStore::FlushFailedDueToLostDevice) { + store->handle()->graphicsDeviceReportedLost(); + widget->update(); + } + } else { + qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget; + store->flush(region, widget->windowHandle(), offset); + } } // --------------------------------------------------------------------------- @@ -1353,6 +1309,11 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c } } +QRhi *QWidgetRepaintManager::rhi() const +{ + return store->handle()->rhi(); +} + QT_END_NAMESPACE #include "qwidgetrepaintmanager.moc" diff --git a/src/widgets/kernel/qwidgetrepaintmanager_p.h b/src/widgets/kernel/qwidgetrepaintmanager_p.h index 89f65e05bc..fe26d52bcb 100644 --- a/src/widgets/kernel/qwidgetrepaintmanager_p.h +++ b/src/widgets/kernel/qwidgetrepaintmanager_p.h @@ -62,8 +62,10 @@ QT_BEGIN_NAMESPACE class QPlatformTextureList; class QPlatformTextureListWatcher; class QWidgetRepaintManager; +class QRhi; +class QRhiSwapChain; -class Q_AUTOTEST_EXPORT QWidgetRepaintManager +class Q_WIDGETS_EXPORT QWidgetRepaintManager { Q_GADGET public: @@ -106,6 +108,8 @@ public: bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); + QRhi *rhi() const; + private: void updateLists(QWidget *widget); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 88818ce9c5..6524393ee1 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -108,9 +108,6 @@ public: } QRectF closestAcceptableGeometry(const QRectF &rect) const override; -#if QT_CONFIG(opengl) - QOpenGLContext *shareContext() const override; -#endif void processSafeAreaMarginsChanged() override { @@ -152,26 +149,19 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const return result; } -#if QT_CONFIG(opengl) -QOpenGLContext *QWidgetWindowPrivate::shareContext() const -{ - Q_Q(const QWidgetWindow); - const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget()); - return widgetPrivate->shareContext(); -} -#endif // opengl +bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType); QWidgetWindow::QWidgetWindow(QWidget *widget) : QWindow(*new QWidgetWindowPrivate(), nullptr) , m_widget(widget) { updateObjectName(); - // Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it, - // and the application developer has not explicitly disabled it. - if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface) - && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { - setSurfaceType(QSurface::RasterGLSurface); + if (!QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { + QSurface::SurfaceType type = QSurface::RasterSurface; + q_evaluateRhiConfig(m_widget, nullptr, &type); + setSurfaceType(type); } + connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange())); } diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 5484544444..b26bc68d19 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -204,8 +204,6 @@ QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent, Qt::Wi return new QWindowContainer(window, parent, flags); } - - /*! \internal */ @@ -219,13 +217,6 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: return; } - // The embedded QWindow must use the same logic as QWidget when it comes to the surface type. - // Otherwise we may end up with BadMatch failures on X11. - if (embeddedWindow->surfaceType() == QSurface::RasterSurface - && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface) - && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) - embeddedWindow->setSurfaceType(QSurface::RasterGLSurface); - d->window = embeddedWindow; QString windowName = d->window->objectName(); |