summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qbackingstore.cpp
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@theqtcompany.com>2015-06-22 12:32:11 +0200
committerPaul Olav Tvete <paul.tvete@theqtcompany.com>2015-07-30 12:44:41 +0000
commita705b4ec1f6f7133390054f8b6b8077ef0550311 (patch)
treed9df0f8650bd62690c8489e4491bc5c2407c9d07 /src/gui/painting/qbackingstore.cpp
parentdcd2debe625841ee8cba6d13a56cde7613c40358 (diff)
Introduce cross platform high-dpi scaling
Add a coordinate scaling layer to QtGui, which supports 'devicePixelRatio' type high-dpi on all platforms, in production and also for development and testing purposes. High-DPI scaling is opt-in, by setting environment variables: QT_SCALE_FACTOR - sets a global scale factor QT_AUTO_SCREEN_SCALE_FACTOR - sets per-screen scale factors, where the scale factors are provided by the platform plugin. This QtGui scaling can be used instead of or in addition to scaling done by the window system. This distinction is not visible to applications [when they use Qt API], which will see a change in the value returned by the devicePixelRatio() accessors as usual. Introduce a new (private to Qt) coordinate system: native pixels. The coordinate system stack now looks like: device-independent pixels (app, upper parts of Qt) native pixels (lower parts of Qt Gui, platform plugins) device pixels (backing stores and OpenGL) Add private QHighDpi namespace with scaling functions that convert between device-independent pixels and native pixels: T toNativePixels(T, QWindow *); T fromNativePixels(T, QWindow *); Add scaling calls the QWindow (and friends) cross-platform implementation, around the calls to QPlatformWindow functions. QPlatformWindow now uses native coordinates - platform code remains largely unchanged since native coordinates are window system coordinates. QWindow now uses (possibly) scaled coordinates. This means that platform plugins no longer can rely on QWindow::geometry() and related functions. QPlatformWindow::windowGeometry() and other convenience functions have been added for use when the platform plugin needs to convert scaled geometry to native geometry. Add Qt::AA_NoHighDpiScaling, which can be use to disable any scaling in QtGui, effectively ignoring the environment variables. (Note that this does not disable any scaling done by the window system.) Contributions from Friedemann and Paul. Task-number: QTBUG-46615 Change-Id: I673bbd69c130e73b13cce83be11bfb28f580bf60 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'src/gui/painting/qbackingstore.cpp')
-rw-r--r--src/gui/painting/qbackingstore.cpp48
1 files changed, 43 insertions, 5 deletions
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 19074e4c47..4136c29d4e 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -38,10 +38,13 @@
#include <qpa/qplatformintegration.h>
#include <qscreen.h>
#include <qdebug.h>
+#include <qscopedpointer.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
+#include <private/qhighdpiscaling_p.h>
+
QT_BEGIN_NAMESPACE
class QBackingStorePrivate
@@ -54,6 +57,7 @@ public:
QWindow *window;
QPlatformBackingStore *platformBackingStore;
+ QScopedPointer<QImage> highDpiBackingstore;
QRegion staticContents;
QSize size;
};
@@ -102,7 +106,7 @@ void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &off
}
#endif
- d_ptr->platformBackingStore->flush(win, region, offset);
+ d_ptr->platformBackingStore->flush(win, QHighDpi::toNativeLocalRegion(region, d_ptr->window), offset);
}
/*!
@@ -112,7 +116,12 @@ void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &off
*/
QPaintDevice *QBackingStore::paintDevice()
{
- return d_ptr->platformBackingStore->paintDevice();
+ QPaintDevice *device = d_ptr->platformBackingStore->paintDevice();
+
+ if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
+ return d_ptr->highDpiBackingstore.data();
+
+ return device;
}
/*!
@@ -150,7 +159,36 @@ QWindow* QBackingStore::window() const
void QBackingStore::beginPaint(const QRegion &region)
{
- d_ptr->platformBackingStore->beginPaint(region);
+ if (d_ptr->highDpiBackingstore &&
+ d_ptr->highDpiBackingstore->devicePixelRatio() != d_ptr->window->devicePixelRatio())
+ resize(size());
+
+ d_ptr->platformBackingStore->beginPaint(QHighDpi::toNativeLocalRegion(region, d_ptr->window));
+
+ // When QtGui is applying a high-dpi scale factor the backing store
+ // creates a "large" backing store image. This image needs to be
+ // painted on as a high-dpi image, which is done by setting
+ // devicePixelRatio. Do this on a separate image instance that shares
+ // the image data to avoid having the new devicePixelRatio be propagated
+ // back to the platform plugin.
+ QPaintDevice *device = d_ptr->platformBackingStore->paintDevice();
+ if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image) {
+ QImage *source = static_cast<QImage *>(device);
+ const bool needsNewImage = d_ptr->highDpiBackingstore.isNull()
+ || source->data_ptr() != d_ptr->highDpiBackingstore->data_ptr()
+ || source->size() != d_ptr->highDpiBackingstore->size()
+ || source->devicePixelRatio() != d_ptr->highDpiBackingstore->devicePixelRatio();
+ if (needsNewImage) {
+ qCDebug(lcScaling) << "QBackingStore::beginPaint new backingstore for" << d_ptr->window;
+ qCDebug(lcScaling) << " source size" << source->size() << "dpr" << source->devicePixelRatio();
+ d_ptr->highDpiBackingstore.reset(
+ new QImage(source->bits(), source->width(), source->height(), source->format()));
+ qreal targetDevicePixelRatio = d_ptr->window->devicePixelRatio();
+ d_ptr->highDpiBackingstore->setDevicePixelRatio(targetDevicePixelRatio);
+ qCDebug(lcScaling) <<" destination size" << d_ptr->highDpiBackingstore->size()
+ << "dpr" << targetDevicePixelRatio;
+ }
+ }
}
/*!
@@ -171,7 +209,7 @@ void QBackingStore::endPaint()
void QBackingStore::resize(const QSize &size)
{
d_ptr->size = size;
- d_ptr->platformBackingStore->resize(size, d_ptr->staticContents);
+ d_ptr->platformBackingStore->resize(QHighDpi::toNativePixels(size, d_ptr->window), d_ptr->staticContents);
}
/*!
@@ -194,7 +232,7 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
Q_UNUSED(dx);
Q_UNUSED(dy);
- return d_ptr->platformBackingStore->scroll(area, dx, dy);
+ return d_ptr->platformBackingStore->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window), QHighDpi::toNativePixels(dx, d_ptr->window), QHighDpi::toNativePixels(dy, d_ptr->window));
}
void QBackingStore::setStaticContents(const QRegion &region)