Android: Give raster windows their own surface, and flush via RHI
Refactored platform windows on Android so that all window types, including raster windows, have their own surface to draw on. Raster windows now flush the backing-store via RHI/OpenGL. As a drive by, update to newer JNI syntax where appropriate. Task-number: QTBUG-116187 Change-Id: I3b764b7126abf53556750b0ccbb7d27efe007bc1 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
76b58be4b8
commit
2020ce5fd2
@ -377,7 +377,7 @@ class QtNative
|
||||
// application methods
|
||||
|
||||
// surface methods
|
||||
public static native void setSurface(int id, Object surface, int w, int h);
|
||||
public static native void setSurface(int id, Object surface);
|
||||
// surface methods
|
||||
|
||||
// window methods
|
||||
|
@ -50,13 +50,13 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
||||
if (width < 1 || height < 1)
|
||||
return;
|
||||
|
||||
QtNative.setSurface(getId(), holder.getSurface(), width, height);
|
||||
QtNative.setSurface(getId(), holder.getSurface());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder)
|
||||
{
|
||||
QtNative.setSurface(getId(), null, 0, 0);
|
||||
QtNative.setSurface(getId(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -641,6 +641,8 @@ endif()
|
||||
qt_internal_extend_target(Gui CONDITION ANDROID
|
||||
SOURCES
|
||||
platform/android/qandroidnativeinterface.cpp
|
||||
painting/qrasterbackingstore.cpp painting/qrasterbackingstore_p.h
|
||||
painting/qrhibackingstore.cpp painting/qrhibackingstore_p.h
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STREQUAL arm64 OR TEST_architecture_arch STREQUAL arm)
|
||||
|
@ -17,13 +17,11 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
|
||||
androidjniinput.cpp androidjniinput.h
|
||||
androidjnimain.cpp androidjnimain.h
|
||||
androidjnimenu.cpp androidjnimenu.h
|
||||
androidsurfaceclient.h
|
||||
main.cpp
|
||||
qandroidassetsfileenginehandler.cpp qandroidassetsfileenginehandler.h
|
||||
qandroideventdispatcher.cpp qandroideventdispatcher.h
|
||||
qandroidinputcontext.cpp qandroidinputcontext.h
|
||||
qandroidplatformaccessibility.cpp qandroidplatformaccessibility.h
|
||||
qandroidplatformbackingstore.cpp qandroidplatformbackingstore.h
|
||||
qandroidplatformclipboard.cpp qandroidplatformclipboard.h
|
||||
qandroidplatformdialoghelpers.cpp qandroidplatformdialoghelpers.h
|
||||
qandroidplatformfiledialoghelper.cpp qandroidplatformfiledialoghelper.h
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qandroidplatformdialoghelpers.h"
|
||||
#include "qandroidplatformintegration.h"
|
||||
#include "qandroidplatformclipboard.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
@ -69,7 +70,7 @@ static void *m_mainLibraryHnd = nullptr;
|
||||
static QList<QByteArray> m_applicationParams;
|
||||
static sem_t m_exitSemaphore, m_terminateSemaphore;
|
||||
|
||||
QHash<int, AndroidSurfaceClient *> m_surfaces;
|
||||
QHash<int, QAndroidPlatformWindow *> m_surfaces;
|
||||
|
||||
Q_CONSTINIT static QBasicMutex m_surfacesMutex;
|
||||
|
||||
@ -323,7 +324,7 @@ namespace QtAndroid
|
||||
return QJniObject::callStaticMethod<jint>("android/view/View", "generateViewId", "()I");
|
||||
}
|
||||
|
||||
int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth)
|
||||
int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth)
|
||||
{
|
||||
QJniEnvironment env;
|
||||
if (!env.jniEnv())
|
||||
@ -331,7 +332,7 @@ namespace QtAndroid
|
||||
|
||||
m_surfacesMutex.lock();
|
||||
jint surfaceId = generateViewId();
|
||||
m_surfaces[surfaceId] = client;
|
||||
m_surfaces[surfaceId] = window;
|
||||
m_surfacesMutex.unlock();
|
||||
|
||||
jint x = 0, y = 0, w = -1, h = -1;
|
||||
@ -594,8 +595,11 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
|
||||
sem_post(&m_exitSemaphore);
|
||||
}
|
||||
|
||||
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
|
||||
static void setSurface(JNIEnv *env, jobject thiz, jint id, jobject jSurface)
|
||||
{
|
||||
Q_UNUSED(env);
|
||||
Q_UNUSED(thiz);
|
||||
|
||||
QMutexLocker lock(&m_surfacesMutex);
|
||||
const auto &it = m_surfaces.find(id);
|
||||
if (it == m_surfaces.end())
|
||||
@ -603,7 +607,7 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
|
||||
|
||||
auto surfaceClient = it.value();
|
||||
if (surfaceClient)
|
||||
surfaceClient->surfaceChanged(env, jSurface, w, h);
|
||||
surfaceClient->onSurfaceChanged(jSurface);
|
||||
}
|
||||
|
||||
static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWidthPixels,
|
||||
@ -658,10 +662,6 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
|
||||
QWindowSystemInterface::handleExposeEvent(w, QRegion(QRect(QPoint(), w->geometry().size())));
|
||||
}
|
||||
}
|
||||
|
||||
QAndroidPlatformScreen *screen = static_cast<QAndroidPlatformScreen *>(m_androidPlatformIntegration->screen());
|
||||
if (screen->rasterSurfaces())
|
||||
QMetaObject::invokeMethod(screen, "setDirty", Qt::QueuedConnection, Q_ARG(QRect,screen->geometry()));
|
||||
}
|
||||
|
||||
static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state)
|
||||
@ -802,7 +802,7 @@ static JNINativeMethod methods[] = {
|
||||
{ "quitQtCoreApplication", "()V", (void *)quitQtCoreApplication },
|
||||
{ "terminateQt", "()V", (void *)terminateQt },
|
||||
{ "waitForServiceSetup", "()V", (void *)waitForServiceSetup },
|
||||
{ "setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface },
|
||||
{ "setSurface", "(ILjava/lang/Object;)V", (void *)setSurface },
|
||||
{ "updateWindow", "()V", (void *)updateWindow },
|
||||
{ "updateApplicationState", "(I)V", (void *)updateApplicationState },
|
||||
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
|
||||
|
@ -23,7 +23,7 @@ class QAndroidPlatformIntegration;
|
||||
class QWidget;
|
||||
class QString;
|
||||
class QWindow;
|
||||
class AndroidSurfaceClient;
|
||||
class QAndroidPlatformWindow;
|
||||
class QBasicMutex;
|
||||
|
||||
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
|
||||
@ -37,7 +37,7 @@ namespace QtAndroid
|
||||
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
||||
void setQtThread(QThread *thread);
|
||||
|
||||
int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop, int imageDepth);
|
||||
int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth);
|
||||
int insertNativeView(QtJniTypes::View view, const QRect &geometry);
|
||||
void setViewVisibility(jobject view, bool visible);
|
||||
void setSurfaceGeometry(int surfaceId, const QRect &geometry);
|
||||
|
@ -1,24 +0,0 @@
|
||||
// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef ANDROIDSURFACECLIENT_H
|
||||
#define ANDROIDSURFACECLIENT_H
|
||||
#include <QMutex>
|
||||
#include <jni.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class AndroidSurfaceClient
|
||||
{
|
||||
public:
|
||||
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) = 0;
|
||||
void lockSurface() { m_surfaceMutex.lock(); }
|
||||
void unlockSurface() { m_surfaceMutex.unlock(); }
|
||||
|
||||
protected:
|
||||
QMutex m_surfaceMutex;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // ANDROIDSURFACECLIENT_H
|
@ -1,48 +0,0 @@
|
||||
// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qandroidplatformbackingstore.h"
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
#include <qpa/qplatformscreen.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QAndroidPlatformBackingStore::QAndroidPlatformBackingStore(QWindow *window)
|
||||
: QPlatformBackingStore(window)
|
||||
{
|
||||
if (window->handle())
|
||||
setBackingStore(window);
|
||||
}
|
||||
|
||||
QPaintDevice *QAndroidPlatformBackingStore::paintDevice()
|
||||
{
|
||||
return &m_image;
|
||||
}
|
||||
|
||||
void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
Q_UNUSED(offset);
|
||||
|
||||
auto *platformWindow = static_cast<QAndroidPlatformWindow *>(window->handle());
|
||||
if (!platformWindow->backingStore())
|
||||
setBackingStore(window);
|
||||
|
||||
platformWindow->repaint(region);
|
||||
}
|
||||
|
||||
void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
{
|
||||
Q_UNUSED(staticContents);
|
||||
|
||||
if (m_image.size() != size)
|
||||
m_image = QImage(size, window()->screen()->handle()->format());
|
||||
}
|
||||
|
||||
void QAndroidPlatformBackingStore::setBackingStore(QWindow *window)
|
||||
{
|
||||
(static_cast<QAndroidPlatformWindow *>(window->handle()))->setBackingStore(this);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -1,28 +0,0 @@
|
||||
// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QANDROIDPLATFORMBACKINGSTORE_H
|
||||
#define QANDROIDPLATFORMBACKINGSTORE_H
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
explicit QAndroidPlatformBackingStore(QWindow *window);
|
||||
QPaintDevice *paintDevice() override;
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override;
|
||||
void resize(const QSize &size, const QRegion &staticContents) override;
|
||||
QImage toImage() const override { return m_image; }
|
||||
void setBackingStore(QWindow *window);
|
||||
protected:
|
||||
QImage m_image;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QANDROIDPLATFORMBACKINGSTORE_H
|
@ -4,7 +4,6 @@
|
||||
#ifndef QANDROIDPLATFORMFOREIGNWINDOW_H
|
||||
#define QANDROIDPLATFORMFOREIGNWINDOW_H
|
||||
|
||||
#include "androidsurfaceclient.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
|
||||
#include <QtCore/QJniObject>
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qandroideventdispatcher.h"
|
||||
#include "qandroidplatformaccessibility.h"
|
||||
#include "qandroidplatformbackingstore.h"
|
||||
#include "qandroidplatformclipboard.h"
|
||||
#include "qandroidplatformfontdatabase.h"
|
||||
#include "qandroidplatformforeignwindow.h"
|
||||
@ -29,6 +28,7 @@
|
||||
#include <QtGui/private/qeglpbuffer_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/private/qoffscreensurface_p.h>
|
||||
#include <QtGui/private/qrhibackingstore_p.h>
|
||||
#include <qpa/qplatformoffscreensurface.h>
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
@ -323,6 +323,9 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
|
||||
case RasterGLSurface: return QtAndroidPrivate::activity().isValid();
|
||||
case TopStackedNativeChildWindows: return false;
|
||||
case MaximizeUsingFullscreenGeometry: return true;
|
||||
// FIXME QTBUG-118849 - we do not implement grabWindow() anymore, calling it will return
|
||||
// a null QPixmap also for raster windows - for OpenGL windows this was always true
|
||||
case ScreenWindowGrabbing: return false;
|
||||
default:
|
||||
return QPlatformIntegration::hasCapability(cap);
|
||||
}
|
||||
@ -333,7 +336,7 @@ QPlatformBackingStore *QAndroidPlatformIntegration::createPlatformBackingStore(Q
|
||||
if (!QtAndroidPrivate::activity().isValid())
|
||||
return nullptr;
|
||||
|
||||
return new QAndroidPlatformBackingStore(window);
|
||||
return new QRhiBackingStore(window);
|
||||
}
|
||||
|
||||
QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||
|
@ -24,41 +24,19 @@ QT_BEGIN_NAMESPACE
|
||||
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
|
||||
:QAndroidPlatformWindow(window), m_eglDisplay(display)
|
||||
{
|
||||
if (window->surfaceType() == QSurface::RasterSurface)
|
||||
window->setSurfaceType(QSurface::OpenGLSurface);
|
||||
}
|
||||
|
||||
QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
|
||||
{
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
lockSurface();
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
destroySurface();
|
||||
clearEgl();
|
||||
unlockSurface();
|
||||
}
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::repaint(const QRegion ®ion)
|
||||
{
|
||||
// This is only for real raster top-level windows. Stop in all other cases.
|
||||
if ((window()->surfaceType() == QSurface::RasterGLSurface && qt_window_private(window())->compositing)
|
||||
|| window()->surfaceType() == QSurface::OpenGLSurface
|
||||
|| QAndroidPlatformWindow::parent())
|
||||
return;
|
||||
|
||||
QRect currentGeometry = geometry();
|
||||
|
||||
QRect dirtyClient = region.boundingRect();
|
||||
QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(),
|
||||
currentGeometry.top() + dirtyClient.top(),
|
||||
dirtyClient.width(),
|
||||
dirtyClient.height());
|
||||
QRect mOldGeometryLocal = m_oldGeometry;
|
||||
m_oldGeometry = currentGeometry;
|
||||
// If this is a move, redraw the previous location
|
||||
if (mOldGeometryLocal != currentGeometry)
|
||||
platformScreen()->setDirty(mOldGeometryLocal);
|
||||
platformScreen()->setDirty(dirtyRegion);
|
||||
}
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
if (rect == geometry())
|
||||
@ -67,8 +45,7 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
||||
m_oldGeometry = geometry();
|
||||
|
||||
QAndroidPlatformWindow::setGeometry(rect);
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
||||
setSurfaceGeometry(rect);
|
||||
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (rect.width() > 0
|
||||
@ -77,9 +54,6 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
||||
&& availableGeometry.height() > 0) {
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
|
||||
}
|
||||
|
||||
if (rect.topLeft() != m_oldGeometry.topLeft())
|
||||
repaint(QRegion(rect));
|
||||
}
|
||||
|
||||
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
||||
@ -94,8 +68,7 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
||||
if (!protector.acquire())
|
||||
return m_eglSurface;
|
||||
|
||||
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
|
||||
createSurface();
|
||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||
}
|
||||
|
||||
@ -127,10 +100,7 @@ void QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState
|
||||
QAndroidPlatformWindow::applicationStateChanged(state);
|
||||
if (state <= Qt::ApplicationHidden) {
|
||||
lockSurface();
|
||||
if (m_nativeSurfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
m_nativeSurfaceId = -1;
|
||||
}
|
||||
destroySurface();
|
||||
clearEgl();
|
||||
unlockSurface();
|
||||
}
|
||||
@ -173,24 +143,4 @@ void QAndroidPlatformOpenGLWindow::clearEgl()
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h)
|
||||
{
|
||||
Q_UNUSED(jniEnv);
|
||||
Q_UNUSED(w);
|
||||
Q_UNUSED(h);
|
||||
|
||||
lockSurface();
|
||||
m_androidSurfaceObject = surface;
|
||||
if (surface) // wait until we have a valid surface to draw into
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
unlockSurface();
|
||||
|
||||
if (surface) {
|
||||
// repaint the window, when we have a valid surface
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size())));
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef QANDROIDPLATFORMOPENGLWINDOW_H
|
||||
#define QANDROIDPLATFORMOPENGLWINDOW_H
|
||||
|
||||
#include "androidsurfaceclient.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
|
||||
#include <QWaitCondition>
|
||||
@ -16,7 +15,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformOpenGLWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient
|
||||
class QAndroidPlatformOpenGLWindow : public QAndroidPlatformWindow
|
||||
{
|
||||
public:
|
||||
explicit QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display);
|
||||
@ -30,10 +29,7 @@ public:
|
||||
|
||||
void applicationStateChanged(Qt::ApplicationState) override;
|
||||
|
||||
void repaint(const QRegion ®ion) override;
|
||||
|
||||
protected:
|
||||
void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override;
|
||||
void createEgl(EGLConfig config);
|
||||
void clearEgl();
|
||||
|
||||
@ -42,9 +38,6 @@ private:
|
||||
EGLSurface m_eglSurface = EGL_NO_SURFACE;
|
||||
EGLNativeWindowType m_nativeWindow = nullptr;
|
||||
|
||||
int m_nativeSurfaceId = -1;
|
||||
QJniObject m_androidSurfaceObject;
|
||||
QWaitCondition m_surfaceWaitCondition;
|
||||
QSurfaceFormat m_format;
|
||||
QRect m_oldGeometry;
|
||||
};
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "qandroidplatformbackingstore.h"
|
||||
#include "qandroidplatformintegration.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
#include "androidjnimain.h"
|
||||
@ -131,11 +130,6 @@ QAndroidPlatformScreen::QAndroidPlatformScreen(const QJniObject &displayObject)
|
||||
|
||||
QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
||||
{
|
||||
if (m_surfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_surfaceId);
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
releaseSurface();
|
||||
}
|
||||
}
|
||||
|
||||
QWindow *QAndroidPlatformScreen::topWindow() const
|
||||
@ -159,16 +153,6 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QAndroidPlatformScreen::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::UpdateRequest) {
|
||||
doRedraw();
|
||||
m_updatePending = false;
|
||||
return true;
|
||||
}
|
||||
return QObject::event(event);
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent() && window->isRaster())
|
||||
@ -178,10 +162,6 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
||||
return;
|
||||
|
||||
m_windowStack.prepend(window);
|
||||
if (window->isRaster()) {
|
||||
m_rasterSurfaces.ref();
|
||||
setDirty(window->geometry());
|
||||
}
|
||||
|
||||
QWindow *w = topWindow();
|
||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
||||
@ -198,11 +178,6 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||
if (m_windowStack.contains(window))
|
||||
qWarning() << "Failed to remove window";
|
||||
|
||||
if (window->isRaster()) {
|
||||
m_rasterSurfaces.deref();
|
||||
setDirty(window->geometry());
|
||||
}
|
||||
|
||||
QWindow *w = topWindow();
|
||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
||||
topWindowChanged(w);
|
||||
@ -210,16 +185,11 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||
|
||||
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
int index = m_windowStack.indexOf(window);
|
||||
if (index <= 0)
|
||||
return;
|
||||
m_windowStack.move(index, 0);
|
||||
if (window->isRaster()) {
|
||||
setDirty(window->geometry());
|
||||
}
|
||||
|
||||
QWindow *w = topWindow();
|
||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
||||
topWindowChanged(w);
|
||||
@ -227,36 +197,16 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||
|
||||
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
||||
{
|
||||
if (window->parent() && window->isRaster())
|
||||
return;
|
||||
|
||||
int index = m_windowStack.indexOf(window);
|
||||
if (index == -1 || index == (m_windowStack.size() - 1))
|
||||
return;
|
||||
m_windowStack.move(index, m_windowStack.size() - 1);
|
||||
if (window->isRaster()) {
|
||||
setDirty(window->geometry());
|
||||
}
|
||||
|
||||
QWindow *w = topWindow();
|
||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
||||
topWindowChanged(w);
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::scheduleUpdate()
|
||||
{
|
||||
if (!m_updatePending) {
|
||||
m_updatePending = true;
|
||||
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::setDirty(const QRect &rect)
|
||||
{
|
||||
QRect intersection = rect.intersected(m_availableGeometry);
|
||||
m_dirtyRect |= intersection;
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
|
||||
{
|
||||
m_physicalSize = size;
|
||||
@ -306,7 +256,6 @@ void QAndroidPlatformScreen::setOrientation(Qt::ScreenOrientation orientation)
|
||||
|
||||
void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
|
||||
{
|
||||
QMutexLocker lock(&m_surfaceMutex);
|
||||
if (m_availableGeometry == rect)
|
||||
return;
|
||||
|
||||
@ -327,25 +276,12 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_surfaceId != -1) {
|
||||
releaseSurface();
|
||||
QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState state)
|
||||
{
|
||||
for (QAndroidPlatformWindow *w : std::as_const(m_windowStack))
|
||||
w->applicationStateChanged(state);
|
||||
|
||||
if (state <= Qt::ApplicationHidden) {
|
||||
lockSurface();
|
||||
QtAndroid::destroySurface(m_surfaceId);
|
||||
m_surfaceId = -1;
|
||||
releaseSurface();
|
||||
unlockSurface();
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
|
||||
@ -359,133 +295,6 @@ void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
|
||||
}
|
||||
}
|
||||
|
||||
int QAndroidPlatformScreen::rasterSurfaces()
|
||||
{
|
||||
return m_rasterSurfaces;
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::doRedraw(QImage* screenGrabImage)
|
||||
{
|
||||
PROFILE_SCOPE;
|
||||
if (!QtAndroidPrivate::activity().isValid())
|
||||
return;
|
||||
|
||||
if (m_dirtyRect.isEmpty())
|
||||
return;
|
||||
|
||||
// Stop if there are no visible raster windows. If we only have RasterGLSurface
|
||||
// windows that have renderToTexture children (i.e. they need the OpenGL path) then
|
||||
// we do not need an overlay surface.
|
||||
bool hasVisibleRasterWindows = false;
|
||||
for (QAndroidPlatformWindow *window : std::as_const(m_windowStack)) {
|
||||
if (window->window()->isVisible() && window->isRaster() && !qt_window_private(window->window())->compositing) {
|
||||
hasVisibleRasterWindows = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasVisibleRasterWindows) {
|
||||
lockSurface();
|
||||
if (m_surfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_surfaceId);
|
||||
releaseSurface();
|
||||
m_surfaceId = -1;
|
||||
}
|
||||
unlockSurface();
|
||||
return;
|
||||
}
|
||||
QMutexLocker lock(&m_surfaceMutex);
|
||||
if (m_surfaceId == -1 && m_rasterSurfaces) {
|
||||
m_surfaceId = QtAndroid::createSurface(this, geometry(), true, m_depth);
|
||||
AndroidDeadlockProtector protector;
|
||||
if (!protector.acquire())
|
||||
return;
|
||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||
}
|
||||
|
||||
if (!m_nativeSurface)
|
||||
return;
|
||||
|
||||
ANativeWindow_Buffer nativeWindowBuffer;
|
||||
ARect nativeWindowRect;
|
||||
nativeWindowRect.top = m_dirtyRect.top();
|
||||
nativeWindowRect.left = m_dirtyRect.left();
|
||||
nativeWindowRect.bottom = m_dirtyRect.bottom() + 1; // for some reason that I don't understand the QRect bottom needs to +1 to be the same with ARect bottom
|
||||
nativeWindowRect.right = m_dirtyRect.right() + 1; // same for the right
|
||||
|
||||
int ret;
|
||||
if ((ret = ANativeWindow_lock(m_nativeSurface, &nativeWindowBuffer, &nativeWindowRect)) < 0) {
|
||||
qWarning() << "ANativeWindow_lock() failed! error=" << ret;
|
||||
return;
|
||||
}
|
||||
|
||||
int bpp = 4;
|
||||
if (nativeWindowBuffer.format == WINDOW_FORMAT_RGB_565) {
|
||||
bpp = 2;
|
||||
m_pixelFormat = QImage::Format_RGB16;
|
||||
}
|
||||
|
||||
QImage screenImage(reinterpret_cast<uchar *>(nativeWindowBuffer.bits)
|
||||
, nativeWindowBuffer.width, nativeWindowBuffer.height
|
||||
, nativeWindowBuffer.stride * bpp , m_pixelFormat);
|
||||
|
||||
QPainter compositePainter(&screenImage);
|
||||
compositePainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
||||
QRegion visibleRegion(m_dirtyRect);
|
||||
for (QAndroidPlatformWindow *window : std::as_const(m_windowStack)) {
|
||||
if (!window->window()->isVisible()
|
||||
|| qt_window_private(window->window())->compositing
|
||||
|| !window->isRaster())
|
||||
continue;
|
||||
|
||||
for (const QRect &rect : std::vector<QRect>(visibleRegion.begin(), visibleRegion.end())) {
|
||||
QRect targetRect = window->geometry();
|
||||
targetRect &= rect;
|
||||
|
||||
if (targetRect.isNull())
|
||||
continue;
|
||||
|
||||
visibleRegion -= targetRect;
|
||||
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
|
||||
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformWindow *>(window)->backingStore();
|
||||
if (backingStore)
|
||||
compositePainter.drawImage(targetRect.topLeft(), backingStore->toImage(), windowRect);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QRect &rect : visibleRegion)
|
||||
compositePainter.fillRect(rect, QColor(Qt::transparent));
|
||||
|
||||
ret = ANativeWindow_unlockAndPost(m_nativeSurface);
|
||||
if (ret >= 0)
|
||||
m_dirtyRect = QRect();
|
||||
|
||||
if (screenGrabImage) {
|
||||
if (screenGrabImage->size() != screenImage.size()) {
|
||||
uchar* bytes = static_cast<uchar*>(malloc(screenImage.height() * screenImage.bytesPerLine()));
|
||||
*screenGrabImage = QImage(bytes, screenImage.width(), screenImage.height(),
|
||||
screenImage.bytesPerLine(), m_pixelFormat,
|
||||
[](void* ptr){ if (ptr) free (ptr);});
|
||||
}
|
||||
memcpy(screenGrabImage->bits(),
|
||||
screenImage.bits(),
|
||||
screenImage.bytesPerLine() * screenImage.height());
|
||||
}
|
||||
m_repaintOccurred = true;
|
||||
}
|
||||
|
||||
QPixmap QAndroidPlatformScreen::doScreenShot(QRect grabRect)
|
||||
{
|
||||
if (!m_repaintOccurred)
|
||||
return QPixmap::fromImage(m_lastScreenshot.copy(grabRect));
|
||||
QRect tmp = m_dirtyRect;
|
||||
m_dirtyRect = geometry();
|
||||
doRedraw(&m_lastScreenshot);
|
||||
m_dirtyRect = tmp;
|
||||
m_repaintOccurred = false;
|
||||
return QPixmap::fromImage(m_lastScreenshot.copy(grabRect));
|
||||
}
|
||||
|
||||
static const int androidLogicalDpi = 72;
|
||||
|
||||
QDpi QAndroidPlatformScreen::logicalDpi() const
|
||||
@ -508,67 +317,4 @@ Qt::ScreenOrientation QAndroidPlatformScreen::nativeOrientation() const
|
||||
{
|
||||
return QAndroidPlatformIntegration::m_nativeOrientation;
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w, int h)
|
||||
{
|
||||
lockSurface();
|
||||
if (surface && w > 0 && h > 0) {
|
||||
releaseSurface();
|
||||
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
|
||||
QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
|
||||
} else {
|
||||
releaseSurface();
|
||||
}
|
||||
unlockSurface();
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QAndroidPlatformScreen::releaseSurface()
|
||||
{
|
||||
if (m_nativeSurface) {
|
||||
ANativeWindow_release(m_nativeSurface);
|
||||
m_nativeSurface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is called when Qt needs to be able to grab the content of a window.
|
||||
|
||||
Returns the content of the window specified with the WId handle within the boundaries of
|
||||
QRect(x, y, width, height).
|
||||
*/
|
||||
QPixmap QAndroidPlatformScreen::grabWindow(WId window, int x, int y, int width, int height) const
|
||||
{
|
||||
QRectF screenshotRect(x, y, width, height);
|
||||
QWindow* wnd = 0;
|
||||
if (window)
|
||||
{
|
||||
const auto windowList = qApp->allWindows();
|
||||
for (QWindow *w : windowList)
|
||||
if (w->winId() == window) {
|
||||
wnd = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wnd) {
|
||||
const qreal factor = logicalDpi().first / androidLogicalDpi; //HighDPI factor;
|
||||
QRectF wndRect = wnd->geometry();
|
||||
if (wnd->parent())
|
||||
wndRect.moveTopLeft(wnd->parent()->mapToGlobal(wndRect.topLeft().toPoint()));
|
||||
if (!qFuzzyCompare(factor, 1))
|
||||
wndRect = QRectF(wndRect.left() * factor, wndRect.top() * factor,
|
||||
wndRect.width() * factor, wndRect.height() * factor);
|
||||
|
||||
if (!screenshotRect.isEmpty()) {
|
||||
screenshotRect.moveTopLeft(wndRect.topLeft() + screenshotRect.topLeft());
|
||||
screenshotRect = screenshotRect.intersected(wndRect);
|
||||
} else {
|
||||
screenshotRect = wndRect;
|
||||
}
|
||||
} else {
|
||||
screenshotRect = screenshotRect.isValid() ? screenshotRect : geometry();
|
||||
}
|
||||
return const_cast<QAndroidPlatformScreen *>(this)->doScreenShot(screenshotRect.toRect());
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -5,8 +5,6 @@
|
||||
#ifndef QANDROIDPLATFORMSCREEN_H
|
||||
#define QANDROIDPLATFORMSCREEN_H
|
||||
|
||||
#include "androidsurfaceclient.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
@ -15,14 +13,12 @@
|
||||
#include <qpa/qplatformscreen.h>
|
||||
#include <qpa/qplatformscreen_p.h>
|
||||
|
||||
#include <android/native_window.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformWindow;
|
||||
|
||||
class QAndroidPlatformScreen: public QObject,
|
||||
public QPlatformScreen, public AndroidSurfaceClient,
|
||||
public QPlatformScreen,
|
||||
public QNativeInterface::Private::QAndroidScreen
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -44,19 +40,15 @@ public:
|
||||
inline QWindow *topWindow() const;
|
||||
QWindow *topLevelAt(const QPoint & p) const override;
|
||||
|
||||
// compositor api
|
||||
void addWindow(QAndroidPlatformWindow *window);
|
||||
void removeWindow(QAndroidPlatformWindow *window);
|
||||
void raise(QAndroidPlatformWindow *window);
|
||||
void lower(QAndroidPlatformWindow *window);
|
||||
|
||||
void scheduleUpdate();
|
||||
void topWindowChanged(QWindow *w);
|
||||
int rasterSurfaces();
|
||||
int displayId() const override;
|
||||
|
||||
public slots:
|
||||
void setDirty(const QRect &rect);
|
||||
void setPhysicalSize(const QSize &size);
|
||||
void setAvailableGeometry(const QRect &rect);
|
||||
void setSize(const QSize &size);
|
||||
@ -66,12 +58,8 @@ public slots:
|
||||
void setOrientation(Qt::ScreenOrientation orientation);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
typedef QList<QAndroidPlatformWindow *> WindowStackType;
|
||||
WindowStackType m_windowStack;
|
||||
QRect m_dirtyRect;
|
||||
bool m_updatePending = false;
|
||||
|
||||
QRect m_availableGeometry;
|
||||
int m_depth;
|
||||
@ -88,25 +76,9 @@ private:
|
||||
QDpi logicalBaseDpi() const override;
|
||||
Qt::ScreenOrientation orientation() const override;
|
||||
Qt::ScreenOrientation nativeOrientation() const override;
|
||||
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
|
||||
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h) override;
|
||||
void releaseSurface();
|
||||
void applicationStateChanged(Qt::ApplicationState);
|
||||
QPixmap doScreenShot(QRect grabRect = QRect());
|
||||
|
||||
private slots:
|
||||
void doRedraw(QImage *screenGrabImage = nullptr);
|
||||
|
||||
private:
|
||||
int m_surfaceId = -1;
|
||||
QAtomicInt m_rasterSurfaces = 0;
|
||||
ANativeWindow* m_nativeSurface = nullptr;
|
||||
QWaitCondition m_surfaceWaitCondition;
|
||||
QSize m_size;
|
||||
|
||||
QImage m_lastScreenshot;
|
||||
QImage::Format m_pixelFormat = QImage::Format_RGBA8888_Premultiplied;
|
||||
bool m_repaintOccurred = false;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -18,7 +18,6 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
QAndroidPlatformVulkanWindow::QAndroidPlatformVulkanWindow(QWindow *window)
|
||||
: QAndroidPlatformWindow(window),
|
||||
m_nativeSurfaceId(-1),
|
||||
m_nativeWindow(nullptr),
|
||||
m_vkSurface(0),
|
||||
m_createVkSurface(nullptr),
|
||||
@ -29,11 +28,7 @@ QAndroidPlatformVulkanWindow::QAndroidPlatformVulkanWindow(QWindow *window)
|
||||
QAndroidPlatformVulkanWindow::~QAndroidPlatformVulkanWindow()
|
||||
{
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
lockSurface();
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
clearSurface();
|
||||
unlockSurface();
|
||||
destroyAndClearSurface();
|
||||
}
|
||||
|
||||
void QAndroidPlatformVulkanWindow::setGeometry(const QRect &rect)
|
||||
@ -44,8 +39,7 @@ void QAndroidPlatformVulkanWindow::setGeometry(const QRect &rect)
|
||||
m_oldGeometry = geometry();
|
||||
|
||||
QAndroidPlatformWindow::setGeometry(rect);
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
||||
setSurfaceGeometry(rect);
|
||||
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (rect.width() > 0
|
||||
@ -54,22 +48,13 @@ void QAndroidPlatformVulkanWindow::setGeometry(const QRect &rect)
|
||||
&& availableGeometry.height() > 0) {
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
|
||||
}
|
||||
|
||||
if (rect.topLeft() != m_oldGeometry.topLeft())
|
||||
repaint(QRegion(rect));
|
||||
}
|
||||
|
||||
void QAndroidPlatformVulkanWindow::applicationStateChanged(Qt::ApplicationState state)
|
||||
{
|
||||
QAndroidPlatformWindow::applicationStateChanged(state);
|
||||
if (state <= Qt::ApplicationHidden) {
|
||||
lockSurface();
|
||||
if (m_nativeSurfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
m_nativeSurfaceId = -1;
|
||||
}
|
||||
clearSurface();
|
||||
unlockSurface();
|
||||
destroyAndClearSurface();
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,27 +76,12 @@ void QAndroidPlatformVulkanWindow::clearSurface()
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformVulkanWindow::sendExpose()
|
||||
void QAndroidPlatformVulkanWindow::destroyAndClearSurface()
|
||||
{
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size())));
|
||||
}
|
||||
|
||||
void QAndroidPlatformVulkanWindow::surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h)
|
||||
{
|
||||
Q_UNUSED(jniEnv);
|
||||
Q_UNUSED(w);
|
||||
Q_UNUSED(h);
|
||||
|
||||
lockSurface();
|
||||
m_androidSurfaceObject = surface;
|
||||
if (surface)
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
destroySurface();
|
||||
clearSurface();
|
||||
unlockSurface();
|
||||
|
||||
if (surface)
|
||||
sendExpose();
|
||||
}
|
||||
|
||||
VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
|
||||
@ -128,8 +98,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
|
||||
AndroidDeadlockProtector protector;
|
||||
if (!protector.acquire())
|
||||
return &m_vkSurface;
|
||||
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
|
||||
createSurface();
|
||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
|
||||
#include "androidsurfaceclient.h"
|
||||
#include "qandroidplatformvulkaninstance.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
|
||||
@ -20,7 +19,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformVulkanWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient
|
||||
class QAndroidPlatformVulkanWindow : public QAndroidPlatformWindow
|
||||
{
|
||||
public:
|
||||
explicit QAndroidPlatformVulkanWindow(QWindow *window);
|
||||
@ -32,17 +31,11 @@ public:
|
||||
|
||||
VkSurfaceKHR *vkSurface();
|
||||
|
||||
protected:
|
||||
void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override;
|
||||
|
||||
private:
|
||||
void sendExpose();
|
||||
void clearSurface();
|
||||
void destroyAndClearSurface();
|
||||
|
||||
int m_nativeSurfaceId;
|
||||
ANativeWindow *m_nativeWindow;
|
||||
QJniObject m_androidSurfaceObject;
|
||||
QWaitCondition m_surfaceWaitCondition;
|
||||
QSurfaceFormat m_format;
|
||||
QRect m_oldGeometry;
|
||||
VkSurfaceKHR m_vkSurface;
|
||||
|
@ -17,10 +17,13 @@ QT_BEGIN_NAMESPACE
|
||||
Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
|
||||
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
|
||||
: QPlatformWindow(window)
|
||||
: QPlatformWindow(window), m_androidSurfaceObject(nullptr)
|
||||
{
|
||||
m_windowFlags = Qt::Widget;
|
||||
m_windowState = Qt::WindowNoState;
|
||||
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
|
||||
// the fact that it's a raster window for now
|
||||
m_isRaster = window->surfaceType() == QSurface::RasterSurface;
|
||||
m_windowId = winIdGenerator.fetchAndAddRelaxed(1) + 1;
|
||||
setWindowState(window->windowStates());
|
||||
|
||||
@ -171,4 +174,44 @@ void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::createSurface()
|
||||
{
|
||||
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::destroySurface()
|
||||
{
|
||||
if (m_nativeSurfaceId != -1) {
|
||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
||||
m_nativeSurfaceId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &rect)
|
||||
{
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::sendExpose()
|
||||
{
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (!geometry().isNull() && !availableGeometry.isNull()) {
|
||||
QWindowSystemInterface::handleExposeEvent(window(),
|
||||
QRegion(QRect(QPoint(), geometry().size())));
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
|
||||
{
|
||||
lockSurface();
|
||||
m_androidSurfaceObject = surface;
|
||||
if (m_androidSurfaceObject.isValid())
|
||||
m_surfaceWaitCondition.wakeOne();
|
||||
unlockSurface();
|
||||
if (m_androidSurfaceObject.isValid())
|
||||
sendExpose();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -7,11 +7,19 @@
|
||||
#include <qobject.h>
|
||||
#include <qrect.h>
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QtCore/qjnienvironment.h>
|
||||
#include <QtCore/qjniobject.h>
|
||||
#include <QtCore/qjnitypes.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qwaitcondition.h>
|
||||
#include <jni.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_JNI_CLASS(Surface, "android/view/Surface")
|
||||
|
||||
class QAndroidPlatformScreen;
|
||||
class QAndroidPlatformBackingStore;
|
||||
|
||||
class QAndroidPlatformWindow: public QPlatformWindow
|
||||
{
|
||||
@ -39,32 +47,33 @@ public:
|
||||
void propagateSizeHints() override;
|
||||
void requestActivateWindow() override;
|
||||
void updateSystemUiVisibility();
|
||||
inline bool isRaster() const {
|
||||
if (isForeignWindow())
|
||||
return false;
|
||||
|
||||
return window()->surfaceType() == QSurface::RasterSurface
|
||||
|| window()->surfaceType() == QSurface::RasterGLSurface;
|
||||
}
|
||||
inline bool isRaster() const { return m_isRaster; }
|
||||
bool isExposed() const override;
|
||||
|
||||
virtual void applicationStateChanged(Qt::ApplicationState);
|
||||
|
||||
void setBackingStore(QAndroidPlatformBackingStore *store) { m_backingStore = store; }
|
||||
QAndroidPlatformBackingStore *backingStore() const { return m_backingStore; }
|
||||
|
||||
virtual void repaint(const QRegion &) { }
|
||||
void onSurfaceChanged(QtJniTypes::Surface surface);
|
||||
|
||||
protected:
|
||||
void setGeometry(const QRect &rect) override;
|
||||
void lockSurface() { m_surfaceMutex.lock(); }
|
||||
void unlockSurface() { m_surfaceMutex.unlock(); }
|
||||
void createSurface();
|
||||
void destroySurface();
|
||||
void setSurfaceGeometry(const QRect &rect);
|
||||
void sendExpose();
|
||||
|
||||
protected:
|
||||
Qt::WindowFlags m_windowFlags;
|
||||
Qt::WindowStates m_windowState;
|
||||
bool m_isRaster;
|
||||
|
||||
WId m_windowId;
|
||||
|
||||
QAndroidPlatformBackingStore *m_backingStore = nullptr;
|
||||
// The Android Surface, accessed from multiple threads, guarded by m_surfaceMutex
|
||||
QtJniTypes::Surface m_androidSurfaceObject;
|
||||
QWaitCondition m_surfaceWaitCondition;
|
||||
int m_nativeSurfaceId = -1;
|
||||
QMutex m_surfaceMutex;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user