From 16809e6b15db15ef2ae30ce9d1dfcbcaef50ad54 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 20 Dec 2023 12:12:16 +0200 Subject: [PATCH] core: Port RenderTarget to OutputTransform --- src/compositor_wayland.cpp | 11 ++-- src/core/output.cpp | 43 ------------- src/core/output.h | 6 -- src/core/rendertarget.cpp | 71 ++++++++++----------- src/core/rendertarget.h | 11 +--- src/core/renderviewport.cpp | 18 ++++-- src/core/renderviewport.h | 5 +- src/opengl/gltexture.h | 2 + src/plugins/backgroundcontrast/contrast.cpp | 2 +- src/plugins/glide/glide.cpp | 2 +- src/plugins/screenshot/screenshot.cpp | 16 ++--- src/scene/cursordelegate_opengl.cpp | 2 +- 12 files changed, 69 insertions(+), 120 deletions(-) diff --git a/src/compositor_wayland.cpp b/src/compositor_wayland.cpp index c6504ba029..a8ea264b43 100644 --- a/src/compositor_wayland.cpp +++ b/src/compositor_wayland.cpp @@ -291,18 +291,17 @@ void WaylandCompositor::addOutput(Output *output) if (!outputLayer || forceSoftwareCursor) { return false; } - const QMatrix4x4 monitorMatrix = Output::logicalToNativeMatrix(output->rect(), output->scale(), output->transform()); - QRectF nativeCursorRect = monitorMatrix.mapRect(outputLocalRect); + QRectF nativeCursorRect = output->transform().map(scaledRect(outputLocalRect, output->scale()), output->pixelSize()); QSize bufferSize(std::ceil(nativeCursorRect.width()), std::ceil(nativeCursorRect.height())); if (const auto fixedSize = outputLayer->fixedSize()) { if (fixedSize->width() < bufferSize.width() || fixedSize->height() < bufferSize.height()) { return false; } bufferSize = *fixedSize; - nativeCursorRect = monitorMatrix.mapRect(QRectF(outputLocalRect.topLeft(), QSizeF(bufferSize) / output->scale())); + nativeCursorRect = output->transform().map(QRectF(outputLocalRect.topLeft() * output->scale(), bufferSize), output->pixelSize()); } outputLayer->setPosition(nativeCursorRect.topLeft()); - outputLayer->setHotspot(Output::logicalToNativeMatrix(QRectF(QPointF(), QSizeF(bufferSize) / output->scale()), output->scale(), output->transform()).map(cursor->hotspot())); + outputLayer->setHotspot(output->transform().map(cursor->hotspot() * output->scale(), bufferSize)); outputLayer->setSize(bufferSize); if (auto beginInfo = outputLayer->beginFrame()) { const RenderTarget &renderTarget = beginInfo->renderTarget; @@ -345,8 +344,8 @@ void WaylandCompositor::addOutput(Output *output) bool hardwareCursor = false; if (outputLayer) { if (outputLayer->isEnabled()) { - const QMatrix4x4 monitorMatrix = Output::logicalToNativeMatrix(output->rect(), output->scale(), output->transform()); - const QRectF nativeCursorRect = monitorMatrix.mapRect(QRectF(outputLocalRect.topLeft(), outputLayer->size() / output->scale())); + const QRectF nativeCursorRect = output->transform() + .map(QRectF(outputLocalRect.topLeft() * output->scale(), outputLayer->size()), output->pixelSize()); outputLayer->setPosition(nativeCursorRect.topLeft()); hardwareCursor = output->updateCursorLayer(); } else if (!cursorLayer->isVisible() && !forceSoftwareCursor) { diff --git a/src/core/output.cpp b/src/core/output.cpp index 2b98afc9c2..483d06584c 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -646,49 +646,6 @@ Output::DpmsMode Output::dpmsMode() const return m_state.dpmsMode; } -QMatrix4x4 Output::logicalToNativeMatrix(const QRectF &rect, qreal scale, OutputTransform transform) -{ - QMatrix4x4 matrix; - matrix.scale(scale); - - switch (transform.kind()) { - case OutputTransform::Normal: - case OutputTransform::FlipX: - break; - case OutputTransform::Rotate90: - case OutputTransform::FlipX90: - matrix.translate(0, rect.width()); - matrix.rotate(-90, 0, 0, 1); - break; - case OutputTransform::Rotate180: - case OutputTransform::FlipX180: - matrix.translate(rect.width(), rect.height()); - matrix.rotate(-180, 0, 0, 1); - break; - case OutputTransform::Rotate270: - case OutputTransform::FlipX270: - matrix.translate(rect.height(), 0); - matrix.rotate(-270, 0, 0, 1); - break; - } - - switch (transform.kind()) { - case OutputTransform::FlipX: - case OutputTransform::FlipX90: - case OutputTransform::FlipX180: - case OutputTransform::FlipX270: - matrix.translate(rect.width(), 0); - matrix.scale(-1, 1); - break; - default: - break; - } - - matrix.translate(-rect.x(), -rect.y()); - - return matrix; -} - uint32_t Output::overscan() const { return m_state.overscan; diff --git a/src/core/output.h b/src/core/output.h index ebfdd8b6a7..5876b77036 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -322,11 +321,6 @@ public: uint32_t overscan() const; - /** - * Returns a matrix that can translate into the display's coordinates system - */ - static QMatrix4x4 logicalToNativeMatrix(const QRectF &rect, qreal scale, OutputTransform transform); - VrrPolicy vrrPolicy() const; RgbRange rgbRange() const; diff --git a/src/core/rendertarget.cpp b/src/core/rendertarget.cpp index d33cfd8090..ca1c6e542a 100644 --- a/src/core/rendertarget.cpp +++ b/src/core/rendertarget.cpp @@ -10,9 +10,39 @@ namespace KWin { +static OutputTransform textureTransformToOutputTransform(TextureTransforms transforms) // TODO: Kill TextureTransform? +{ + if (transforms == TextureTransforms()) { + return OutputTransform::Normal; + } else if (transforms == TextureTransform::Rotate90) { + return OutputTransform::Rotate90; + } else if (transforms == TextureTransform::Rotate180) { + return OutputTransform::Rotate180; + } else if (transforms == TextureTransform::Rotate270) { + return OutputTransform::Rotate270; + } else if (transforms == TextureTransform::MirrorX) { + return OutputTransform::FlipX; + } else if (transforms == TextureTransforms(TextureTransform::MirrorX | TextureTransform::Rotate90)) { + return OutputTransform::FlipX90; + } else if (transforms == TextureTransforms(TextureTransform::MirrorX | TextureTransform::Rotate180)) { + return OutputTransform::FlipX180; + } else if (transforms == TextureTransforms(TextureTransform::MirrorX | TextureTransform::Rotate270)) { + return OutputTransform::FlipX270; + } else if (transforms == TextureTransform::MirrorY) { + return OutputTransform::FlipY; + } else if (transforms == TextureTransforms(TextureTransform::MirrorY | TextureTransform::Rotate90)) { + return OutputTransform::FlipY90; + } else if (transforms == TextureTransforms(TextureTransform::MirrorY | TextureTransform::Rotate180)) { + return OutputTransform::FlipY180; + } else if (transforms == TextureTransforms(TextureTransform::MirrorY | TextureTransform::Rotate270)) { + return OutputTransform::FlipY270; + } + Q_UNREACHABLE(); +} + RenderTarget::RenderTarget(GLFramebuffer *fbo, const ColorDescription &colorDescription) : m_framebuffer(fbo) - , m_transformation(fbo->colorAttachment() ? fbo->colorAttachment()->contentTransformMatrix() : QMatrix4x4()) + , m_transform(fbo->colorAttachment() ? textureTransformToOutputTransform(fbo->colorAttachment()->contentTransforms()) : OutputTransform()) , m_colorDescription(colorDescription) { } @@ -34,44 +64,9 @@ QSize RenderTarget::size() const } } -QRectF RenderTarget::applyTransformation(const QRectF &rect) const +OutputTransform RenderTarget::transform() const { - const auto bounds = size(); - QMatrix4x4 relativeTransformation; - relativeTransformation.translate(bounds.width() / 2.0, bounds.height() / 2.0); - relativeTransformation *= m_transformation; - relativeTransformation.translate(-bounds.width() / 2.0, -bounds.height() / 2.0); - return relativeTransformation.mapRect(rect); -} - -QRect RenderTarget::applyTransformation(const QRect &rect) const -{ - return applyTransformation(QRectF(rect)).toRect(); -} - -QPointF RenderTarget::applyTransformation(const QPointF &point) const -{ - const auto bounds = size(); - QMatrix4x4 relativeTransformation; - relativeTransformation.translate(bounds.width() / 2.0, bounds.height() / 2.0); - relativeTransformation *= m_transformation; - relativeTransformation.translate(-bounds.width() / 2.0, -bounds.height() / 2.0); - return relativeTransformation.map(point); -} - -QPoint RenderTarget::applyTransformation(const QPoint &point) const -{ - const auto bounds = size(); - QMatrix4x4 relativeTransformation; - relativeTransformation.translate(bounds.width() / 2.0, bounds.height() / 2.0); - relativeTransformation *= m_transformation; - relativeTransformation.translate(-bounds.width() / 2.0, -bounds.height() / 2.0); - return relativeTransformation.map(point); -} - -QMatrix4x4 RenderTarget::transformation() const -{ - return m_transformation; + return m_transform; } GLFramebuffer *RenderTarget::framebuffer() const diff --git a/src/core/rendertarget.h b/src/core/rendertarget.h index 0e6a4b14b0..0c81ad506a 100644 --- a/src/core/rendertarget.h +++ b/src/core/rendertarget.h @@ -7,10 +7,9 @@ #pragma once #include "core/colorspace.h" +#include "core/output.h" #include -#include -#include namespace KWin { @@ -25,12 +24,8 @@ public: explicit RenderTarget(QImage *image, const ColorDescription &colorDescription = ColorDescription::sRGB); QSize size() const; - QMatrix4x4 transformation() const; + OutputTransform transform() const; const ColorDescription &colorDescription() const; - QRectF applyTransformation(const QRectF &rect) const; - QRect applyTransformation(const QRect &rect) const; - QPointF applyTransformation(const QPointF &point) const; - QPoint applyTransformation(const QPoint &point) const; QImage *image() const; GLFramebuffer *framebuffer() const; @@ -39,7 +34,7 @@ public: private: QImage *m_image = nullptr; GLFramebuffer *m_framebuffer = nullptr; - QMatrix4x4 m_transformation; + const OutputTransform m_transform; const ColorDescription m_colorDescription; }; diff --git a/src/core/renderviewport.cpp b/src/core/renderviewport.cpp index c490709cef..a2bbe9e59e 100644 --- a/src/core/renderviewport.cpp +++ b/src/core/renderviewport.cpp @@ -13,13 +13,19 @@ namespace KWin static QMatrix4x4 createProjectionMatrix(const RenderTarget &renderTarget, const QRect &rect) { - QMatrix4x4 ret = renderTarget.transformation(); + QMatrix4x4 ret; + + ret.scale(1, -1); // flip the y axis back + ret *= renderTarget.transform().toMatrix(); + ret.scale(1, -1); // undo ortho() flipping the y axis + ret.ortho(rect); return ret; } RenderViewport::RenderViewport(const QRectF &renderRect, double scale, const RenderTarget &renderTarget) - : m_renderTarget(&renderTarget) + : m_transform(renderTarget.transform()) + , m_transformBounds(m_transform.map(renderTarget.size())) , m_renderRect(renderRect) , m_deviceRenderRect(snapToPixelGrid(scaledRect(renderRect, scale))) , m_projectionMatrix(createProjectionMatrix(renderTarget, m_deviceRenderRect)) @@ -46,26 +52,26 @@ QRectF RenderViewport::mapToRenderTarget(const QRectF &logicalGeometry) const { const QRectF deviceGeometry = scaledRect(logicalGeometry, m_scale) .translated(-m_deviceRenderRect.topLeft()); - return m_renderTarget->applyTransformation(deviceGeometry); + return m_transform.map(deviceGeometry, m_transformBounds); } QRect RenderViewport::mapToRenderTarget(const QRect &logicalGeometry) const { const QRect deviceGeometry = snapToPixelGrid(scaledRect(logicalGeometry, m_scale)) .translated(-m_deviceRenderRect.topLeft()); - return m_renderTarget->applyTransformation(deviceGeometry); + return m_transform.map(deviceGeometry, m_transformBounds); } QPoint RenderViewport::mapToRenderTarget(const QPoint &logicalGeometry) const { const QPoint devicePoint = snapToPixelGrid(QPointF(logicalGeometry) * m_scale) - m_deviceRenderRect.topLeft(); - return m_renderTarget->applyTransformation(devicePoint); + return m_transform.map(devicePoint, m_transformBounds); } QPointF RenderViewport::mapToRenderTarget(const QPointF &logicalGeometry) const { const QPointF devicePoint = logicalGeometry * m_scale - m_deviceRenderRect.topLeft(); - return m_renderTarget->applyTransformation(devicePoint); + return m_transform.map(devicePoint, m_transformBounds); } QRegion RenderViewport::mapToRenderTarget(const QRegion &logicalGeometry) const diff --git a/src/core/renderviewport.h b/src/core/renderviewport.h index 23d8efee3e..567e1e9b6f 100644 --- a/src/core/renderviewport.h +++ b/src/core/renderviewport.h @@ -6,7 +6,7 @@ #pragma once -#include "kwin_export.h" +#include "core/output.h" #include #include @@ -39,7 +39,8 @@ public: QRegion mapToRenderTargetTexture(const QRegion &logicalGeometry) const; private: - const RenderTarget *m_renderTarget; + const OutputTransform m_transform; + const QSize m_transformBounds; const QRectF m_renderRect; const QRect m_deviceRenderRect; const QMatrix4x4 m_projectionMatrix; diff --git a/src/opengl/gltexture.h b/src/opengl/gltexture.h index debae998d8..89ef9663a7 100644 --- a/src/opengl/gltexture.h +++ b/src/opengl/gltexture.h @@ -161,4 +161,6 @@ protected: } // namespace +Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::TextureTransforms) + /** @} */ diff --git a/src/plugins/backgroundcontrast/contrast.cpp b/src/plugins/backgroundcontrast/contrast.cpp index 8470aab93d..13b84cddb5 100644 --- a/src/plugins/backgroundcontrast/contrast.cpp +++ b/src/plugins/backgroundcontrast/contrast.cpp @@ -476,7 +476,7 @@ void ContrastEffect::doContrast(const RenderTarget &renderTarget, const RenderVi QMatrix4x4 textureMatrix; // apply texture->buffer transformation textureMatrix.translate(0.5, 0.5); - textureMatrix *= renderTarget.transformation(); + textureMatrix *= renderTarget.transform().toMatrix(); textureMatrix.translate(-0.5, -0.5); // scaled logical to texture coordinates textureMatrix.scale(1, -1); diff --git a/src/plugins/glide/glide.cpp b/src/plugins/glide/glide.cpp index c27096ed03..92843c5866 100644 --- a/src/plugins/glide/glide.cpp +++ b/src/plugins/glide/glide.cpp @@ -137,7 +137,7 @@ void GlideEffect::paintWindow(const RenderTarget &renderTarget, const RenderView // [move to the origin] -> [rotate] -> [translate] -> // -> [perspective projection] -> [reverse "move to the origin"] - const QMatrix4x4 oldProjMatrix = createPerspectiveMatrix(viewport.renderRect(), viewport.scale(), renderTarget.transformation()); + const QMatrix4x4 oldProjMatrix = createPerspectiveMatrix(viewport.renderRect(), viewport.scale(), renderTarget.transform().toMatrix()); const auto frame = w->frameGeometry(); const QRectF windowGeo = scaledRect(frame, viewport.scale()); const QVector3D invOffset = oldProjMatrix.map(QVector3D(windowGeo.center())); diff --git a/src/plugins/screenshot/screenshot.cpp b/src/plugins/screenshot/screenshot.cpp index 6c8787084d..1a36a720b5 100644 --- a/src/plugins/screenshot/screenshot.cpp +++ b/src/plugins/screenshot/screenshot.cpp @@ -47,7 +47,7 @@ struct ScreenShotScreenData Output *screen = nullptr; }; -static void convertFromGLImage(QImage &img, int w, int h, const QMatrix4x4 &renderTargetTransformation) +static void convertFromGLImage(QImage &img, int w, int h, const OutputTransform &renderTargetTransformation) { // from QtOpenGL/qgl.cpp // SPDX-FileCopyrightText: 2010 Nokia Corporation and /or its subsidiary(-ies) @@ -79,7 +79,7 @@ static void convertFromGLImage(QImage &img, int w, int h, const QMatrix4x4 &rend // OpenGL textures are flipped vs QImage matrix.scale(1, -1); // apply render target transformation - matrix *= renderTargetTransformation.inverted(); + matrix *= renderTargetTransformation.inverted().toMatrix(); img = img.transformed(matrix.toTransform()); } @@ -284,7 +284,7 @@ void ScreenShotEffect::takeScreenShot(ScreenShotWindowData *screenshot) glReadnPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.sizeInBytes(), static_cast(img.bits())); GLFramebuffer::popFramebuffer(); - convertFromGLImage(img, img.width(), img.height(), renderTarget.transformation()); + convertFromGLImage(img, img.width(), img.height(), renderTarget.transform()); } if (screenshot->flags & ScreenShotIncludeCursor) { @@ -371,10 +371,10 @@ QImage ScreenShotEffect::blitScreenshot(const RenderTarget &renderTarget, const if (effects->isOpenGLCompositing()) { const auto screenGeometry = m_paintedScreen ? m_paintedScreen->geometry() : effects->virtualScreenGeometry(); - const QSize nativeSize = renderTarget.applyTransformation( - snapToPixelGrid(scaledRect(geometry, devicePixelRatio)) - .translated(-snapToPixelGrid(scaledRect(screenGeometry, devicePixelRatio)).topLeft())) - .size(); + const QSize nativeSize = renderTarget.transform().map( + snapToPixelGrid(scaledRect(geometry, devicePixelRatio)) + .translated(-snapToPixelGrid(scaledRect(screenGeometry, devicePixelRatio)).topLeft()) + .size()); image = QImage(nativeSize, QImage::Format_ARGB32); const auto texture = GLTexture::allocate(GL_RGBA8, nativeSize); @@ -397,7 +397,7 @@ QImage ScreenShotEffect::blitScreenshot(const RenderTarget &renderTarget, const glReadPixels(0, 0, nativeSize.width(), nativeSize.height(), GL_RGBA, GL_UNSIGNED_BYTE, static_cast(image.bits())); GLFramebuffer::popFramebuffer(); - convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transformation()); + convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transform()); } image.setDevicePixelRatio(devicePixelRatio); diff --git a/src/scene/cursordelegate_opengl.cpp b/src/scene/cursordelegate_opengl.cpp index 46b1b737df..4ef5299027 100644 --- a/src/scene/cursordelegate_opengl.cpp +++ b/src/scene/cursordelegate_opengl.cpp @@ -58,7 +58,7 @@ void CursorDelegateOpenGL::paint(const RenderTarget &renderTarget, const QRegion renderLayer.delegate()->paint(offscreenRenderTarget, infiniteRegion()); renderLayer.delegate()->postPaint(); - QMatrix4x4 mvp = renderTarget.transformation(); + QMatrix4x4 mvp = renderTarget.transform().toMatrix(); mvp.ortho(QRectF(QPointF(0, 0), m_output->transform().map(renderTarget.size()))); mvp.translate(cursorRect.x(), cursorRect.y());