Cocoa: Fix backing store performance regression.

Commit 916dfcb8 introduced a regression where QNSView
would hold a copy if the backing store QImage, which
would cause a detach and deep copy if/when the image
was painted on while the copy was held.

Revert back to the previous share-by-pointer scheme.
Make sure the following bugs stays fixed:
    QTBUG-38377
    QTBUG-42206
    QTBUG-44313

Change-Id: Ib8049051d51947113f23b66ee61dc34c22388914
Task-number: QTBUG-46959
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
This commit is contained in:
Morten Johan Sørvig 2015-08-13 21:42:10 +02:00
parent dbb1e1936c
commit 53ecaade10
3 changed files with 22 additions and 15 deletions

View File

@ -44,6 +44,8 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QCocoaBackingStore::~QCocoaBackingStore()
{
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()))
[cocoaWindow->m_qtView clearBackingStore:this];
}
QPaintDevice *QCocoaBackingStore::paintDevice()

View File

@ -51,8 +51,7 @@ QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
QImage m_backingStore;
qreal m_pixelRatio;
QCocoaBackingStore* m_backingStore;
QPoint m_backingStoreOffset;
CGImageRef m_maskImage;
uchar *m_maskData;
@ -86,6 +85,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;

View File

@ -135,7 +135,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
{
self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
if (self) {
m_pixelRatio = 1.;
m_backingStore = 0;
m_maskImage = 0;
m_shouldInvalidateWindowShadow = false;
m_window = 0;
@ -371,7 +371,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
if (!m_platformWindow->m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
else
m_backingStore = QImage();
m_backingStore = 0;
}
}
@ -476,12 +476,16 @@ QT_WARNING_POP
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore->toImage();
m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio();
m_backingStoreOffset = offset * m_pixelRatio;
foreach (QRect rect, region.rects()) {
m_backingStore = backingStore;
m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
foreach (QRect rect, region.rects())
[self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
}
}
- (void)clearBackingStore:(QCocoaBackingStore *)backingStore
{
if (backingStore == m_backingStore)
m_backingStore = 0;
}
- (BOOL) hasMask
@ -544,7 +548,7 @@ QT_WARNING_POP
if (m_platformWindow->m_drawContentBorderGradient)
NSDrawWindowBackground(dirtyRect);
if (m_backingStore.isNull())
if (!m_backingStore)
return;
// Calculate source and target rects. The target rect is the dirtyRect:
@ -552,10 +556,11 @@ QT_WARNING_POP
// The backing store source rect will be larger on retina displays.
// Scale dirtyRect by the device pixel ratio:
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio,
dirtyRect.origin.y * m_pixelRatio,
dirtyRect.size.width * m_pixelRatio,
dirtyRect.size.height * m_pixelRatio);
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);
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
@ -581,7 +586,7 @@ QT_WARNING_POP
dirtyBackingRect.size.width,
dirtyBackingRect.size.height
);
CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore);
CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage());
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
// Optimization: Copy frame buffer content instead of blending for