Add device pixel ratio property to QQuickRenderTarget

Currently, in order to render a QtQuick scene in a HiDPI offscreen
texture without a render window, one need to fight Qt, for example by
returning a dummy window in QQuickRenderControl::renderWindowFor().

This change adds a device pixel ratio property to QQuickRenderTarget,
which can be used by the QQuickWindow to calculate the logical size of
the offscreen texture.

The main motivation behind this change is to allow KWin to render some
internal QtQuick scenes at HiDPI. Since kwin is the compositor, it does
not have any windows that can be returned from the renderWindowFor()
function.

Change-Id: Iefa7046385e750e15ca0e53b398b51a8e0aabad2
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Vlad Zahorodnii 2021-07-22 20:29:58 +03:00
parent 8b2b39a000
commit ddff1591fb
5 changed files with 49 additions and 3 deletions

View File

@ -64,6 +64,7 @@ QQuickRenderTargetPrivate::QQuickRenderTargetPrivate(const QQuickRenderTargetPri
: ref(1),
type(other->type),
pixelSize(other->pixelSize),
devicePixelRatio(other->devicePixelRatio),
sampleCount(other->sampleCount),
u(other->u)
{
@ -122,6 +123,42 @@ bool QQuickRenderTarget::isNull() const
return d->type == QQuickRenderTargetPrivate::Type::Null;
}
/*!
\return the device pixel ratio for the render target. This is the ratio
between \e{device pixels} and \e{device independent pixels}.
The default device pixel ratio is 1.0.
\since 6.3
\sa setDevicePixelRatio()
*/
qreal QQuickRenderTarget::devicePixelRatio() const
{
return d->devicePixelRatio;
}
/*!
Sets the device pixel ratio for this render target to \a ratio. This is
the ratio between \e{device pixels} and \e{device independent pixels}.
Note that the specified device pixel ratio value will be ignored if
QQuickRenderControl::renderWindow() is re-implemented to return a valid
QWindow.
\since 6.3
\sa devicePixelRatio()
*/
void QQuickRenderTarget::setDevicePixelRatio(qreal ratio)
{
if (d->devicePixelRatio == ratio)
return;
detach();
d->devicePixelRatio = ratio;
}
/*!
\return a new QQuickRenderTarget referencing an OpenGL texture object
specified by \a textureId.
@ -384,6 +421,7 @@ bool QQuickRenderTarget::isEqual(const QQuickRenderTarget &other) const noexcept
{
if (d->type != other.d->type
|| d->pixelSize != other.d->pixelSize
|| d->devicePixelRatio != other.d->devicePixelRatio
|| d->sampleCount != other.d->sampleCount)
{
return false;

View File

@ -66,6 +66,9 @@ public:
bool isNull() const;
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal ratio);
#if QT_CONFIG(opengl) || defined(Q_CLANG_QDOC)
static QQuickRenderTarget fromOpenGLTexture(uint textureId, const QSize &pixelSize, int sampleCount = 1);
static QQuickRenderTarget fromOpenGLRenderBuffer(uint renderbufferId, const QSize &pixelSize, int sampleCount = 1);

View File

@ -79,6 +79,7 @@ public:
QAtomicInt ref;
Type type = Type::Null;
QSize pixelSize;
qreal devicePixelRatio = 1.0;
int sampleCount = 1;
struct NativeTexture {
quint64 object;

View File

@ -515,6 +515,7 @@ void QQuickWindowPrivate::ensureCustomRenderTarget()
redirect.renderTargetDirty = false;
redirect.rt.reset(rhi, renderer);
redirect.devicePixelRatio = customRenderTarget.devicePixelRatio();
// a default constructed QQuickRenderTarget means no redirection
if (customRenderTarget.isNull())
@ -538,7 +539,7 @@ void QQuickWindowPrivate::syncSceneGraph()
// Calculate the dpr the same way renderSceneGraph() will.
qreal devicePixelRatio = q->effectiveDevicePixelRatio();
if (redirect.rt.renderTarget && !QQuickRenderControl::renderWindowFor(q))
devicePixelRatio = 1;
devicePixelRatio = redirect.devicePixelRatio;
QRhiCommandBuffer *cb = nullptr;
if (rhi) {
@ -655,8 +656,10 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa
renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size), matrixFlags);
renderer->setDevicePixelRatio(devicePixelRatio);
} else {
renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), rect.size()), matrixFlags);
renderer->setDevicePixelRatio(1);
const QSizeF logicalSize =
redirect.rt.renderTarget->pixelSize() / redirect.devicePixelRatio;
renderer->setProjectionMatrixToRect(QRectF(QPointF(0, 0), logicalSize), matrixFlags);
renderer->setDevicePixelRatio(redirect.devicePixelRatio);
}
} else {
QSize pixelSize;

View File

@ -228,6 +228,7 @@ public:
struct Redirect {
QRhiCommandBuffer *commandBuffer = nullptr;
QQuickWindowRenderTarget rt;
qreal devicePixelRatio = 1.0;
bool renderTargetDirty = false;
} redirect;