OpenGL: Add parameters to choose FBO grab orientation

We want to be able to pass as an argument whether the texture grabbed to
an FBO is supposed to have a flipped y-axis or not. This is required for
screen capture on the EGLFS platform.

Task-number: QTBUG-121835
Pick-to: 6.6 6.5
Change-Id: I6dddc879a4be7ff2c2c189747193423644be55a0
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
(cherry picked from commit 342ae435a198acdd794e575dc54ccab1d33b320b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Mikko Hallamaa 2024-02-15 10:58:40 +01:00 committed by Qt Cherry-pick Bot
parent 2a0d34373e
commit d33437c4f9
2 changed files with 31 additions and 16 deletions

View File

@ -90,7 +90,7 @@ QImage QOpenGLCompositor::grab()
return fbo.toImage(); return fbo.toImage();
} }
bool QOpenGLCompositor::grabToFrameBufferObject(QOpenGLFramebufferObject *fbo) bool QOpenGLCompositor::grabToFrameBufferObject(QOpenGLFramebufferObject *fbo, GrabOrientation orientation)
{ {
Q_ASSERT(fbo); Q_ASSERT(fbo);
if (fbo->size() != m_nativeTargetGeometry.size() if (fbo->size() != m_nativeTargetGeometry.size()
@ -98,7 +98,9 @@ bool QOpenGLCompositor::grabToFrameBufferObject(QOpenGLFramebufferObject *fbo)
return false; return false;
m_context->makeCurrent(m_targetWindow); m_context->makeCurrent(m_targetWindow);
renderAll(fbo); renderAll(fbo,
orientation == Flipped ? QOpenGLTextureBlitter::OriginTopLeft
: QOpenGLTextureBlitter::OriginBottomLeft);
return true; return true;
} }
@ -109,7 +111,7 @@ void QOpenGLCompositor::handleRenderAllRequest()
renderAll(0); renderAll(0);
} }
void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo) void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo, QOpenGLTextureBlitter::Origin origin)
{ {
if (fbo) if (fbo)
fbo->bind(); fbo->bind();
@ -126,7 +128,7 @@ void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo)
m_windows.at(i)->beginCompositing(); m_windows.at(i)->beginCompositing();
for (int i = 0; i < m_windows.size(); ++i) for (int i = 0; i < m_windows.size(); ++i)
render(m_windows.at(i)); render(m_windows.at(i), origin);
m_blitter.release(); m_blitter.release();
if (!fbo) if (!fbo)
@ -167,9 +169,10 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height()); topLeftRect.width(), topLeftRect.height());
} }
static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &sourceWindowRect, static void clippedBlit(const QPlatformTextureList *textures, int idx,
const QRect &targetWindowRect, const QRect &sourceWindowRect, const QRect &targetWindowRect,
QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix) QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix,
QOpenGLTextureBlitter::Origin sourceOrigin)
{ {
const QRect clipRect = textures->clipRect(idx); const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty()) if (clipRect.isEmpty())
@ -184,13 +187,13 @@ static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRe
target = *rotationMatrix * target; target = *rotationMatrix * target;
const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(), const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(),
QOpenGLTextureBlitter::OriginBottomLeft); sourceOrigin);
const uint textureId = textures->texture(idx)->nativeTexture().object; const uint textureId = textures->texture(idx)->nativeTexture().object;
blitter->blit(textureId, target, source); blitter->blit(textureId, target, source);
} }
void QOpenGLCompositor::render(QOpenGLCompositorWindow *window) void QOpenGLCompositor::render(QOpenGLCompositorWindow *window, QOpenGLTextureBlitter::Origin origin)
{ {
const QPlatformTextureList *textures = window->textures(); const QPlatformTextureList *textures = window->textures();
if (!textures) if (!textures)
@ -200,6 +203,9 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
float currentOpacity = 1.0f; float currentOpacity = 1.0f;
BlendStateBinder blend; BlendStateBinder blend;
const QRect sourceWindowRect = window->sourceWindow()->geometry(); const QRect sourceWindowRect = window->sourceWindow()->geometry();
auto clippedBlitSourceOrigin = origin == QOpenGLTextureBlitter::OriginTopLeft
? QOpenGLTextureBlitter::OriginBottomLeft
: QOpenGLTextureBlitter::OriginTopLeft;
for (int i = 0; i < textures->count(); ++i) { for (int i = 0; i < textures->count(); ++i) {
const uint textureId = textures->texture(i)->nativeTexture().object; const uint textureId = textures->texture(i)->nativeTexture().object;
const float opacity = window->sourceWindow()->opacity(); const float opacity = window->sourceWindow()->opacity();
@ -214,7 +220,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
if (m_rotation) if (m_rotation)
target = m_rotationMatrix * target; target = m_rotationMatrix * target;
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); m_blitter.blit(textureId, target, origin);
} else if (textures->count() == 1) { } else if (textures->count() == 1) {
// A regular QWidget window // A regular QWidget window
const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0; const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0;
@ -222,18 +228,20 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
if (m_rotation) if (m_rotation)
target = m_rotationMatrix * target; target = m_rotationMatrix * target;
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); m_blitter.blit(textureId, target, origin);
} else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { } else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
// Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget // Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget
blend.set(false); blend.set(false);
clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter,
m_rotation ? &m_rotationMatrix : nullptr, clippedBlitSourceOrigin);
} }
} }
for (int i = 0; i < textures->count(); ++i) { for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
blend.set(true); blend.set(true);
clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter,
m_rotation ? &m_rotationMatrix : nullptr, clippedBlitSourceOrigin);
} }
} }

View File

@ -47,6 +47,11 @@ class Q_OPENGL_EXPORT QOpenGLCompositor : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum GrabOrientation {
Flipped,
NotFlipped,
};
static QOpenGLCompositor *instance(); static QOpenGLCompositor *instance();
static void destroy(); static void destroy();
@ -60,7 +65,7 @@ public:
void update(); void update();
QImage grab(); QImage grab();
bool grabToFrameBufferObject(QOpenGLFramebufferObject *fbo); bool grabToFrameBufferObject(QOpenGLFramebufferObject *fbo, GrabOrientation orientation = Flipped);
QList<QOpenGLCompositorWindow *> windows() const { return m_windows; } QList<QOpenGLCompositorWindow *> windows() const { return m_windows; }
void addWindow(QOpenGLCompositorWindow *window); void addWindow(QOpenGLCompositorWindow *window);
@ -78,8 +83,10 @@ private:
QOpenGLCompositor(); QOpenGLCompositor();
~QOpenGLCompositor(); ~QOpenGLCompositor();
void renderAll(QOpenGLFramebufferObject *fbo); void renderAll(QOpenGLFramebufferObject *fbo,
void render(QOpenGLCompositorWindow *window); QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft);
void render(QOpenGLCompositorWindow *window,
QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft);
void ensureCorrectZOrder(); void ensureCorrectZOrder();
QOpenGLContext *m_context; QOpenGLContext *m_context;