core: Port RenderTarget to OutputTransform

wilder/Plasma/6.2
Vlad Zahorodnii 2 years ago
parent c970d3261b
commit 16809e6b15
  1. 11
      src/compositor_wayland.cpp
  2. 43
      src/core/output.cpp
  3. 6
      src/core/output.h
  4. 71
      src/core/rendertarget.cpp
  5. 11
      src/core/rendertarget.h
  6. 18
      src/core/renderviewport.cpp
  7. 5
      src/core/renderviewport.h
  8. 2
      src/opengl/gltexture.h
  9. 2
      src/plugins/backgroundcontrast/contrast.cpp
  10. 2
      src/plugins/glide/glide.cpp
  11. 16
      src/plugins/screenshot/screenshot.cpp
  12. 2
      src/scene/cursordelegate_opengl.cpp

@ -291,18 +291,17 @@ void WaylandCompositor::addOutput(Output *output)
if (!outputLayer || forceSoftwareCursor) { if (!outputLayer || forceSoftwareCursor) {
return false; return false;
} }
const QMatrix4x4 monitorMatrix = Output::logicalToNativeMatrix(output->rect(), output->scale(), output->transform()); QRectF nativeCursorRect = output->transform().map(scaledRect(outputLocalRect, output->scale()), output->pixelSize());
QRectF nativeCursorRect = monitorMatrix.mapRect(outputLocalRect);
QSize bufferSize(std::ceil(nativeCursorRect.width()), std::ceil(nativeCursorRect.height())); QSize bufferSize(std::ceil(nativeCursorRect.width()), std::ceil(nativeCursorRect.height()));
if (const auto fixedSize = outputLayer->fixedSize()) { if (const auto fixedSize = outputLayer->fixedSize()) {
if (fixedSize->width() < bufferSize.width() || fixedSize->height() < bufferSize.height()) { if (fixedSize->width() < bufferSize.width() || fixedSize->height() < bufferSize.height()) {
return false; return false;
} }
bufferSize = *fixedSize; 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->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); outputLayer->setSize(bufferSize);
if (auto beginInfo = outputLayer->beginFrame()) { if (auto beginInfo = outputLayer->beginFrame()) {
const RenderTarget &renderTarget = beginInfo->renderTarget; const RenderTarget &renderTarget = beginInfo->renderTarget;
@ -345,8 +344,8 @@ void WaylandCompositor::addOutput(Output *output)
bool hardwareCursor = false; bool hardwareCursor = false;
if (outputLayer) { if (outputLayer) {
if (outputLayer->isEnabled()) { if (outputLayer->isEnabled()) {
const QMatrix4x4 monitorMatrix = Output::logicalToNativeMatrix(output->rect(), output->scale(), output->transform()); const QRectF nativeCursorRect = output->transform()
const QRectF nativeCursorRect = monitorMatrix.mapRect(QRectF(outputLocalRect.topLeft(), outputLayer->size() / output->scale())); .map(QRectF(outputLocalRect.topLeft() * output->scale(), outputLayer->size()), output->pixelSize());
outputLayer->setPosition(nativeCursorRect.topLeft()); outputLayer->setPosition(nativeCursorRect.topLeft());
hardwareCursor = output->updateCursorLayer(); hardwareCursor = output->updateCursorLayer();
} else if (!cursorLayer->isVisible() && !forceSoftwareCursor) { } else if (!cursorLayer->isVisible() && !forceSoftwareCursor) {

@ -646,49 +646,6 @@ Output::DpmsMode Output::dpmsMode() const
return m_state.dpmsMode; 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 uint32_t Output::overscan() const
{ {
return m_state.overscan; return m_state.overscan;

@ -15,7 +15,6 @@
#include <QDebug> #include <QDebug>
#include <QList> #include <QList>
#include <QMatrix3x3>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QObject> #include <QObject>
#include <QRect> #include <QRect>
@ -322,11 +321,6 @@ public:
uint32_t overscan() const; 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; VrrPolicy vrrPolicy() const;
RgbRange rgbRange() const; RgbRange rgbRange() const;

@ -10,9 +10,39 @@
namespace KWin 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) RenderTarget::RenderTarget(GLFramebuffer *fbo, const ColorDescription &colorDescription)
: m_framebuffer(fbo) : m_framebuffer(fbo)
, m_transformation(fbo->colorAttachment() ? fbo->colorAttachment()->contentTransformMatrix() : QMatrix4x4()) , m_transform(fbo->colorAttachment() ? textureTransformToOutputTransform(fbo->colorAttachment()->contentTransforms()) : OutputTransform())
, m_colorDescription(colorDescription) , 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 GLFramebuffer *RenderTarget::framebuffer() const

@ -7,10 +7,9 @@
#pragma once #pragma once
#include "core/colorspace.h" #include "core/colorspace.h"
#include "core/output.h"
#include <QImage> #include <QImage>
#include <QMatrix4x4>
#include <variant>
namespace KWin namespace KWin
{ {
@ -25,12 +24,8 @@ public:
explicit RenderTarget(QImage *image, const ColorDescription &colorDescription = ColorDescription::sRGB); explicit RenderTarget(QImage *image, const ColorDescription &colorDescription = ColorDescription::sRGB);
QSize size() const; QSize size() const;
QMatrix4x4 transformation() const; OutputTransform transform() const;
const ColorDescription &colorDescription() 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; QImage *image() const;
GLFramebuffer *framebuffer() const; GLFramebuffer *framebuffer() const;
@ -39,7 +34,7 @@ public:
private: private:
QImage *m_image = nullptr; QImage *m_image = nullptr;
GLFramebuffer *m_framebuffer = nullptr; GLFramebuffer *m_framebuffer = nullptr;
QMatrix4x4 m_transformation; const OutputTransform m_transform;
const ColorDescription m_colorDescription; const ColorDescription m_colorDescription;
}; };

@ -13,13 +13,19 @@ namespace KWin
static QMatrix4x4 createProjectionMatrix(const RenderTarget &renderTarget, const QRect &rect) 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); ret.ortho(rect);
return ret; return ret;
} }
RenderViewport::RenderViewport(const QRectF &renderRect, double scale, const RenderTarget &renderTarget) 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_renderRect(renderRect)
, m_deviceRenderRect(snapToPixelGrid(scaledRect(renderRect, scale))) , m_deviceRenderRect(snapToPixelGrid(scaledRect(renderRect, scale)))
, m_projectionMatrix(createProjectionMatrix(renderTarget, m_deviceRenderRect)) , m_projectionMatrix(createProjectionMatrix(renderTarget, m_deviceRenderRect))
@ -46,26 +52,26 @@ QRectF RenderViewport::mapToRenderTarget(const QRectF &logicalGeometry) const
{ {
const QRectF deviceGeometry = scaledRect(logicalGeometry, m_scale) const QRectF deviceGeometry = scaledRect(logicalGeometry, m_scale)
.translated(-m_deviceRenderRect.topLeft()); .translated(-m_deviceRenderRect.topLeft());
return m_renderTarget->applyTransformation(deviceGeometry); return m_transform.map(deviceGeometry, m_transformBounds);
} }
QRect RenderViewport::mapToRenderTarget(const QRect &logicalGeometry) const QRect RenderViewport::mapToRenderTarget(const QRect &logicalGeometry) const
{ {
const QRect deviceGeometry = snapToPixelGrid(scaledRect(logicalGeometry, m_scale)) const QRect deviceGeometry = snapToPixelGrid(scaledRect(logicalGeometry, m_scale))
.translated(-m_deviceRenderRect.topLeft()); .translated(-m_deviceRenderRect.topLeft());
return m_renderTarget->applyTransformation(deviceGeometry); return m_transform.map(deviceGeometry, m_transformBounds);
} }
QPoint RenderViewport::mapToRenderTarget(const QPoint &logicalGeometry) const QPoint RenderViewport::mapToRenderTarget(const QPoint &logicalGeometry) const
{ {
const QPoint devicePoint = snapToPixelGrid(QPointF(logicalGeometry) * m_scale) - m_deviceRenderRect.topLeft(); 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 QPointF RenderViewport::mapToRenderTarget(const QPointF &logicalGeometry) const
{ {
const QPointF devicePoint = logicalGeometry * m_scale - m_deviceRenderRect.topLeft(); 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 QRegion RenderViewport::mapToRenderTarget(const QRegion &logicalGeometry) const

@ -6,7 +6,7 @@
#pragma once #pragma once
#include "kwin_export.h" #include "core/output.h"
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QRectF> #include <QRectF>
@ -39,7 +39,8 @@ public:
QRegion mapToRenderTargetTexture(const QRegion &logicalGeometry) const; QRegion mapToRenderTargetTexture(const QRegion &logicalGeometry) const;
private: private:
const RenderTarget *m_renderTarget; const OutputTransform m_transform;
const QSize m_transformBounds;
const QRectF m_renderRect; const QRectF m_renderRect;
const QRect m_deviceRenderRect; const QRect m_deviceRenderRect;
const QMatrix4x4 m_projectionMatrix; const QMatrix4x4 m_projectionMatrix;

@ -161,4 +161,6 @@ protected:
} // namespace } // namespace
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::TextureTransforms)
/** @} */ /** @} */

@ -476,7 +476,7 @@ void ContrastEffect::doContrast(const RenderTarget &renderTarget, const RenderVi
QMatrix4x4 textureMatrix; QMatrix4x4 textureMatrix;
// apply texture->buffer transformation // apply texture->buffer transformation
textureMatrix.translate(0.5, 0.5); textureMatrix.translate(0.5, 0.5);
textureMatrix *= renderTarget.transformation(); textureMatrix *= renderTarget.transform().toMatrix();
textureMatrix.translate(-0.5, -0.5); textureMatrix.translate(-0.5, -0.5);
// scaled logical to texture coordinates // scaled logical to texture coordinates
textureMatrix.scale(1, -1); textureMatrix.scale(1, -1);

@ -137,7 +137,7 @@ void GlideEffect::paintWindow(const RenderTarget &renderTarget, const RenderView
// [move to the origin] -> [rotate] -> [translate] -> // [move to the origin] -> [rotate] -> [translate] ->
// -> [perspective projection] -> [reverse "move to the origin"] // -> [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 auto frame = w->frameGeometry();
const QRectF windowGeo = scaledRect(frame, viewport.scale()); const QRectF windowGeo = scaledRect(frame, viewport.scale());
const QVector3D invOffset = oldProjMatrix.map(QVector3D(windowGeo.center())); const QVector3D invOffset = oldProjMatrix.map(QVector3D(windowGeo.center()));

@ -47,7 +47,7 @@ struct ScreenShotScreenData
Output *screen = nullptr; 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 // from QtOpenGL/qgl.cpp
// SPDX-FileCopyrightText: 2010 Nokia Corporation and /or its subsidiary(-ies) // 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 // OpenGL textures are flipped vs QImage
matrix.scale(1, -1); matrix.scale(1, -1);
// apply render target transformation // apply render target transformation
matrix *= renderTargetTransformation.inverted(); matrix *= renderTargetTransformation.inverted().toMatrix();
img = img.transformed(matrix.toTransform()); 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(), glReadnPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.sizeInBytes(),
static_cast<GLvoid *>(img.bits())); static_cast<GLvoid *>(img.bits()));
GLFramebuffer::popFramebuffer(); GLFramebuffer::popFramebuffer();
convertFromGLImage(img, img.width(), img.height(), renderTarget.transformation()); convertFromGLImage(img, img.width(), img.height(), renderTarget.transform());
} }
if (screenshot->flags & ScreenShotIncludeCursor) { if (screenshot->flags & ScreenShotIncludeCursor) {
@ -371,10 +371,10 @@ QImage ScreenShotEffect::blitScreenshot(const RenderTarget &renderTarget, const
if (effects->isOpenGLCompositing()) { if (effects->isOpenGLCompositing()) {
const auto screenGeometry = m_paintedScreen ? m_paintedScreen->geometry() : effects->virtualScreenGeometry(); const auto screenGeometry = m_paintedScreen ? m_paintedScreen->geometry() : effects->virtualScreenGeometry();
const QSize nativeSize = renderTarget.applyTransformation( const QSize nativeSize = renderTarget.transform().map(
snapToPixelGrid(scaledRect(geometry, devicePixelRatio)) snapToPixelGrid(scaledRect(geometry, devicePixelRatio))
.translated(-snapToPixelGrid(scaledRect(screenGeometry, devicePixelRatio)).topLeft())) .translated(-snapToPixelGrid(scaledRect(screenGeometry, devicePixelRatio)).topLeft())
.size(); .size());
image = QImage(nativeSize, QImage::Format_ARGB32); image = QImage(nativeSize, QImage::Format_ARGB32);
const auto texture = GLTexture::allocate(GL_RGBA8, nativeSize); 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, glReadPixels(0, 0, nativeSize.width(), nativeSize.height(), GL_RGBA,
GL_UNSIGNED_BYTE, static_cast<GLvoid *>(image.bits())); GL_UNSIGNED_BYTE, static_cast<GLvoid *>(image.bits()));
GLFramebuffer::popFramebuffer(); GLFramebuffer::popFramebuffer();
convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transformation()); convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transform());
} }
image.setDevicePixelRatio(devicePixelRatio); image.setDevicePixelRatio(devicePixelRatio);

@ -58,7 +58,7 @@ void CursorDelegateOpenGL::paint(const RenderTarget &renderTarget, const QRegion
renderLayer.delegate()->paint(offscreenRenderTarget, infiniteRegion()); renderLayer.delegate()->paint(offscreenRenderTarget, infiniteRegion());
renderLayer.delegate()->postPaint(); 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.ortho(QRectF(QPointF(0, 0), m_output->transform().map(renderTarget.size())));
mvp.translate(cursorRect.x(), cursorRect.y()); mvp.translate(cursorRect.x(), cursorRect.y());

Loading…
Cancel
Save