summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qbackingstore.cpp48
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor.cpp5
-rw-r--r--src/widgets/kernel/qwidget.cpp15
-rw-r--r--tests/manual/highdpi/dprgadget/main.cpp9
4 files changed, 59 insertions, 18 deletions
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index ecc0d1cac2..f609cddd3c 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -25,11 +25,32 @@ public:
{
}
+ // Returns the DPR for the backing store. This is the DPR for the QWindow,
+ // possibly rounded up to the nearest integer.
+ qreal backingStoreDevicePixelRatio() const
+ {
+ // Note: keep in sync with QWidget::metric()!
+ qreal windowDpr = window->devicePixelRatio();
+ return downscale ? std::ceil(windowDpr) : windowDpr;
+ }
+
+ // Returns the factor used for converting from device independent to native
+ // backing store sizes. Normally this is just the gui scale factor, however
+ // if the backing store rounds the DPR up to the nearest integer then we also
+ // need to account for the factor introduced by that rounding.
+ qreal deviceIndependentToNativeFactor() const
+ {
+ const qreal roundingFactor = backingStoreDevicePixelRatio() / window->devicePixelRatio();
+ const qreal guiFactor = QHighDpiScaling::factor(window);
+ return roundingFactor * guiFactor;
+ }
+
QWindow *window;
QPlatformBackingStore *platformBackingStore = nullptr;
QScopedPointer<QImage> highDpiBackingstore;
QRegion staticContents;
QSize size;
+ bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
};
/*!
@@ -94,12 +115,14 @@ QWindow* QBackingStore::window() const
void QBackingStore::beginPaint(const QRegion &region)
{
+ const qreal dpr = d_ptr->backingStoreDevicePixelRatio();
+
if (d_ptr->highDpiBackingstore &&
- d_ptr->highDpiBackingstore->devicePixelRatio() != d_ptr->window->devicePixelRatio())
+ d_ptr->highDpiBackingstore->devicePixelRatio() != dpr)
resize(size());
QPlatformBackingStore *platformBackingStore = handle();
- platformBackingStore->beginPaint(QHighDpi::toNativeLocalRegion(region, d_ptr->window));
+ platformBackingStore->beginPaint(QHighDpi::scale(region, d_ptr->deviceIndependentToNativeFactor()));
// When QtGui is applying a high-dpi scale factor the backing store
// creates a "large" backing store image. This image needs to be
@@ -118,8 +141,7 @@ void QBackingStore::beginPaint(const QRegion &region)
d_ptr->highDpiBackingstore.reset(
new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format()));
- qreal targetDevicePixelRatio = d_ptr->window->devicePixelRatio();
- d_ptr->highDpiBackingstore->setDevicePixelRatio(targetDevicePixelRatio);
+ d_ptr->highDpiBackingstore->setDevicePixelRatio(dpr);
}
}
}
@@ -184,13 +206,15 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
Q_ASSERT(window == topLevelWindow || topLevelWindow->isAncestorOf(window, QWindow::ExcludeTransients));
- QRegion nativeRegion = QHighDpi::toNativeLocalRegion(region, window);
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
+
+ QRegion nativeRegion = QHighDpi::scale(region, toNativeFactor);
QPoint nativeOffset;
if (!offset.isNull()) {
- nativeOffset = QHighDpi::toNativeLocalPosition(offset, window);
+ nativeOffset = QHighDpi::scale(offset, toNativeFactor);
// Under fractional DPR, rounding of region and offset may accumulate to an off-by-one
QPoint topLeft = region.boundingRect().topLeft() + offset;
- QPoint nativeTopLeft = QHighDpi::toNativeLocalPosition(topLeft, window);
+ QPoint nativeTopLeft = QHighDpi::scale(topLeft, toNativeFactor);
QPoint diff = nativeTopLeft - (nativeRegion.boundingRect().topLeft() + nativeOffset);
Q_ASSERT(qMax(qAbs(diff.x()), qAbs(diff.y())) <= 1);
nativeRegion.translate(diff);
@@ -206,7 +230,7 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
void QBackingStore::resize(const QSize &size)
{
d_ptr->size = size;
- handle()->resize(QHighDpi::toNativePixels(size, d_ptr->window), d_ptr->staticContents);
+ handle()->resize(QHighDpi::scale(size, d_ptr->deviceIndependentToNativeFactor()), d_ptr->staticContents);
}
/*!
@@ -228,13 +252,13 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
// Disable scrolling for non-integer scroll deltas. For this case
// the existing rendered pixels can't be re-used, and we return
// false to signal that a repaint is needed.
- const qreal nativeDx = QHighDpi::toNativePixels(qreal(dx), d_ptr->window);
- const qreal nativeDy = QHighDpi::toNativePixels(qreal(dy), d_ptr->window);
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
+ const qreal nativeDx = QHighDpi::scale(qreal(dx), toNativeFactor);
+ const qreal nativeDy = QHighDpi::scale(qreal(dy), toNativeFactor);
if (qFloor(nativeDx) != nativeDx || qFloor(nativeDy) != nativeDy)
return false;
- return handle()->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window),
- nativeDx, nativeDy);
+ return handle()->scroll(QHighDpi::scale(area, toNativeFactor), nativeDx, nativeDy);
}
/*!
diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp
index 949b3bc10a..bb5fe58aa8 100644
--- a/src/gui/painting/qbackingstoredefaultcompositor.cpp
+++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp
@@ -408,7 +408,7 @@ void QBackingStoreDefaultCompositor::ensureResources(QRhiSwapChain *swapchain, Q
}
if (!m_sampler) {
- m_sampler = m_rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
+ m_sampler = m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
if (!m_sampler->create())
qWarning("QBackingStoreDefaultCompositor: Failed to create sampler");
@@ -506,7 +506,8 @@ QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatfo
if (m_texture) {
// The backingstore is for the entire tlw.
// In case of native children offset tells the position relative to the tlw.
- const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(deviceWindowOffset), m_texture->pixelSize().height());
+ const QRect textureRect = QRect(QPoint(), m_texture->pixelSize());
+ const QRect srcRect = toBottomLeftRect(textureRect.translated(deviceWindowOffset), m_texture->pixelSize().height());
const QMatrix3x3 source = sourceTransform(srcRect, m_texture->pixelSize(), origin);
QMatrix4x4 target; // identity
if (invertTargetY)
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 01a8905c79..9c1cec5d8d 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -12698,6 +12698,17 @@ int QWidget::metric(PaintDeviceMetric m) const
return QPaintDevice::metric(m);
}
+ auto resolveDevicePixelRatio = [this, screen]() -> qreal {
+
+ // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
+ static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
+ QWindow *window = this->window()->windowHandle();
+ if (downscale && window)
+ return std::ceil(window->devicePixelRatio());
+
+ return screen->devicePixelRatio();
+ };
+
switch (m) {
case PdmWidth:
return data->crect.width();
@@ -12726,9 +12737,9 @@ int QWidget::metric(PaintDeviceMetric m) const
case PdmPhysicalDpiY:
return qRound(screen->physicalDotsPerInchY());
case PdmDevicePixelRatio:
- return screen->devicePixelRatio();
+ return resolveDevicePixelRatio();
case PdmDevicePixelRatioScaled:
- return QPaintDevice::devicePixelRatioFScale() * screen->devicePixelRatio();
+ return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
default:
break;
}
diff --git a/tests/manual/highdpi/dprgadget/main.cpp b/tests/manual/highdpi/dprgadget/main.cpp
index 78189e8a39..9da74b4893 100644
--- a/tests/manual/highdpi/dprgadget/main.cpp
+++ b/tests/manual/highdpi/dprgadget/main.cpp
@@ -22,6 +22,7 @@ bool g_qtScaleFactor = false;
bool g_qtUsePhysicalDpi = false;
bool g_qtFontDpi = false;
bool g_qtScaleFactorRoundingPolicy = false;
+bool g_qtHighDpiDownscale = false;
bool g_displayEvents = false;
@@ -136,7 +137,7 @@ public:
if (g_displayEvents)
layout->addWidget(eventsLabel);
- bool activeEnvironment = g_qtScaleFactor || g_qtUsePhysicalDpi || g_qtFontDpi || g_qtScaleFactorRoundingPolicy;
+ bool activeEnvironment = g_qtScaleFactor || g_qtUsePhysicalDpi || g_qtFontDpi || g_qtScaleFactorRoundingPolicy || g_qtHighDpiDownscale;
if (activeEnvironment) {
layout->addWidget(new QLabel("Active Environment:"));
if (g_qtScaleFactor) {
@@ -155,7 +156,10 @@ public:
QString text = QString("QT_SCALE_FACTOR_ROUNDING_POLICY=") + qgetenv("QT_SCALE_FACTOR_ROUNDING_POLICY");
layout->addWidget(new QLabel(text));
}
-
+ if (g_qtHighDpiDownscale) {
+ QString text = QString("QT_WIDGETS_HIGHDPI_DOWNSCALE=") + qgetenv("QT_WIDGETS_HIGHDPI_DOWNSCALE");
+ layout->addWidget(new QLabel(text));
+ }
}
auto updateValues = [=]() {
@@ -244,6 +248,7 @@ int main(int argc, char **argv) {
g_qtUsePhysicalDpi = qgetenv("QT_USE_PHYSICAL_DPI") == QByteArray("1");
g_qtFontDpi = qEnvironmentVariableIsSet("QT_FONT_DPI");
g_qtScaleFactorRoundingPolicy = qEnvironmentVariableIsSet("QT_SCALE_FACTOR_ROUNDING_POLICY");
+ g_qtHighDpiDownscale = qEnvironmentVariableIsSet("QT_WIDGETS_HIGHDPI_DOWNSCALE");
QApplication app(argc, argv);