core: Port RenderTarget to OutputTransform
This commit is contained in:
parent
c970d3261b
commit
16809e6b15
12 changed files with 69 additions and 120 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QMatrix3x3>
|
||||
#include <QMatrix4x4>
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/colorspace.h"
|
||||
#include "core/output.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QMatrix4x4>
|
||||
#include <variant>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kwin_export.h"
|
||||
#include "core/output.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QRectF>
|
||||
|
@ -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;
|
||||
|
|
|
@ -161,4 +161,6 @@ protected:
|
|||
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::TextureTransforms)
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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<GLvoid *>(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<GLvoid *>(image.bits()));
|
||||
GLFramebuffer::popFramebuffer();
|
||||
convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transformation());
|
||||
convertFromGLImage(image, nativeSize.width(), nativeSize.height(), renderTarget.transform());
|
||||
}
|
||||
|
||||
image.setDevicePixelRatio(devicePixelRatio);
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
Loading…
Reference in a new issue