summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-10-25 15:21:31 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-03-11 21:25:00 +0100
commit68a4c5da9a080101cccd8a3b2edb1c908da0ca8e (patch)
treee89a8c02539147d30cb7529441d1a9e055163760 /src/opengl
parent8ccf1080fcb131940939369271e6828b178b8e9e (diff)
Compose render-to-texture widgets through QRhi
QPlatformTextureList holds a QRhiTexture instead of GLuint. A QPlatformBackingStore now optionally can own a QRhi and a QRhiSwapChain for the associated window. Non-GL rendering must use this QRhi everywhere, whereas GL (QOpenGLWidget) can choose to still rely on resource sharing between contexts. A widget tells that it wants QRhi and the desired configuration in a new virtual function in QWidgetPrivate returning a QPlatformBackingStoreRhiConfig. This is evaluated (among a top-level's all children) upon create() before creating the repaint manager and the QWidgetWindow. In QOpenGLWidget what do request is obvious: it will request an OpenGL-based QRhi. QQuickWidget (or a potential future QRhiWidget) will be more interesting: it needs to honor the standard Qt Quick env.vars. and QQuickWindow APIs (or, in whatever way the user configured the QRhiWidget), and so will set up the config struct accordingly. In addition, the rhiconfig and surface type is (re)evaluated when (re)parenting a widget to a new tlw. If needed, this will now trigger a destroy - create on the tlw. This should be be safe to do in setParent. When multiple child widgets report an enabled rhiconfig, the first one (the first child encountered) wins. So e.g. attempting to have a QOpenGLWidget and a Vulkan-based QQuickWidget in the same top-level window will fail one of the widgets (it likely won't render). RasterGLSurface is no longer used by widgets. Rather, the appropriate surface type is chosen. The rhi support in the backingstore is usable without widgets as well. To make rhiFlush() functional, one needs to call setRhiConfig() after creating the QBackingStore. (like QWidget does to top-level windows) Most of the QT_NO_OPENGL ifdefs are eliminated all over the place. Everything with QRhi is unconditional code at compile time, except the actual initialization. Having to plumb the widget tlw's shareContext (or, now, the QRhi) through QWindowPrivate is no longer needed. The old approach does not scale: to implement composeAndFlush (now rhiFlush) we need more than just a QRhi object, and this way we no longer pollute everything starting from the widget level (QWidget's topextra -> QWidgetWindow -> QWindowPrivate) just to send data around. The BackingStoreOpenGLSupport interface and the QtGui - QtOpenGL split is all gone. Instead, there is a QBackingStoreDefaultCompositor in QtGui which is what the default implementations of composeAndFlush and toTexture call. (overriding composeAndFlush and co. f.ex. in eglfs should continue working mostly as-is, apart from adapting to the texture list changes and getting the native OpenGL texture id out of the QRhiTexture) As QQuickWidget is way too complicated to just port as-is, an rhi manual test (rhiwidget) is introduced as a first step, in ordewr to exercise a simple, custom render-to-texture widget that does something using a (not necessarily OpenGL-backed) QRhi and acts as fully functional QWidget (modeled after QOpenGLWidget). This can also form the foundation of a potential future QRhiWidget. It is also possible to force the QRhi-based flushing always, regardless of the presence of render-to-texture widgets. To exercise this, set the env.var. QT_WIDGETS_RHI=1. This picks a platform-specific default, and can be overridden with QT_WIDGETS_RHI_BACKEND. (in sync with Qt Quick) This can eventually be extended to query the platform plugin as well to check if the platform plugin prefers to always do flushes with a 3D API. QOpenGLWidget should work like before from the user's perspective, while internally it has to do some things differently to play nice and prevent regressions with the new rendering architecture. To exercise this better, the qopenglwidget example gets a new tab-based view (that could perhaps replace the example's main window later on?). The openglwidget manual test is made compatible with Qt 6, and gets a counterpart in form of the dockedopenglwidget manual test, which is a modified version of the cube example that features dock widgets. This is relevant in particular because render-to-texture widgets within a QDockWidget has its own specific quirks, with logic taking this into account, hence testing is essential. For existing applications there are two important consequences with this patch in place: - Once the rhi-based composition is enabled, it stays active for the lifetime of the top-level window. - Dynamically creating and parenting the first render-to-texture widget to an already created tlw will destroy and recreate the tlw (and the underlying window). The visible effects of this depend on the platform. (e.g. the window may disappear and reappear on some, whereas with other windowing systems it is not noticeable at all - this is not really different from similar situtions with reparenting or when moving windows between screens, so should be acceptable in practice) - On iOS raster windows are flushed with Metal (and rhi) from now on (previously this was through OpenGL by making flush() call composeAndFlush(). Change-Id: Id05bd0f7a26fa845f8b7ad8eedda3b0e78ab7a4e Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/CMakeLists.txt1
-rw-r--r--src/opengl/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp8
-rw-r--r--src/opengl/qopenglcompositor.cpp6
-rw-r--r--src/opengl/qopenglcompositorbackingstore.cpp42
-rw-r--r--src/opengl/qopenglcompositorbackingstore_p.h8
-rw-r--r--src/opengl/qplatformbackingstoreopenglsupport.cpp465
-rw-r--r--src/opengl/qplatformbackingstoreopenglsupport.h87
7 files changed, 45 insertions, 572 deletions
diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt
index 03ace0cad7..f9eb5e36a3 100644
--- a/src/opengl/CMakeLists.txt
+++ b/src/opengl/CMakeLists.txt
@@ -30,7 +30,6 @@ qt_internal_add_module(OpenGL
qopenglversionprofile.cpp qopenglversionprofile.h
qopenglvertexarrayobject.cpp qopenglvertexarrayobject.h
qopenglwindow.cpp qopenglwindow.h
- qplatformbackingstoreopenglsupport.cpp qplatformbackingstoreopenglsupport.h
qtopenglglobal.h
DEFINES
QT_NO_FOREACH
diff --git a/src/opengl/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp b/src/opengl/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp
index 633a413b4f..c1bf6731c7 100644
--- a/src/opengl/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp
+++ b/src/opengl/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp
@@ -173,9 +173,14 @@ void MyGLWidget::initializeGL()
//! [4]
//! [5]
+MyGLWidget::~MyGLWidget()
+{
+ cleanup();
+}
+
void MyGLWidget::initializeGL()
{
- // context() and QOpenGLContext::currentContext() are equivalent when called from initializeGL or paintGL.
+ ...
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &MyGLWidget::cleanup);
}
@@ -186,6 +191,7 @@ void MyGLWidget::cleanup()
m_texture = 0;
...
doneCurrent();
+ disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &MyGLWidget::cleanup);
}
//! [5]
diff --git a/src/opengl/qopenglcompositor.cpp b/src/opengl/qopenglcompositor.cpp
index abfaca3f9c..a5fe4dda30 100644
--- a/src/opengl/qopenglcompositor.cpp
+++ b/src/opengl/qopenglcompositor.cpp
@@ -40,6 +40,7 @@
#include <QtOpenGL/QOpenGLFramebufferObject>
#include <QtGui/QOpenGLContext>
#include <QtGui/QWindow>
+#include <QtGui/private/qrhi_p.h>
#include <qpa/qplatformbackingstore.h>
#include "qopenglcompositor_p.h"
@@ -207,7 +208,8 @@ static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRe
const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(),
QOpenGLTextureBlitter::OriginBottomLeft);
- blitter->blit(textures->textureId(idx), target, source);
+ const uint textureId = textures->texture(idx)->nativeTexture().object;
+ blitter->blit(textureId, target, source);
}
void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
@@ -221,7 +223,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
BlendStateBinder blend;
const QRect sourceWindowRect = window->sourceWindow()->geometry();
for (int i = 0; i < textures->count(); ++i) {
- uint textureId = textures->textureId(i);
+ const uint textureId = textures->texture(i)->nativeTexture().object;
const float opacity = window->sourceWindow()->opacity();
if (opacity != currentOpacity) {
currentOpacity = opacity;
diff --git a/src/opengl/qopenglcompositorbackingstore.cpp b/src/opengl/qopenglcompositorbackingstore.cpp
index 34542dde47..ed4a0ffb3c 100644
--- a/src/opengl/qopenglcompositorbackingstore.cpp
+++ b/src/opengl/qopenglcompositorbackingstore.cpp
@@ -43,6 +43,7 @@
#include <QtGui/QOffscreenSurface>
#include <qpa/qplatformbackingstore.h>
#include <private/qwindow_p.h>
+#include <private/qrhi_p.h>
#include "qopenglcompositorbackingstore_p.h"
#include "qopenglcompositor_p.h"
@@ -79,9 +80,11 @@ QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)
: QPlatformBackingStore(window),
m_window(window),
m_bsTexture(0),
+ m_bsTextureWrapper(nullptr),
m_bsTextureContext(0),
m_textures(new QPlatformTextureList),
- m_lockedWidgetTextures(0)
+ m_lockedWidgetTextures(0),
+ m_rhi(nullptr)
{
}
@@ -103,10 +106,12 @@ QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()
}
}
- if (m_bsTextureContext && ctx && ctx->shareGroup() == m_bsTextureContext->shareGroup())
+ if (m_bsTextureContext && ctx && ctx->shareGroup() == m_bsTextureContext->shareGroup()) {
+ delete m_bsTextureWrapper;
glDeleteTextures(1, &m_bsTexture);
- else
+ } else {
qWarning("QOpenGLCompositorBackingStore: Texture is not valid in the current context");
+ }
if (tempSurface && ctx)
ctx->doneCurrent();
@@ -132,6 +137,8 @@ void QOpenGLCompositorBackingStore::updateTexture()
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
+ m_bsTextureWrapper->createFrom({m_bsTexture, 0});
} else {
glBindTexture(GL_TEXTURE_2D, m_bsTexture);
}
@@ -198,14 +205,16 @@ void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion &region
dstCtx->makeCurrent(dstWin);
updateTexture();
m_textures->clear();
- m_textures->appendTexture(nullptr, m_bsTexture, window->geometry());
+ m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
compositor->update();
}
-void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
- QPlatformTextureList *textures,
- bool translucentBackground)
+QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWindow *window,
+ const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures,
+ bool translucentBackground)
{
// QOpenGLWidget/QQuickWidget content provided as textures. The raster content goes on top.
@@ -213,34 +222,35 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
Q_UNUSED(offset);
Q_UNUSED(translucentBackground);
+ m_rhi = rhi();
+
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
QOpenGLContext *dstCtx = compositor->context();
Q_ASSERT(dstCtx); // setTarget() must have been called before, e.g. from QEGLFSWindow
- // The compositor's context and the context to which QOpenGLWidget/QQuickWidget
- // textures belong are not the same. They share resources, though.
- Q_ASSERT(qt_window_private(window)->shareContext()->shareGroup() == dstCtx->shareGroup());
-
QWindow *dstWin = compositor->targetWindow();
if (!dstWin)
- return;
+ return FlushFailed;
dstCtx->makeCurrent(dstWin);
QWindowPrivate::get(window)->lastComposeTime.start();
m_textures->clear();
- for (int i = 0; i < textures->count(); ++i)
- m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
+ for (int i = 0; i < textures->count(); ++i) {
+ m_textures->appendTexture(textures->source(i), textures->texture(i), textures->geometry(i),
textures->clipRect(i), textures->flags(i));
+ }
updateTexture();
- m_textures->appendTexture(nullptr, m_bsTexture, window->geometry());
+ m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
textures->lock(true);
m_lockedWidgetTextures = textures;
compositor->update();
+
+ return FlushSuccess;
}
void QOpenGLCompositorBackingStore::notifyComposited()
@@ -280,6 +290,8 @@ void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &sta
dstCtx->makeCurrent(dstWin);
if (m_bsTexture) {
+ delete m_bsTextureWrapper;
+ m_bsTextureWrapper = nullptr;
glDeleteTextures(1, &m_bsTexture);
m_bsTexture = 0;
m_bsTextureContext = nullptr;
diff --git a/src/opengl/qopenglcompositorbackingstore_p.h b/src/opengl/qopenglcompositorbackingstore_p.h
index 6c61ab1bff..e8be9eef9e 100644
--- a/src/opengl/qopenglcompositorbackingstore_p.h
+++ b/src/opengl/qopenglcompositorbackingstore_p.h
@@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE
class QOpenGLContext;
class QPlatformTextureList;
+class QRhiTexture;
class Q_OPENGL_EXPORT QOpenGLCompositorBackingStore : public QPlatformBackingStore
{
@@ -77,7 +78,10 @@ public:
void resize(const QSize &size, const QRegion &staticContents) override;
QImage toImage() const override;
- void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+
+ FlushResult rhiFlush(QWindow *window,
+ const QRegion &region,
+ const QPoint &offset,
QPlatformTextureList *textures,
bool translucentBackground) override;
@@ -92,9 +96,11 @@ private:
QImage m_image;
QRegion m_dirty;
uint m_bsTexture;
+ QRhiTexture *m_bsTextureWrapper;
QOpenGLContext *m_bsTextureContext;
QPlatformTextureList *m_textures;
QPlatformTextureList *m_lockedWidgetTextures;
+ QRhi *m_rhi;
};
QT_END_NAMESPACE
diff --git a/src/opengl/qplatformbackingstoreopenglsupport.cpp b/src/opengl/qplatformbackingstoreopenglsupport.cpp
deleted file mode 100644
index 30532c5b4b..0000000000
--- a/src/opengl/qplatformbackingstoreopenglsupport.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT_NO_OPENGL
-
-#include "qplatformbackingstoreopenglsupport.h"
-
-#include <QtGui/private/qwindow_p.h>
-
-#include <qpa/qplatformgraphicsbuffer.h>
-#include <qpa/qplatformgraphicsbufferhelper.h>
-
-#include <QtOpenGL/QOpenGLTextureBlitter>
-#include <QtGui/qopengl.h>
-#include <QtGui/QOpenGLFunctions>
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOffscreenSurface>
-
-#ifndef GL_TEXTURE_BASE_LEVEL
-#define GL_TEXTURE_BASE_LEVEL 0x813C
-#endif
-#ifndef GL_TEXTURE_MAX_LEVEL
-#define GL_TEXTURE_MAX_LEVEL 0x813D
-#endif
-#ifndef GL_UNPACK_ROW_LENGTH
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-#endif
-#ifndef GL_RGB10_A2
-#define GL_RGB10_A2 0x8059
-#endif
-#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#endif
-
-#ifndef GL_FRAMEBUFFER_SRGB
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
-#endif
-#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE
-#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static inline QRect deviceRect(const QRect &rect, QWindow *window)
-{
- QRect deviceRect(rect.topLeft() * window->devicePixelRatio(),
- rect.size() * window->devicePixelRatio());
- return deviceRect;
-}
-
-static inline QPoint deviceOffset(const QPoint &pt, QWindow *window)
-{
- return pt * window->devicePixelRatio();
-}
-
-static QRegion deviceRegion(const QRegion &region, QWindow *window, const QPoint &offset)
-{
- if (offset.isNull() && window->devicePixelRatio() <= 1)
- return region;
-
- QVarLengthArray<QRect, 4> rects;
- rects.reserve(region.rectCount());
- for (const QRect &rect : region)
- rects.append(deviceRect(rect.translated(offset), window));
-
- QRegion deviceRegion;
- deviceRegion.setRects(rects.constData(), rects.count());
- return deviceRegion;
-}
-
-static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
-{
- return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
- topLeftRect.width(), topLeftRect.height());
-}
-
-static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
- QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb)
-{
- const QRect clipRect = textures->clipRect(idx);
- if (clipRect.isEmpty())
- return;
-
- QRect rectInWindow = textures->geometry(idx);
- // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust
- rectInWindow.translate(-offset);
-
- const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
- const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
-
- const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(deviceRect(clippedRectInWindow, window),
- deviceWindowRect);
-
- const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window),
- deviceRect(rectInWindow, window).size(),
- QOpenGLTextureBlitter::OriginBottomLeft);
-
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb);
- if (srgb && canUseSrgb)
- funcs->glEnable(GL_FRAMEBUFFER_SRGB);
-
- blitter->blit(textures->textureId(idx), target, source);
-
- if (srgb && canUseSrgb)
- funcs->glDisable(GL_FRAMEBUFFER_SRGB);
-}
-
-QPlatformBackingStoreOpenGLSupport::~QPlatformBackingStoreOpenGLSupport() {
- if (context) {
- QOffscreenSurface offscreenSurface;
- offscreenSurface.setFormat(context->format());
- offscreenSurface.create();
- context->makeCurrent(&offscreenSurface);
- if (textureId)
- context->functions()->glDeleteTextures(1, &textureId);
- if (blitter)
- blitter->destroy();
- }
- delete blitter;
-}
-
-void QPlatformBackingStoreOpenGLSupport::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground)
-{
- if (!qt_window_private(window)->receivedExpose)
- return;
-
- if (!context) {
- context.reset(new QOpenGLContext);
- context->setFormat(window->requestedFormat());
- context->setScreen(window->screen());
- context->setShareContext(qt_window_private(window)->shareContext());
- if (!context->create()) {
- qCWarning(lcQpaBackingStore, "composeAndFlush: QOpenGLContext creation failed");
- return;
- }
- }
-
- bool current = context->makeCurrent(window);
-
- if (!current && !context->isValid()) {
- // release resources and attempt to reinitialize upon context loss
- delete blitter;
- blitter = nullptr;
- textureId = 0;
- current = context->create() && context->makeCurrent(window);
- }
-
- if (!current) {
- qCWarning(lcQpaBackingStore, "composeAndFlush: makeCurrent() failed");
- return;
- }
-
- qCDebug(lcQpaBackingStore) << "Composing and flushing" << region << "of" << window
- << "at offset" << offset << "with" << textures->count() << "texture(s) in" << textures;
-
- QWindowPrivate::get(window)->lastComposeTime.start();
-
- QOpenGLFunctions *funcs = context->functions();
- funcs->glViewport(0, 0, qRound(window->width() * window->devicePixelRatio()), qRound(window->height() * window->devicePixelRatio()));
- funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1);
- funcs->glClear(GL_COLOR_BUFFER_BIT);
-
- if (!blitter) {
- blitter = new QOpenGLTextureBlitter;
- blitter->create();
- }
-
- blitter->bind();
-
- const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window);
- const QPoint deviceWindowOffset = deviceOffset(offset, window);
-
- bool canUseSrgb = false;
- // If there are any sRGB textures in the list, check if the destination
- // framebuffer is sRGB capable.
- for (int i = 0; i < textures->count(); ++i) {
- if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) {
- GLint cap = 0;
- funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap);
- if (cap)
- canUseSrgb = true;
- break;
- }
- }
-
- // Textures for renderToTexture widgets.
- for (int i = 0; i < textures->count(); ++i) {
- if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, blitter, offset, canUseSrgb);
- }
-
- // Backingstore texture with the normal widgets.
- GLuint textureId = 0;
- QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft;
- if (QPlatformGraphicsBuffer *graphicsBuffer = backingStore->graphicsBuffer()) {
- if (graphicsBuffer->size() != textureSize) {
- if (this->textureId)
- funcs->glDeleteTextures(1, &this->textureId);
- funcs->glGenTextures(1, &this->textureId);
- funcs->glBindTexture(GL_TEXTURE_2D, this->textureId);
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- }
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &needsSwizzle, &premultiplied)) {
- textureSize = graphicsBuffer->size();
- } else {
- textureSize = QSize(0,0);
- }
-
- graphicsBuffer->unlock();
- } else if (!region.isEmpty()){
- funcs->glBindTexture(GL_TEXTURE_2D, this->textureId);
- QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &needsSwizzle, &premultiplied);
- graphicsBuffer->unlock();
- }
-
- if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)
- origin = QOpenGLTextureBlitter::OriginBottomLeft;
- textureId = this->textureId;
- } else {
- QPlatformBackingStore::TextureFlags flags;
- textureId = backingStore->toTexture(deviceRegion(region, window, offset), &textureSize, &flags);
- needsSwizzle = (flags & QPlatformBackingStore::TextureSwizzle) != 0;
- premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0;
- if (flags & QPlatformBackingStore::TextureFlip)
- origin = QOpenGLTextureBlitter::OriginBottomLeft;
- }
-
- funcs->glEnable(GL_BLEND);
- if (premultiplied)
- funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
- else
- funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
-
- if (textureId) {
- if (needsSwizzle)
- blitter->setRedBlueSwizzle(true);
- // The backingstore is for the entire tlw.
- // In case of native children offset tells the position relative to the tlw.
- const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(deviceWindowOffset), textureSize.height());
- const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect,
- textureSize,
- origin);
- blitter->blit(textureId, QMatrix4x4(), source);
- if (needsSwizzle)
- blitter->setRedBlueSwizzle(false);
- }
-
- // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
- bool blendIsPremultiplied = premultiplied;
- for (int i = 0; i < textures->count(); ++i) {
- const QPlatformTextureList::Flags flags = textures->flags(i);
- if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending)) {
- if (!blendIsPremultiplied) {
- funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
- blendIsPremultiplied = true;
- }
- } else {
- if (blendIsPremultiplied) {
- funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
- blendIsPremultiplied = false;
- }
- }
- if (flags.testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, blitter, offset, canUseSrgb);
- }
-
- funcs->glDisable(GL_BLEND);
- blitter->release();
-
- context->swapBuffers(window);
-}
-
-GLuint QPlatformBackingStoreOpenGLSupport::toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const
-{
- Q_ASSERT(textureSize);
- Q_ASSERT(flags);
-
- QImage image = backingStore->toImage();
- QSize imageSize = image.size();
-
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- GLenum internalFormat = GL_RGBA;
- GLuint pixelType = GL_UNSIGNED_BYTE;
-
- bool needsConversion = false;
- *flags = { };
- switch (image.format()) {
- case QImage::Format_ARGB32_Premultiplied:
- *flags |= QPlatformBackingStore::TexturePremultiplied;
- Q_FALLTHROUGH();
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32:
- *flags |= QPlatformBackingStore::TextureSwizzle;
- break;
- case QImage::Format_RGBA8888_Premultiplied:
- *flags |= QPlatformBackingStore::TexturePremultiplied;
- Q_FALLTHROUGH();
- case QImage::Format_RGBX8888:
- case QImage::Format_RGBA8888:
- break;
- case QImage::Format_BGR30:
- case QImage::Format_A2BGR30_Premultiplied:
- if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
- pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
- internalFormat = GL_RGB10_A2;
- *flags |= QPlatformBackingStore::TexturePremultiplied;
- } else {
- needsConversion = true;
- }
- break;
- case QImage::Format_RGB30:
- case QImage::Format_A2RGB30_Premultiplied:
- if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
- pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
- internalFormat = GL_RGB10_A2;
- *flags |= QPlatformBackingStore::TextureSwizzle | QPlatformBackingStore::TexturePremultiplied;
- } else {
- needsConversion = true;
- }
- break;
- default:
- needsConversion = true;
- break;
- }
- if (imageSize.isEmpty()) {
- *textureSize = imageSize;
- return 0;
- }
-
- // Must rely on the input only, not d_ptr.
- // With the default composeAndFlush() textureSize is &d_ptr->textureSize.
- bool resized = *textureSize != imageSize;
- if (dirtyRegion.isEmpty() && !resized)
- return textureId;
-
- *textureSize = imageSize;
-
- if (needsConversion)
- image = image.convertToFormat(QImage::Format_RGBA8888);
-
- // The image provided by the backingstore may have a stride larger than width * 4, for
- // instance on platforms that manually implement client-side decorations.
- static const int bytesPerPixel = 4;
- const qsizetype strideInPixels = image.bytesPerLine() / bytesPerPixel;
- const bool hasUnpackRowLength = !ctx->isOpenGLES() || ctx->format().majorVersion() >= 3;
-
- QOpenGLFunctions *funcs = ctx->functions();
-
- if (hasUnpackRowLength) {
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, strideInPixels);
- } else if (strideInPixels != image.width()) {
- // No UNPACK_ROW_LENGTH on ES 2.0 and yet we would need it. This case is typically
- // hit with QtWayland which is rarely used in combination with a ES2.0-only GL
- // implementation. Therefore, accept the performance hit and do a copy.
- image = image.copy();
- }
-
- if (resized) {
- if (textureId)
- funcs->glDeleteTextures(1, &textureId);
- funcs->glGenTextures(1, &textureId);
- funcs->glBindTexture(GL_TEXTURE_2D, textureId);
- if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- }
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, imageSize.width(), imageSize.height(), 0, GL_RGBA, pixelType,
- const_cast<uchar*>(image.constBits()));
- } else {
- funcs->glBindTexture(GL_TEXTURE_2D, textureId);
- QRect imageRect = image.rect();
- QRect rect = dirtyRegion.boundingRect() & imageRect;
-
- if (hasUnpackRowLength) {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
- image.constScanLine(rect.y()) + rect.x() * bytesPerPixel);
- } else {
- // if the rect is wide enough it's cheaper to just
- // extend it instead of doing an image copy
- if (rect.width() >= imageRect.width() / 2) {
- rect.setX(0);
- rect.setWidth(imageRect.width());
- }
-
- // if the sub-rect is full-width we can pass the image data directly to
- // OpenGL instead of copying, since there's no gap between scanlines
-
- if (rect.width() == imageRect.width()) {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
- image.constScanLine(rect.y()));
- } else {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
- image.copy(rect).constBits());
- }
- }
- }
-
- if (hasUnpackRowLength)
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
- return textureId;
-}
-
-void qt_registerDefaultPlatformBackingStoreOpenGLSupport()
-{
- if (!QPlatformBackingStoreOpenGLSupportBase::factoryFunction()) {
- QPlatformBackingStoreOpenGLSupportBase::setFactoryFunction([]() -> QPlatformBackingStoreOpenGLSupportBase* {
- return new QPlatformBackingStoreOpenGLSupport;
- });
- }
-}
-
-#endif // QT_NO_OPENGL
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qplatformbackingstoreopenglsupport.h b/src/opengl/qplatformbackingstoreopenglsupport.h
deleted file mode 100644
index ae9d972c6a..0000000000
--- a/src/opengl/qplatformbackingstoreopenglsupport.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPLATFORMBACKINGSTOREOPENGLSUPPORT_H
-#define QPLATFORMBACKINGSTOREOPENGLSUPPORT_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is part of the QPA API and is not meant to be used
-// in applications. Usage of this API may make your code
-// source and binary incompatible with future versions of Qt.
-//
-
-#ifndef QT_NO_OPENGL
-
-#include <QtOpenGL/qtopenglglobal.h>
-#include <qpa/qplatformbackingstore.h>
-
-#include <QtGui/QOpenGLContext>
-
-QT_BEGIN_NAMESPACE
-
-class QOpenGLTextureBlitter;
-class QOpenGLBackingStore;
-
-class Q_OPENGL_EXPORT QPlatformBackingStoreOpenGLSupport : public QPlatformBackingStoreOpenGLSupportBase
-{
-public:
- ~QPlatformBackingStoreOpenGLSupport() override;
- void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
- QPlatformTextureList *textures, bool translucentBackground) override;
- GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const override;
-
-private:
- QScopedPointer<QOpenGLContext> context;
- mutable GLuint textureId = 0;
- mutable QSize textureSize;
- mutable bool needsSwizzle = false;
- mutable bool premultiplied = false;
- QOpenGLTextureBlitter *blitter = nullptr;
-};
-
-Q_OPENGL_EXPORT void qt_registerDefaultPlatformBackingStoreOpenGLSupport();
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_OPENGL
-
-#endif // QPLATFORMBACKINGSTOREOPENGLSUPPORT_H