From 77a4915bf900aac0c96260018c0a4ccfbdd7c094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 30 Jan 2019 13:14:38 +0100 Subject: macOS: Add IOSurface based backingstore for layer-backed views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The naïve approach used for layer-backing in the past caused a detach of the backingstore QImage on each beginPaint, since the image was assigned to the layer via a CGImageRef that participated in the QImage implicit sharing (and had to, so we couldn't get around that). We now use IOSurfaces, wrapped in a QPlatformGraphicsBuffer abstraction. The surfaces can be assigned to the layer's content the same way images could, but allows us to reason more closely about whether or a buffer is in use, and increases the chance that we will have a zero-copy path to the screen. Unless the window has requested a surface format with single buffering we use a dynamic swap chain of buffers. In most situations there will be two buffers in play, one assigned to the layer and one ready to paint to, but during resize and some other situations the buffers will grow temporarily to accommodate the increased back-pressure. Since QBackingStore is documented as having single-buffer behavior, we take care to persist content between the buffers before every swap. By doing this before swapping, instead of before each paint, we can avoid preserving areas that will be painted to anyways, and will in many situations (such as blinking cursors e.g.) end up not persisting anything. The RasterGL surface case is handled by reading out the buffer data and doing a manual texture upload. In the future we can support direct texture access via CGLTexImageIOSurface2D, but this requires QPlatformBackingStore::composeAndFlush to learn how to support other targets than GL_TEXTURE_2D, as CGLTexImageIOSurface2D only works with GL_TEXTURE_RECTANGLE_ARB targets. Fixes: QTBUG-48763 Fixes: QTBUG-72360 Fixes: QTBUG-71162 Change-Id: Ica12f69b244e54d0fd31c929730d15657c286af8 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 52 ++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'src/plugins/platforms/cocoa/qcocoabackingstore.h') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index b4cd506513..508f24d578 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -44,13 +44,16 @@ #include +#include +#include "qiosurfacegraphicsbuffer.h" + QT_BEGIN_NAMESPACE -class QCocoaBackingStore : public QRasterBackingStore +class QNSWindowBackingStore : public QRasterBackingStore { public: - QCocoaBackingStore(QWindow *window); - ~QCocoaBackingStore(); + QNSWindowBackingStore(QWindow *window); + ~QNSWindowBackingStore(); void flush(QWindow *, const QRegion &, const QPoint &) override; @@ -60,6 +63,49 @@ private: void redrawRoundedBottomCorners(CGRect) const; }; +class QCALayerBackingStore : public QPlatformBackingStore +{ +public: + QCALayerBackingStore(QWindow *window); + ~QCALayerBackingStore(); + + void resize(const QSize &size, const QRegion &staticContents) override; + + void beginPaint(const QRegion ®ion) override; + QPaintDevice *paintDevice() override; + void endPaint() override; + + void flush(QWindow *, const QRegion &, const QPoint &) override; + void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, bool translucentBackground) override; + + QPlatformGraphicsBuffer *graphicsBuffer() const override; + +private: + QSize m_requestedSize; + QRegion m_paintedRegion; + + class GraphicsBuffer : public QIOSurfaceGraphicsBuffer + { + public: + GraphicsBuffer(const QSize &size, qreal devicePixelRatio, + const QPixelFormat &format, QCFType colorSpace); + + QRegion dirtyRegion; // In unscaled coordinates + QImage *asImage(); + + private: + qreal m_devicePixelRatio; + QImage m_image; + }; + + void ensureBackBuffer(); + bool recreateBackBufferIfNeeded(); + bool prepareForFlush(); + + std::list> m_buffers; +}; + QT_END_NAMESPACE #endif -- cgit v1.2.3