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.5 6.2
Invaluable-research-by: Viktor Arvidsson
Change-Id: I06ea582c87fb0d359387ef9495451801612701c9
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 58caa18d2ff1a67e16f960f5bd6b804cdaec4063)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tor Arne Vestbø 2024-10-14 15:14:41 +02:00 committed by Qt Cherry-pick Bot
parent dc885e39c9
commit 11c8b80f4b

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());
return m_buffers.back()->asImage();
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;
}