Make rhiFlush() support custom source DPR

The rhiFlush() implementation currently assumes that
QWindow->devicePixelRatio() is the correct scale factor for
transforming device independent window geometry to source geometry.

However, this assumption does not hold if/when we add support
for drawing to a rounded-up DPR, with a downscale later in
the rhiFlush implementation.

Fix this by adding a sourceDevicePixelRatio argument to rhiFlush(),
which is set to either QWindow::devicePixelRatio() or
QWidget::devicePixelRatio(), depending on from where it is used.

Change deviceRect() and friends in qbackingstoredefualtcompositor.cpp
to be scale*() functions instead which take a scale factor instead
of a QWindow. Update call sites to use srouceDevicePixelRatio
where that makes sense.

Change-Id: Idb7b1e2f36816a201e00f0defe100d2dc079cb17
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit d38118c80828eecb3c0192404249c1fad5660792)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Morten Sørvig 2022-06-03 11:22:50 +02:00 committed by Qt Cherry-pick Bot
parent 71f57c3e7e
commit b623835dd9
12 changed files with 31 additions and 19 deletions

View File

@ -129,26 +129,25 @@ QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage
return m_texture; return m_texture;
} }
static inline QRect deviceRect(const QRect &rect, QWindow *window) static inline QRect scaledRect(const QRect &rect, qreal factor)
{ {
return QRect(rect.topLeft() * window->devicePixelRatio(), return QRect(rect.topLeft() * factor, rect.size() * factor);
rect.size() * window->devicePixelRatio());
} }
static inline QPoint deviceOffset(const QPoint &pt, QWindow *window) static inline QPoint scaledOffset(const QPoint &pt, qreal factor)
{ {
return pt * window->devicePixelRatio(); return pt * factor;
} }
static QRegion deviceRegion(const QRegion &region, QWindow *window, const QPoint &offset) static QRegion scaledRegion(const QRegion &region, qreal factor, const QPoint &offset)
{ {
if (offset.isNull() && window->devicePixelRatio() <= 1) if (offset.isNull() && factor <= 1)
return region; return region;
QVarLengthArray<QRect, 4> rects; QVarLengthArray<QRect, 4> rects;
rects.reserve(region.rectCount()); rects.reserve(region.rectCount());
for (const QRect &rect : region) for (const QRect &rect : region)
rects.append(deviceRect(rect.translated(offset), window)); rects.append(scaledRect(rect.translated(offset), factor));
QRegion deviceRegion; QRegion deviceRegion;
deviceRegion.setRects(rects.constData(), rects.count()); deviceRegion.setRects(rects.constData(), rects.count());
@ -236,12 +235,12 @@ static bool prepareDrawForRenderToTextureWidget(const QPlatformTextureList *text
const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
*target = targetTransform(deviceRect(clippedRectInWindow, window), *target = targetTransform(scaledRect(clippedRectInWindow, window->devicePixelRatio()),
deviceWindowRect, deviceWindowRect,
invertTargetY); invertTargetY);
*source = sourceTransform(deviceRect(srcRect, window), *source = sourceTransform(scaledRect(srcRect, window->devicePixelRatio()),
deviceRect(rectInWindow, window).size(), scaledRect(rectInWindow, window->devicePixelRatio()).size(),
invertSource ? SourceTransformOrigin::TopLeft : SourceTransformOrigin::BottomLeft); invertSource ? SourceTransformOrigin::TopLeft : SourceTransformOrigin::BottomLeft);
return true; return true;
@ -431,6 +430,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
QRhi *rhi, QRhi *rhi,
QRhiSwapChain *swapchain, QRhiSwapChain *swapchain,
QWindow *window, QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,
@ -479,7 +479,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format()); const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format());
const QSize size = graphicsBuffer->size(); const QSize size = graphicsBuffer->size();
QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format); QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format);
toTexture(wrapperImage, rhi, resourceUpdates, deviceRegion(region, window, offset), &flags); toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags);
gotTextureFromGraphicsBuffer = true; gotTextureFromGraphicsBuffer = true;
graphicsBuffer->unlock(); graphicsBuffer->unlock();
if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)
@ -487,7 +487,7 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
} }
} }
if (!gotTextureFromGraphicsBuffer) if (!gotTextureFromGraphicsBuffer)
toTexture(backingStore, rhi, resourceUpdates, deviceRegion(region, window, offset), &flags); toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags);
ensureResources(swapchain, resourceUpdates); ensureResources(swapchain, resourceUpdates);
@ -497,8 +497,9 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
if (flags & QPlatformBackingStore::TextureFlip) if (flags & QPlatformBackingStore::TextureFlip)
origin = SourceTransformOrigin::BottomLeft; origin = SourceTransformOrigin::BottomLeft;
const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); const qreal dpr = window->devicePixelRatio();
const QPoint deviceWindowOffset = deviceOffset(offset, window); const QRect deviceWindowRect = scaledRect(QRect(QPoint(), window->size()), dpr);
const QPoint deviceWindowOffset = scaledOffset(offset, dpr);
const bool invertTargetY = rhi->clipSpaceCorrMatrix().data()[5] < 0.0f; const bool invertTargetY = rhi->clipSpaceCorrMatrix().data()[5] < 0.0f;
const bool invertSource = rhi->isYUpInFramebuffer() != rhi->isYUpInNDC(); const bool invertSource = rhi->isYUpInFramebuffer() != rhi->isYUpInNDC();

View File

@ -37,6 +37,7 @@ public:
QRhi *rhi, QRhi *rhi,
QRhiSwapChain *swapchain, QRhiSwapChain *swapchain,
QWindow *window, QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,

View File

@ -181,13 +181,14 @@ void QPlatformBackingStore::flush(QWindow *window, const QRegion &region, const
\sa flush() \sa flush()
*/ */
QPlatformBackingStore::FlushResult QPlatformBackingStore::rhiFlush(QWindow *window, QPlatformBackingStore::FlushResult QPlatformBackingStore::rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,
bool translucentBackground) bool translucentBackground)
{ {
return d_ptr->compositor.flush(this, d_ptr->rhiSupport.rhi(), d_ptr->rhiSupport.swapChainForWindow(window), return d_ptr->compositor.flush(this, d_ptr->rhiSupport.rhi(), d_ptr->rhiSupport.swapChainForWindow(window),
window, region, offset, textures, translucentBackground); window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
} }
/*! /*!

View File

@ -154,6 +154,7 @@ public:
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset); virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
virtual FlushResult rhiFlush(QWindow *window, virtual FlushResult rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,

View File

@ -40,7 +40,7 @@ void QRhiBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
static QPlatformTextureList emptyTextureList; static QPlatformTextureList emptyTextureList;
bool translucentBackground = m_image.hasAlphaChannel(); bool translucentBackground = m_image.hasAlphaChannel();
rhiFlush(window, region, offset, &emptyTextureList, translucentBackground); rhiFlush(window, window->devicePixelRatio(), region, offset, &emptyTextureList, translucentBackground);
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -168,6 +168,7 @@ void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion &region
} }
QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWindow *window, QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,
@ -178,6 +179,7 @@ QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWind
Q_UNUSED(region); Q_UNUSED(region);
Q_UNUSED(offset); Q_UNUSED(offset);
Q_UNUSED(translucentBackground); Q_UNUSED(translucentBackground);
Q_UNUSED(sourceDevicePixelRatio);
m_rhi = rhi(); m_rhi = rhi();
if (!m_rhi) { if (!m_rhi) {

View File

@ -44,6 +44,7 @@ public:
QImage toImage() const override; QImage toImage() const override;
FlushResult rhiFlush(QWindow *window, FlushResult rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,

View File

@ -40,6 +40,7 @@ public:
void flush(QWindow *, const QRegion &, const QPoint &) override; void flush(QWindow *, const QRegion &, const QPoint &) override;
FlushResult rhiFlush(QWindow *window, FlushResult rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,

View File

@ -395,6 +395,7 @@ void QCALayerBackingStore::windowDestroyed(QObject *object)
} }
QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *window, QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,
@ -407,7 +408,7 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo
finalizeBackBuffer(); finalizeBackBuffer();
return QPlatformBackingStore::rhiFlush(window, region, offset, textures, translucentBackground); return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
} }
QImage QCALayerBackingStore::toImage() const QImage QCALayerBackingStore::toImage() const

View File

@ -866,6 +866,7 @@ void QXcbBackingStore::render(xcb_window_t window, const QRegion &region, const
} }
QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window, QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,
@ -876,7 +877,7 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
m_image->flushScrolledRegion(true); m_image->flushScrolledRegion(true);
QPlatformBackingStore::rhiFlush(window, region, offset, textures, translucentBackground); QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (platformWindow->needsSync()) { if (platformWindow->needsSync()) {

View File

@ -24,6 +24,7 @@ public:
QPaintDevice *paintDevice() override; QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override; void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
FlushResult rhiFlush(QWindow *window, FlushResult rhiFlush(QWindow *window,
qreal sourceDevicePixelRatio,
const QRegion &region, const QRegion &region,
const QPoint &offset, const QPoint &offset,
QPlatformTextureList *textures, QPlatformTextureList *textures,

View File

@ -1050,6 +1050,7 @@ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion &region, QPlatf
QPlatformBackingStore::FlushResult flushResult; QPlatformBackingStore::FlushResult flushResult;
flushResult = store->handle()->rhiFlush(widget->windowHandle(), flushResult = store->handle()->rhiFlush(widget->windowHandle(),
widget->devicePixelRatio(),
region, region,
offset, offset,
widgetTextures, widgetTextures,