Fix link to platform window in QAndroidPlatformBackingStore::flush()

The Android QPA implementation requires a 1:1 link between a platform
window and a platform backing store, to correctly flush a backing
store to the screen. QAndroidPlatformBackingStore has a bool member
m_backingStoreSet, to remember if this link exists. It defaults to
false and is set to true, when setBackingStore() is called in the
constructor. It falsely remains true, when a platform window is
deleted, e.g. because a QWindow has been hidden. When the QWindow is
shown again, a new Android platform window is created. With
m_backingStoreSet still being true, this new platform window will
never be associated with a backing store. As a consequence, it will
never be displayed on the screen.

The 1:1 relationship of an Android platform window and an Android
backing store is neither ideal, nor in line with other QPA layers
(e.g. XCB). Changing the Android QPA implementation is complex and a
short term fix is  necessary.

This patch removes the member m_backingStoreSet. Instead of it,
QAndroidPlatformBackingStore::flush() directly checks, if the platform
window corresponding to the QWindow argument is associated to a backing
store. If that is not the case, setBackingStore() is called.

QTBUG-97482 has been fixed with another approach, which this patch
reverts.

The following commits are effectively reverted by this patch:
9a39ad8dfb
f91588923b
a4ca9e8065
dbb072eb28
959a8b3967

Fixes: QTBUG-97482
Pick-to: 6.6 6.5 6.2
Change-Id: Ic4344f8df2e954c057dd2705340f11dfd2d4c6fe
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Axel Spoerl 2023-08-04 07:35:31 +02:00
parent 6f6e62650d
commit 86fe84f5f7
14 changed files with 12 additions and 50 deletions

View File

@ -32,7 +32,6 @@ class QScreen;
class QWindow;
class QIcon;
class QRegion;
class QPlatformBackingStore;
class Q_GUI_EXPORT QPlatformWindow : public QPlatformSurface
{
@ -118,8 +117,6 @@ public:
virtual void requestUpdate();
bool hasPendingUpdateRequest() const;
virtual void deliverUpdateRequest();
#define QT_PLATFORM_WINDOW_HAS_VIRTUAL_SET_BACKING_STORE // remove when all modules have migrated
virtual void setBackingStore(QPlatformBackingStore *) {}
// Window property accessors. Platform plugins should use these
// instead of accessing QWindow directly.

View File

@ -47,7 +47,6 @@ bool QFbScreen::event(QEvent *event)
void QFbScreen::addWindow(QFbWindow *window)
{
Q_ASSERT(window->backingStore());
mWindowStack.prepend(window);
if (!mPendingBackingStores.isEmpty()) {
//check if we have a backing store for this window

View File

@ -3,11 +3,9 @@
#include "qfbwindow_p.h"
#include "qfbscreen_p.h"
#include "qfbbackingstore_p.h"
#include <QtGui/QScreen>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformbackingstore.h>
QT_BEGIN_NAMESPACE
@ -113,11 +111,5 @@ void QFbWindow::repaint(const QRegion &region)
for (auto rect : region)
platformScreen()->setDirty(rect.translated(topLeft));
}
void QFbWindow::setBackingStore(QPlatformBackingStore *store)
{
Q_ASSERT(store);
Q_ASSERT_X(dynamic_cast<QFbBackingStore *>(store), __FUNCTION__,
"Argument is not a QFbBackingStore.");
mBackingStore = static_cast<QFbBackingStore *>(store);
}
QT_END_NAMESPACE

View File

@ -41,7 +41,7 @@ public:
WId winId() const override { return mWindowId; }
void setBackingStore(QPlatformBackingStore *store) override;
void setBackingStore(QFbBackingStore *store) { mBackingStore = store; }
QFbBackingStore *backingStore() const { return mBackingStore; }
QFbScreen *platformScreen() const;

View File

@ -25,10 +25,11 @@ void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion &region,
{
Q_UNUSED(offset);
if (!m_backingStoreSet)
auto *platformWindow = static_cast<QAndroidPlatformWindow *>(window->handle());
if (!platformWindow->backingStore())
setBackingStore(window);
(static_cast<QAndroidPlatformWindow *>(window->handle()))->repaint(region);
platformWindow->repaint(region);
}
void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
@ -42,7 +43,6 @@ void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &stat
void QAndroidPlatformBackingStore::setBackingStore(QWindow *window)
{
(static_cast<QAndroidPlatformWindow *>(window->handle()))->setBackingStore(this);
m_backingStoreSet = true;
}
QT_END_NAMESPACE

View File

@ -21,7 +21,6 @@ public:
void setBackingStore(QWindow *window);
protected:
QImage m_image;
bool m_backingStoreSet = false;
};
QT_END_NAMESPACE

View File

@ -43,7 +43,7 @@ public:
}
private:
QElapsedTimer m_timer;
QTime m_timer;
QString m_msg;
};

View File

@ -5,9 +5,9 @@
#include "qandroidplatformwindow.h"
#include "qandroidplatformopenglcontext.h"
#include "qandroidplatformscreen.h"
#include "qandroidplatformbackingstore.h"
#include "androidjnimain.h"
#include "qpa/qplatformbackingstore.h"
#include <qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qhighdpiscaling_p.h>
@ -169,12 +169,4 @@ void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
QWindowSystemInterface::flushWindowSystemEvents();
}
void QAndroidPlatformWindow::setBackingStore(QPlatformBackingStore *store)
{
Q_ASSERT(store);
Q_ASSERT_X(dynamic_cast<QAndroidPlatformBackingStore *>(store), __FUNCTION__,
"Argument is not a QAndroidPlatformBackingStore.");
m_backingStore = static_cast<QAndroidPlatformBackingStore *>(store);
}
QT_END_NAMESPACE

View File

@ -50,7 +50,7 @@ public:
virtual void applicationStateChanged(Qt::ApplicationState);
void setBackingStore(QPlatformBackingStore *store) override;
void setBackingStore(QAndroidPlatformBackingStore *store) { m_backingStore = store; }
QAndroidPlatformBackingStore *backingStore() const { return m_backingStore; }
virtual void repaint(const QRegion &) { }

View File

@ -108,12 +108,8 @@ void QEglFSWindow::create()
#endif
}
void QEglFSWindow::setBackingStore(QPlatformBackingStore *store)
void QEglFSWindow::setBackingStore(QOpenGLCompositorBackingStore *backingStore)
{
Q_ASSERT(store);
Q_ASSERT_X(dynamic_cast<QOpenGLCompositorBackingStore *>(store), __FUNCTION__,
"Argument is not a QOpenGLCompositorBackingStore.");
auto *backingStore = static_cast<QOpenGLCompositorBackingStore *>(store);
#ifndef QT_NO_OPENGL
if (!m_rasterCompositingContext) {
m_rasterCompositingContext = new QOpenGLContext;

View File

@ -71,7 +71,7 @@ public:
#ifndef QT_NO_OPENGL
QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; }
void setBackingStore(QPlatformBackingStore *backingStore) override;
void setBackingStore(QOpenGLCompositorBackingStore *backingStore);
QWindow *sourceWindow() const override;
const QPlatformTextureList *textures() const override;
void endCompositing() override;

View File

@ -236,14 +236,6 @@ QWasmScreen *QWasmWindow::platformScreen() const
return static_cast<QWasmScreen *>(window()->screen()->handle());
}
void QWasmWindow::setBackingStore(QPlatformBackingStore *store)
{
Q_ASSERT(store);
Q_ASSERT_X(dynamic_cast<QWasmBackingStore *>(store), __FUNCTION__,
"Argument is not a QWasmBackingStore.");
m_backingStore = static_cast<QWasmBackingStore *>(store);
}
void QWasmWindow::paint()
{
if (!m_backingStore || !isVisible() || m_context2d.isUndefined())

View File

@ -89,7 +89,7 @@ public:
void setParent(const QPlatformWindow *window) final;
QWasmScreen *platformScreen() const;
void setBackingStore(QPlatformBackingStore *store) override;
void setBackingStore(QWasmBackingStore *store) { m_backingStore = store; }
QWasmBackingStore *backingStore() const { return m_backingStore; }
QWindow *window() const { return m_window; }

View File

@ -1332,11 +1332,6 @@ void QWidgetPrivate::create()
QBackingStore *store = q->backingStore();
usesRhiFlush = false;
// Re-use backing store, in case a new platform window was created and doesn't know about it.
// (e.g. QAndroidPlatformWindow)
if (store && q->windowHandle())
q->windowHandle()->handle()->setBackingStore(store->handle());
if (!store) {
if (q->windowType() != Qt::Desktop) {
if (q->isWindow()) {