macOS: Avoid creating 0x0 size IOSurface in backing-store

During screen attach/detach, we may end up in a situation where the
window has a 0x0 size, and we end up painting to the window, in which
case we were trying to create an IOSurface of size 0x0. This resulted
in the creation failing, triggering an assert.

We now guard the surface creation with a check for the backing store
size being non-empty, and for empty sizes we fall back to a plain
null-QImage for our paint device.

Fixes: QTBUG-128731
Pick-to: 6.8 6.5 6.2
Invaluable-research-by: Viktor Arvidsson
Change-Id: I06ea582c87fb0d359387ef9495451801612701c9
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Tor Arne Vestbø 2024-10-14 15:14:41 +02:00
parent bab1fd8fc3
commit 58caa18d2f

View File

@ -88,6 +88,13 @@ void QCALayerBackingStore::beginPaint(const QRegion &region)
qCInfo(lcQpaBackingStore) << "Beginning paint of" << region << "into backingstore of" << m_requestedSize;
if (m_requestedSize.isEmpty()) {
// We can't create IOSurfaces with and empty size, so instead reset our back buffer
qCDebug(lcQpaBackingStore) << "Size is empty, throwing away back buffer";
m_buffers.back().reset(nullptr);
return;
}
ensureBackBuffer(); // Find an unused back buffer, or reserve space for a new one
const bool bufferWasRecreated = recreateBackBufferIfNeeded();
@ -241,12 +248,19 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded()
QPaintDevice *QCALayerBackingStore::paintDevice()
{
Q_ASSERT(m_buffers.back());
if (m_buffers.back()) {
return m_buffers.back()->asImage();
} else {
static QImage fallbackDevice;
return &fallbackDevice;
}
}
void QCALayerBackingStore::endPaint()
{
if (!m_buffers.back())
return;
qCInfo(lcQpaBackingStore) << "Paint ended. Back buffer valid region is now" << m_buffers.back()->validRegion();
m_buffers.back()->unlock();
@ -317,7 +331,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
Q_UNUSED(offset);
if (!m_buffers.back()) {
qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring.";
return;
}
@ -444,7 +458,7 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo
bool translucentBackground)
{
if (!m_buffers.back()) {
qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring.";
return FlushFailed;
}