Skip to content

Instantly share code, notes, and snippets.

@torarnv
Created August 15, 2019 15:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save torarnv/d9f1ebf1545b2ac68e5b51eea8f0f1b5 to your computer and use it in GitHub Desktop.
Save torarnv/d9f1ebf1545b2ac68e5b51eea8f0f1b5 to your computer and use it in GitHub Desktop.
diff --git i/src/plugins/platforms/cocoa/qcocoabackingstore.mm w/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index af50aabe15..f9e2f792eb 100644
--- i/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ w/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -46,6 +46,13 @@
#include <QuartzCore/CATransaction.h>
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+extern "C" {
+CGContextRef CGIOSurfaceContextCreate(IOSurfaceRef, size_t, size_t, size_t, size_t, CGColorSpaceRef, CGBitmapInfo);
+CGImageRef CGIOSurfaceContextCreateImage(CGContextRef);
+}
+#endif
+
QT_BEGIN_NAMESPACE
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
@@ -531,6 +538,26 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
<< "to" << flushedView.layer << "of" << flushedView;
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+ CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+ size_t bitsPerComponent = 8;
+ size_t bitsPerPixel = 32;
+ QSize bufferSize = m_buffers.back()->size();
+ QCFType<CGContextRef> context = CGIOSurfaceContextCreate(m_buffers.back()->surface(),
+ bufferSize.width(), bufferSize.height(), bitsPerComponent, bitsPerPixel,
+ colorSpace(), bitmapInfo);
+
+ QCFType<CGImageRef> image = CGIOSurfaceContextCreateImage(context);
+
+ if (flushedView != backingStoreView) {
+ auto rect = [flushedView convertRect:flushedView.bounds toView:backingStoreView];
+ auto scale = flushedView.layer.contentsScale;
+ rect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(scale, scale));
+ image = CGImageCreateWithImageInRect(image, rect);
+ }
+
+ flushedView.layer.contents = (__bridge id)static_cast<CGImageRef>(image);
+#else
flushedView.layer.contents = backBufferSurface;
if (flushedView != backingStoreView) {
@@ -540,6 +567,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
// The contentsRect is in unit coordinate system
CGAffineTransformMakeScale(1.0 / backingStoreSize.width, 1.0 / backingStoreSize.height));
}
+#endif
// Since we may receive multiple flushes before a new frame is started, we do not
// swap any buffers just yet. Instead we check in the next beginPaint if the layer's
diff --git i/src/widgets/kernel/qwidget.cpp w/src/widgets/kernel/qwidget.cpp
index 574a490ec7..0682bca3c3 100644
--- i/src/widgets/kernel/qwidget.cpp
+++ w/src/widgets/kernel/qwidget.cpp
@@ -5433,9 +5433,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
sourced->context = 0;
- // Native widgets need to be marked dirty on screen so painting will be done in correct context
- // Same check as in the no effects case below.
- if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
+ if (backingStore)
backingStore->markDirtyOnScreen(rgn, q, offset);
return;
@@ -5554,8 +5552,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
sendPaintEvent(toBePainted);
}
- // Native widgets need to be marked dirty on screen so painting will be done in correct context
- if (backingStore && !onScreen && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow())))
+ if (backingStore)
backingStore->markDirtyOnScreen(toBePainted, q, offset);
//restore
diff --git i/src/widgets/kernel/qwidgetbackingstore.cpp w/src/widgets/kernel/qwidgetbackingstore.cpp
index 48fc73a867..00d963811e 100644
--- i/src/widgets/kernel/qwidgetbackingstore.cpp
+++ w/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -333,9 +333,6 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBacking
Q_UNUSED(widget);
Q_UNUSED(toCleanIsInTopLevelCoordinates);
- // Always flush repainted areas.
- dirtyOnScreen += toClean;
-
#ifdef QT_NO_PAINT_DEBUG
backingStore->beginPaint(toClean);
#else
@@ -714,8 +711,7 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
// Top-level.
if (widget == tlw) {
- if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
- dirtyOnScreen += region;
+ dirtyOnScreen += region;
return;
}
@@ -723,8 +719,7 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
if (!hasPlatformWindow(widget) && !widget->isWindow()) {
QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
if (nativeParent == tlw) {
- if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
- dirtyOnScreen += region.translated(topLevelOffset);
+ dirtyOnScreen += region.translated(topLevelOffset);
return;
}
@@ -1175,11 +1170,6 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
return;
}
- if (exposedWidget != tlw)
- markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint()));
- else
- markDirtyOnScreen(exposedRegion, exposedWidget, QPoint());
-
if (syncAllowed())
doSync();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment