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;
}
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
<< "to" << flushedView.layer << "of" << flushedView;
if (flushedView == backingStoreView) {
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) {
const CGSize backingStoreSize = backingStoreView.bounds.size;
flushedView.layer.contentsRect = CGRectApplyAffineTransform(
[flushedView convertRect:flushedView.bounds toView:backingStoreView],
// The contentsRect is in unit coordinate system
CGAffineTransformMakeScale(1.0 / backingStoreSize.width, 1.0 / backingStoreSize.height));
qCInfo(lcQpaBackingStore) << "Flushing" << subImage
<< "to" << flushedView.layer << "of subview" << flushedView;
QCFType<CGImageRef> cgImage = subImage.toCGImage();
flushedView.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage);
}
// Since we may receive multiple flushes before a new frame is started, we do not