OS X - Cocoa backing store and drawRect
m_backingStore pointer has a limited 'lifetime' - usually it is set in -flushBackingStore:region:offset: method, then -drawRect: is invoked/forced by -setNeedsDisplayInRect:, after that it's dangerous to have a non-null pointer to a backing store (and we reset it). But if Cocoa invokes drawRect (due to some reason) our null backing store pointer is also not good. This patch instead is using a shared resource (QImage) from a backing store. This patch also makes getBackingStoreCGImage() redundant - -drawRect: was the only place we called it. Task-number: QTBUG-42206 Change-Id: Ie7726336f05d07c52f660f6326ae5cef114201dd Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>bb10
parent
148aa0e3e3
commit
916dfcb827
|
|
@ -51,12 +51,9 @@ public:
|
|||
|
||||
QPaintDevice *paintDevice();
|
||||
void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset);
|
||||
#ifndef QT_NO_OPENGL
|
||||
QImage toImage() const Q_DECL_OVERRIDE;
|
||||
#endif
|
||||
QImage toImage() const;
|
||||
void resize (const QSize &size, const QRegion &);
|
||||
bool scroll(const QRegion &area, int dx, int dy);
|
||||
CGImageRef getBackingStoreCGImage();
|
||||
qreal getBackingStoreDevicePixelRatio();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -96,12 +96,10 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
QImage QCocoaBackingStore::toImage() const
|
||||
{
|
||||
return m_qImage;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
|
||||
{
|
||||
|
|
@ -121,17 +119,6 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
|
|||
return true;
|
||||
}
|
||||
|
||||
CGImageRef QCocoaBackingStore::getBackingStoreCGImage()
|
||||
{
|
||||
if (!m_cgImage)
|
||||
m_cgImage = qt_mac_toCGImage(m_qImage);
|
||||
|
||||
// Warning: do not retain/release/cache the returned image from
|
||||
// outside the backingstore since it shares data with a QImage and
|
||||
// needs special memory considerations.
|
||||
return m_cgImage;
|
||||
}
|
||||
|
||||
qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
|
||||
{
|
||||
return m_qImage.devicePixelRatio();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ QT_END_NAMESPACE
|
|||
Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper);
|
||||
|
||||
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
|
||||
QCocoaBackingStore* m_backingStore;
|
||||
QImage m_backingStore;
|
||||
qreal m_pixelRatio;
|
||||
QPoint m_backingStoreOffset;
|
||||
CGImageRef m_maskImage;
|
||||
uchar *m_maskData;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
{
|
||||
self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
|
||||
if (self) {
|
||||
m_backingStore = 0;
|
||||
m_pixelRatio = 1.;
|
||||
m_maskImage = 0;
|
||||
m_shouldInvalidateWindowShadow = false;
|
||||
m_window = 0;
|
||||
|
|
@ -466,8 +466,9 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
|
||||
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
|
||||
{
|
||||
m_backingStore = backingStore;
|
||||
m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
|
||||
m_backingStore = backingStore->toImage();
|
||||
m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio();
|
||||
m_backingStoreOffset = offset * m_pixelRatio;
|
||||
foreach (QRect rect, region.rects()) {
|
||||
[self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
|
||||
}
|
||||
|
|
@ -531,7 +532,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
if (m_platformWindow->m_drawContentBorderGradient)
|
||||
NSDrawWindowBackground(dirtyRect);
|
||||
|
||||
if (!m_backingStore)
|
||||
if (m_backingStore.isNull())
|
||||
return;
|
||||
|
||||
// Calculate source and target rects. The target rect is the dirtyRect:
|
||||
|
|
@ -539,11 +540,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
|
||||
// The backing store source rect will be larger on retina displays.
|
||||
// Scale dirtyRect by the device pixel ratio:
|
||||
const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio();
|
||||
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
|
||||
dirtyRect.origin.y * devicePixelRatio,
|
||||
dirtyRect.size.width * devicePixelRatio,
|
||||
dirtyRect.size.height * devicePixelRatio);
|
||||
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio,
|
||||
dirtyRect.origin.y * m_pixelRatio,
|
||||
dirtyRect.size.width * m_pixelRatio,
|
||||
dirtyRect.size.height * m_pixelRatio);
|
||||
|
||||
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
|
||||
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
|
||||
|
|
@ -569,7 +569,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
dirtyBackingRect.size.width,
|
||||
dirtyBackingRect.size.height
|
||||
);
|
||||
CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage();
|
||||
CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore);
|
||||
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
|
||||
|
||||
// Optimization: Copy frame buffer content instead of blending for
|
||||
|
|
@ -586,8 +586,6 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
|
|||
CGImageRelease(subMask);
|
||||
|
||||
[self invalidateWindowShadowIfNeeded];
|
||||
|
||||
m_backingStore = 0;
|
||||
}
|
||||
|
||||
- (BOOL) isFlipped
|
||||
|
|
|
|||
Loading…
Reference in New Issue