macOS: Optionally flush sub-layers via sub-image copies of the backingstore

When we're flushing the backingstore to sub-views with their own layers
we don't want to pay the cost of uploading the whole backingstore to the
GPU in the case where we're dealing with a discrete GPU.

To work around this we make a copy of the appropriate part of the surfcace.

This results in additional copies of the data, and will need further
investigation to limit these.

Task-number: QTBUG-77447
Change-Id: I318ae80e433dd7b0a55fd5a598b19f114d8bd28e
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit eaf4911db29a82b3d94826a8ff09afe075a2b636)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-09-12 13:29:25 +02:00
parent 45237fa54c
commit 197dfcd36f

View File

@ -572,17 +572,26 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
flushedView.layer.contents = nil; flushedView.layer.contents = nil;
} }
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface if (flushedView == backingStoreView) {
<< "to" << flushedView.layer << "of" << flushedView; qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
<< "to" << flushedView.layer << "of" << flushedView;
flushedView.layer.contents = backBufferSurface;
} else {
auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView];
auto scale = flushedView.layer.contentsScale;
subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale));
flushedView.layer.contents = backBufferSurface; // We make a copy of the image data up front, which means we don't
// need to mark the IOSurface as being in use. FIXME: Investigate
// if there's a cheaper way to get sub-image data to a layer.
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess);
QImage subImage = m_buffers.back()->asImage()->copy(QRectF::fromCGRect(subviewRect).toRect());
m_buffers.back()->unlock();
if (flushedView != backingStoreView) { qCInfo(lcQpaBackingStore) << "Flushing" << subImage
const CGSize backingStoreSize = backingStoreView.bounds.size; << "to" << flushedView.layer << "of subview" << flushedView;
flushedView.layer.contentsRect = CGRectApplyAffineTransform( QCFType<CGImageRef> cgImage = subImage.toCGImage();
[flushedView convertRect:flushedView.bounds toView:backingStoreView], flushedView.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage);
// The contentsRect is in unit coordinate system
CGAffineTransformMakeScale(1.0 / backingStoreSize.width, 1.0 / backingStoreSize.height));
} }
// Since we may receive multiple flushes before a new frame is started, we do not // Since we may receive multiple flushes before a new frame is started, we do not