From 7ac4e55cb979dff890f1575e771e5f2def9e3131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 20 Dec 2019 16:46:24 +0100 Subject: macOS Don't throw away backingstore buffers when backing properties change Clients such as QtWidgets that do their own dirty tracking will assume they can just flush in response to the expose event, without repainting anything. Since we have no way at the moment to inform these clients that the backingstore content might be invalid we can't just throw it away. It turns out that to pick up changes in color spaces we can just tag the existing buffers with the new color space, so we don't need to throw it away. And for the older surface-backed mode we tag the color space on flush, so we didn't need to invalidate anything in the first place. Fixes: QTBUG-80844 Task-number: QTBUG-77749 Change-Id: Icb1ceb178894bb43887cdf03fb855d2d614b5ab0 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 6 ++-- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 36 ++++++++++------------ src/plugins/platforms/cocoa/qcocoaintegration.mm | 2 ++ .../platforms/cocoa/qiosurfacegraphicsbuffer.h | 4 ++- .../platforms/cocoa/qiosurfacegraphicsbuffer.mm | 14 +++++---- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index a874936ce6..b57deacb57 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -54,8 +54,6 @@ class QCocoaBackingStore : public QRasterBackingStore protected: QCocoaBackingStore(QWindow *window); QCFType colorSpace() const; - QMacNotificationObserver m_backingPropertiesObserver; - virtual void backingPropertiesChanged() = 0; }; class QNSWindowBackingStore : public QCocoaBackingStore @@ -71,7 +69,6 @@ private: bool windowHasUnifiedToolbar() const; QImage::Format format() const override; void redrawRoundedBottomCorners(CGRect) const; - void backingPropertiesChanged() override; }; class QCALayerBackingStore : public QCocoaBackingStore @@ -118,7 +115,8 @@ private: bool recreateBackBufferIfNeeded(); bool prepareForFlush(); - void backingPropertiesChanged() override; + void backingPropertiesChanged(); + QMacNotificationObserver m_backingPropertiesObserver; std::list> m_buffers; }; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index b17302a640..8a815a7665 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -51,17 +51,6 @@ QT_BEGIN_NAMESPACE QCocoaBackingStore::QCocoaBackingStore(QWindow *window) : QRasterBackingStore(window) { - // Ideally this would be plumbed from the platform layer to QtGui, and - // the QBackingStore would be recreated, but we don't have that code yet, - // so at least make sure we invalidate our backingstore when the backing - // properties (color space e.g.) are changed. - NSView *view = static_cast(window->handle())->view(); - m_backingPropertiesObserver = QMacNotificationObserver(view.window, - NSWindowDidChangeBackingPropertiesNotification, [this]() { - qCDebug(lcQpaBackingStore) << "Backing properties for" - << this->window() << "did change"; - backingPropertiesChanged(); - }); } QCFType QCocoaBackingStore::colorSpace() const @@ -341,11 +330,6 @@ void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const #endif } -void QNSWindowBackingStore::backingPropertiesChanged() -{ - m_image = QImage(); -} - // ---------------------------------------------------------------------------- QCALayerBackingStore::QCALayerBackingStore(QWindow *window) @@ -353,6 +337,18 @@ QCALayerBackingStore::QCALayerBackingStore(QWindow *window) { qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window; m_buffers.resize(1); + + // Ideally this would be plumbed from the platform layer to QtGui, and + // the QBackingStore would be recreated, but we don't have that code yet, + // so at least make sure we update our backingstore when the backing + // properties (color space e.g.) are changed. + NSView *view = static_cast(window->handle())->view(); + m_backingPropertiesObserver = QMacNotificationObserver(view.window, + NSWindowDidChangeBackingPropertiesNotification, [this]() { + qCDebug(lcQpaBackingStore) << "Backing properties for" + << this->window() << "did change"; + backingPropertiesChanged(); + }); } QCALayerBackingStore::~QCALayerBackingStore() @@ -620,8 +616,9 @@ QImage QCALayerBackingStore::toImage() const void QCALayerBackingStore::backingPropertiesChanged() { - m_buffers.clear(); - m_buffers.resize(1); + qCDebug(lcQpaBackingStore) << "Updating color space of existing buffers"; + for (auto &buffer : m_buffers) + buffer->setColorSpace(colorSpace()); } QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const @@ -698,10 +695,11 @@ bool QCALayerBackingStore::prepareForFlush() QCALayerBackingStore::GraphicsBuffer::GraphicsBuffer(const QSize &size, qreal devicePixelRatio, const QPixelFormat &format, QCFType colorSpace) - : QIOSurfaceGraphicsBuffer(size, format, colorSpace) + : QIOSurfaceGraphicsBuffer(size, format) , dirtyRegion(0, 0, size.width() / devicePixelRatio, size.height() / devicePixelRatio) , m_devicePixelRatio(devicePixelRatio) { + setColorSpace(colorSpace); } QImage *QCALayerBackingStore::GraphicsBuffer::asImage() diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index b7f15a2bf1..d8c931e9a1 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -396,6 +396,8 @@ QVariant QCocoaIntegration::styleHint(StyleHint hint) const return QCoreTextFontEngine::fontSmoothingGamma(); case ShowShortcutsInContextMenus: return QVariant(false); + // case CursorFlashTime: + // return 50000; default: break; } diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h index 872773cb7a..e070ba977d 100644 --- a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h +++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h @@ -48,9 +48,11 @@ QT_BEGIN_NAMESPACE class QIOSurfaceGraphicsBuffer : public QPlatformGraphicsBuffer { public: - QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format, QCFType colorSpace); + QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format); ~QIOSurfaceGraphicsBuffer(); + void setColorSpace(QCFType colorSpace); + const uchar *data() const override; uchar *data() override; int bytesPerLine() const override; diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm index a367487e85..285e316d4a 100644 --- a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm +++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaIOSurface, "qt.qpa.backingstore.iosurface"); -QIOSurfaceGraphicsBuffer::QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format, QCFType colorSpace) +QIOSurfaceGraphicsBuffer::QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format) : QPlatformGraphicsBuffer(size, format) { const size_t width = size.width(); @@ -81,17 +81,19 @@ QIOSurfaceGraphicsBuffer::QIOSurfaceGraphicsBuffer(const QSize &size, const QPix Q_ASSERT(size_t(bytesPerLine()) == bytesPerRow); Q_ASSERT(size_t(byteCount()) == totalBytes); - - if (colorSpace) { - IOSurfaceSetValue(m_surface, CFSTR("IOSurfaceColorSpace"), - QCFType(CGColorSpaceCopyPropertyList(colorSpace))); - } } QIOSurfaceGraphicsBuffer::~QIOSurfaceGraphicsBuffer() { } +void QIOSurfaceGraphicsBuffer::setColorSpace(QCFType colorSpace) +{ + Q_ASSERT(colorSpace); + IOSurfaceSetValue(m_surface, CFSTR("IOSurfaceColorSpace"), + QCFType(CGColorSpaceCopyPropertyList(colorSpace))); +} + const uchar *QIOSurfaceGraphicsBuffer::data() const { return (const uchar *)IOSurfaceGetBaseAddress(m_surface); -- cgit v1.2.3