Skip to content

Commit

Permalink
Add some properties and function for copy OutputViewport
Browse files Browse the repository at this point in the history
Allows set input items how to map to the output device.
Allows copy WOutputLayer to other WOutputViewport.
  • Loading branch information
zccrs committed Jul 26, 2024
1 parent 63a1961 commit 69a7f44
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 81 deletions.
74 changes: 70 additions & 4 deletions src/server/qtquick/private/wbufferrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,32 @@ QSGTextureProvider *WBufferRenderer::textureProvider() const
return m_textureProvider.get();
}

QTransform WBufferRenderer::inputMapToOutput(const QRectF &sourceRect, const QRectF &targetRect,
const QSize &pixelSize, const qreal devicePixelRatio)
{
Q_ASSERT(pixelSize.isValid());

QTransform t;
const auto outputSize = QSizeF(pixelSize) / devicePixelRatio;

if (sourceRect.isValid())
t.translate(-sourceRect.x(), -sourceRect.y());
if (targetRect.isValid())
t.translate(targetRect.x(), targetRect.y());

if (sourceRect.isValid()) {
t.scale(outputSize.width() / sourceRect.width(),
outputSize.height() / sourceRect.height());
}

if (targetRect.isValid()) {
t.scale(targetRect.width() / outputSize.width(),
targetRect.height() / outputSize.height());
}

return t;
}

qw_buffer *WBufferRenderer::beginRender(const QSize &pixelSize, qreal devicePixelRatio,
uint32_t format, RenderFlags flags)
{
Expand Down Expand Up @@ -437,7 +463,14 @@ qw_buffer *WBufferRenderer::beginRender(const QSize &pixelSize, qreal devicePixe
return buffer;
}

void WBufferRenderer::render(int sourceIndex, const QMatrix4x4 &renderMatrix, bool preserveColorContents)
inline static QRect scaleToRect(const QRectF &s, qreal scale) {
return QRect((s.topLeft() * scale).toPoint(),
(s.size() * scale).toSize());
}

void WBufferRenderer::render(int sourceIndex, const QMatrix4x4 &renderMatrix,
const QRectF &sourceRect, const QRectF &targetRect,
bool preserveColorContents)
{
Q_ASSERT(state.buffer);

Expand All @@ -448,15 +481,21 @@ void WBufferRenderer::render(int sourceIndex, const QMatrix4x4 &renderMatrix, bo
const qreal devicePixelRatio = state.devicePixelRatio;
state.renderer = renderer;
state.worldTransform = renderMatrix;
state.worldTransform.optimize();
renderer->setDevicePixelRatio(devicePixelRatio);
renderer->setDeviceRect(QRect(QPoint(0, 0), state.pixelSize));
renderer->setViewportRect(state.pixelSize);
renderer->setRenderTarget(state.sgRenderTarget);
const auto viewportRect = scaleToRect(targetRect, devicePixelRatio);

auto softwareRenderer = dynamic_cast<QSGSoftwareRenderer*>(renderer);
{ // before render
if (softwareRenderer) {
// because software renderer don't supports viewportRect,
// so use transform to simulation.
const auto mapTransform = inputMapToOutput(sourceRect, targetRect,
state.pixelSize, state.devicePixelRatio);
if (!mapTransform.isIdentity())
state.worldTransform = mapTransform * state.worldTransform;
state.worldTransform.optimize();
auto image = getImageFrom(state.renderTarget);
image->setDevicePixelRatio(devicePixelRatio);

Expand All @@ -476,11 +515,24 @@ void WBufferRenderer::render(int sourceIndex, const QMatrix4x4 &renderMatrix, bo
applyTransform(softwareRenderer, t);
}
} else {
state.worldTransform.optimize();

bool flipY = wd->rhi ? !wd->rhi->isYUpInNDC() : false;
if (state.renderTarget.mirrorVertically())
flipY = !flipY;

QRectF rect(QPointF(0, 0), QSizeF(state.pixelSize) / devicePixelRatio);
if (viewportRect.isValid()) {
QRect vr = viewportRect;
if (flipY)
vr.moveTop(-vr.y() + state.pixelSize.height() - vr.height());
renderer->setViewportRect(vr);
} else {
renderer->setViewportRect(QRect(QPoint(0, 0), state.pixelSize));
}

QRectF rect = sourceRect;
if (!rect.isValid())
rect = QRectF(QPointF(0, 0), QSizeF(state.pixelSize) / devicePixelRatio);

const float left = rect.x();
const float right = rect.x() + rect.width();
Expand Down Expand Up @@ -545,6 +597,20 @@ void WBufferRenderer::render(int sourceIndex, const QMatrix4x4 &renderMatrix, bo
PixmanRegion damage;
m_damageRing.get_buffer_damage(state.bufferAge, damage);

if (viewportRect.isValid()) {
QRect imageRect = (currentImage->operator const QImage &()).rect();
QRegion invalidRegion(imageRect);
invalidRegion -= viewportRect;
if (!scaledFlushRegion.isEmpty())
invalidRegion &= scaledFlushRegion;

if (!invalidRegion.isEmpty()) {
QPainter pa(currentImage);
for (const auto r : std::as_const(invalidRegion))
pa.fillRect(r, softwareRenderer->clearColor());
}
}

if (!damage.isEmpty() && state.lastRT.first != state.buffer && !state.lastRT.second.isNull()) {
auto image = getImageFrom(state.lastRT.second);
Q_ASSERT(image);
Expand Down
7 changes: 6 additions & 1 deletion src/server/qtquick/private/wbufferrenderer_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class WAYLIB_SERVER_EXPORT WBufferRenderer : public QQuickItem
bool isTextureProvider() const override;
QSGTextureProvider *textureProvider() const override;

static QTransform inputMapToOutput(const QRectF &sourceRect, const QRectF &targetRect,
const QSize &pixelSize, const qreal devicePixelRatio);

Q_SIGNALS:
void sceneGraphChanged();
void devicePixelRatioChanged();
Expand All @@ -82,7 +85,9 @@ class WAYLIB_SERVER_EXPORT WBufferRenderer : public QQuickItem
protected:
QW_NAMESPACE::qw_buffer *beginRender(const QSize &pixelSize, qreal devicePixelRatio,
uint32_t format, RenderFlags flags = {});
void render(int sourceIndex, const QMatrix4x4 &renderMatrix, bool preserveColorContents = false);
void render(int sourceIndex, const QMatrix4x4 &renderMatrix,
const QRectF &sourceRect = {}, const QRectF &targetRect = {},
bool preserveColorContents = false);
void endRender();
void componentComplete() override;

Expand Down
7 changes: 7 additions & 0 deletions src/server/qtquick/private/woutputviewport_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Q_DECL_HIDDEN WOutputViewportPrivate : public QQuickItemPrivate
, preserveColorContents(false)
, live(true)
, forceRender(false)
, ignoreViewport(false)
{

}
Expand All @@ -48,6 +49,7 @@ class Q_DECL_HIDDEN WOutputViewportPrivate : public QQuickItemPrivate
void init();
void initForOutput();
void invalidateSceneGraph();
void update();

qreal getImplicitWidth() const override;
qreal getImplicitHeight() const override;
Expand All @@ -59,14 +61,19 @@ class Q_DECL_HIDDEN WOutputViewportPrivate : public QQuickItemPrivate
W_DECLARE_PUBLIC(WOutputViewport)
QQuickItem *input = nullptr;
WOutput *output = nullptr;
QQuickTransform *viewportTransform = nullptr;

qreal devicePixelRatio = 1.0;
WBufferRenderer *bufferRenderer = nullptr;
QPointer<QQuickItem> extraRenderSource;
QRectF sourceRect;
QRectF targetRect;

uint offscreen:1;
uint preserveColorContents:1;
uint live:1;
uint forceRender:1;
uint ignoreViewport:1;
};

WAYLIB_SERVER_END_NAMESPACE
Loading

0 comments on commit 69a7f44

Please sign in to comment.