Support QOpenGLWidget and QQuickWidget on Android
It gets somewhat complicated due to the fact that a RasterGLSurface window (i.e. any widget window since 5.3) may behave either like an OpenGLSurface or a RasterSurface, and the expected behavior may change on each backingstore sync. This does not fit designs where the platform window implementation is separated and there is different behavior for raster and GL windows. Therefore QAndroidPlatformOpenGLWindow is now made capable of behaving like the raster one, based on a flag communicated from the widget stack via QWindowPrivate (since the plugin knows nothing about widgets). This means that widget windows that do not have renderToTexture children (QOpenGLWidget, QQuickWidget) will go through the raster path, while the ones that have will behave like an OpenGL window with the actual rendering happening in QPlatformBackingStore::composeAndFlush(). The surface type is RasterGLSurface in both cases nonetheless. Task-number: QTBUG-37907 Change-Id: I6f9261fc0fd993afcda7f30d379c5410069033d3 Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
parent
8688656641
commit
a4f50269f8
@ -100,6 +100,7 @@ public:
|
||||
, cursor(Qt::ArrowCursor)
|
||||
, hasCursor(false)
|
||||
#endif
|
||||
, compositing(false)
|
||||
{
|
||||
isWindow = true;
|
||||
}
|
||||
@ -175,6 +176,8 @@ public:
|
||||
QCursor cursor;
|
||||
bool hasCursor;
|
||||
#endif
|
||||
|
||||
bool compositing;
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,7 +47,6 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
|
||||
$$PWD/qandroidplatformscreen.cpp \
|
||||
$$PWD/qandroidplatformwindow.cpp \
|
||||
$$PWD/qandroidplatformopenglwindow.cpp \
|
||||
$$PWD/qandroidplatformrasterwindow.cpp \
|
||||
$$PWD/qandroidplatformbackingstore.cpp \
|
||||
$$PWD/qandroidplatformopenglcontext.cpp \
|
||||
$$PWD/qandroidplatformforeignwindow.cpp \
|
||||
@ -76,7 +75,6 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
|
||||
$$PWD/qandroidplatformscreen.h \
|
||||
$$PWD/qandroidplatformwindow.h \
|
||||
$$PWD/qandroidplatformopenglwindow.h \
|
||||
$$PWD/qandroidplatformrasterwindow.h \
|
||||
$$PWD/qandroidplatformbackingstore.h \
|
||||
$$PWD/qandroidplatformopenglcontext.h \
|
||||
$$PWD/qandroidplatformforeignwindow.h \
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
#include "qandroidplatformbackingstore.h"
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "qandroidplatformrasterwindow.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
#include <qpa/qplatformscreen.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -66,7 +66,7 @@ void QAndroidPlatformBackingStore::flush(QWindow *window, const QRegion ®ion,
|
||||
if (!m_backingStoreSet)
|
||||
setBackingStore(window);
|
||||
|
||||
(static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->repaint(region);
|
||||
(static_cast<QAndroidPlatformWindow *>(window->handle()))->repaint(region);
|
||||
}
|
||||
|
||||
void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
@ -79,11 +79,11 @@ void QAndroidPlatformBackingStore::resize(const QSize &size, const QRegion &stat
|
||||
|
||||
void QAndroidPlatformBackingStore::setBackingStore(QWindow *window)
|
||||
{
|
||||
if (window->surfaceType() == QSurface::RasterSurface) {
|
||||
(static_cast<QAndroidPlatformRasterWindow *>(window->handle()))->setBackingStore(this);
|
||||
if (window->surfaceType() == QSurface::RasterSurface || window->surfaceType() == QSurface::RasterGLSurface) {
|
||||
(static_cast<QAndroidPlatformWindow *>(window->handle()))->setBackingStore(this);
|
||||
m_backingStoreSet = true;
|
||||
} else {
|
||||
qWarning("QAndroidPlatformBackingStore does not support GL windows.");
|
||||
qWarning("QAndroidPlatformBackingStore does not support OpenGL-only windows.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,6 @@
|
||||
#include "qandroidplatformfontdatabase.h"
|
||||
#include "qandroidplatformopenglcontext.h"
|
||||
#include "qandroidplatformopenglwindow.h"
|
||||
#include "qandroidplatformrasterwindow.h"
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "qandroidplatformservices.h"
|
||||
#include "qandroidplatformtheme.h"
|
||||
@ -192,6 +191,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
case RasterGLSurface: return true;
|
||||
default:
|
||||
return QPlatformIntegration::hasCapability(cap);
|
||||
}
|
||||
@ -227,8 +227,6 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind
|
||||
{
|
||||
if (window->type() == Qt::ForeignWindow)
|
||||
return new QAndroidPlatformForeignWindow(window);
|
||||
else if (window->surfaceType() == QSurface::RasterSurface)
|
||||
return new QAndroidPlatformRasterWindow(window);
|
||||
else
|
||||
return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay);
|
||||
}
|
||||
|
@ -42,9 +42,11 @@
|
||||
|
||||
#include "qandroidplatformopenglwindow.h"
|
||||
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "androidjnimain.h"
|
||||
|
||||
#include <QSurfaceFormat>
|
||||
#include <QtGui/private/qwindow_p.h>
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qpa/qplatformscreen.h>
|
||||
@ -69,25 +71,52 @@ QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
|
||||
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())
|
||||
return;
|
||||
|
||||
QRect oldGeometry = geometry();
|
||||
m_oldGeometry = geometry();
|
||||
|
||||
QAndroidPlatformWindow::setGeometry(rect);
|
||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
||||
if (m_nativeSurfaceId != -1)
|
||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
||||
|
||||
QRect availableGeometry = screen()->availableGeometry();
|
||||
if (oldGeometry.width() == 0
|
||||
&& oldGeometry.height() == 0
|
||||
if (m_oldGeometry.width() == 0
|
||||
&& m_oldGeometry.height() == 0
|
||||
&& rect.width() > 0
|
||||
&& rect.height() > 0
|
||||
&& availableGeometry.width() > 0
|
||||
&& 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)
|
||||
@ -162,8 +191,8 @@ QSurfaceFormat QAndroidPlatformOpenGLWindow::format() const
|
||||
|
||||
void QAndroidPlatformOpenGLWindow::clearEgl()
|
||||
{
|
||||
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (m_eglSurface != EGL_NO_SURFACE) {
|
||||
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
||||
m_eglSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
|
||||
void applicationStateChanged(Qt::ApplicationState);
|
||||
|
||||
void repaint(const QRegion ®ion) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
|
||||
void createEgl(EGLConfig config);
|
||||
@ -80,6 +82,7 @@ private:
|
||||
QJNIObjectPrivate m_androidSurfaceObject;
|
||||
QWaitCondition m_surfaceWaitCondition;
|
||||
QSurfaceFormat m_format;
|
||||
QRect m_oldGeometry;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -1,83 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qandroidplatformrasterwindow.h"
|
||||
|
||||
#include "qandroidplatformscreen.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QAndroidPlatformRasterWindow::QAndroidPlatformRasterWindow(QWindow *window)
|
||||
:QAndroidPlatformWindow(window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QAndroidPlatformRasterWindow::repaint(const QRegion ®ion)
|
||||
{
|
||||
if (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 QAndroidPlatformRasterWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
m_oldGeometry = geometry();
|
||||
QAndroidPlatformWindow::setGeometry(rect);
|
||||
if (rect.topLeft() != m_oldGeometry.topLeft())
|
||||
repaint(QRegion(rect));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -1,70 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QANDROIDPLATFORMRASTERWINDOW_H
|
||||
#define QANDROIDPLATFORMRASTERWINDOW_H
|
||||
|
||||
#include "qandroidplatformwindow.h"
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformBackingStore;
|
||||
class QAndroidPlatformRasterWindow : public QObject, public QAndroidPlatformWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QAndroidPlatformRasterWindow(QWindow *window);
|
||||
|
||||
void setBackingStore(QAndroidPlatformBackingStore *store) { m_backingStore = store; }
|
||||
QAndroidPlatformBackingStore *backingStore() const { return m_backingStore; }
|
||||
void repaint(const QRegion®ion);
|
||||
|
||||
public slots:
|
||||
void setGeometry(const QRect &rect);
|
||||
|
||||
private:
|
||||
QAndroidPlatformBackingStore *m_backingStore = nullptr;
|
||||
QRect m_oldGeometry;
|
||||
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
#endif // QANDROIDPLATFORMRASTERWINDOW_H
|
@ -48,9 +48,9 @@
|
||||
#include "qandroidplatformscreen.h"
|
||||
#include "qandroidplatformbackingstore.h"
|
||||
#include "qandroidplatformintegration.h"
|
||||
#include "qandroidplatformwindow.h"
|
||||
#include "androidjnimain.h"
|
||||
#include "androidjnimenu.h"
|
||||
#include "qandroidplatformrasterwindow.h"
|
||||
|
||||
#include <android/bitmap.h>
|
||||
#include <android/native_window_jni.h>
|
||||
@ -58,6 +58,7 @@
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/private/qwindow_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -291,6 +292,19 @@ void QAndroidPlatformScreen::doRedraw()
|
||||
if (m_dirtyRect.isEmpty())
|
||||
return;
|
||||
|
||||
// Stop if there no visible raster windows. This is important because if we only have
|
||||
// RasterGLSurface windows that have renderToTexture children (i.e. they need the
|
||||
// OpenGL path) then we must bail out right now.
|
||||
bool hasVisibleRasterWindows = false;
|
||||
foreach (QAndroidPlatformWindow *window, m_windowStack) {
|
||||
if (window->window()->isVisible() && window->isRaster() && !qt_window_private(window->window())->compositing) {
|
||||
hasVisibleRasterWindows = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasVisibleRasterWindows)
|
||||
return;
|
||||
|
||||
QMutexLocker lock(&m_surfaceMutex);
|
||||
if (m_id == -1 && m_rasterSurfaces) {
|
||||
m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth);
|
||||
@ -343,7 +357,7 @@ void QAndroidPlatformScreen::doRedraw()
|
||||
|
||||
visibleRegion -= targetRect;
|
||||
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
|
||||
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformRasterWindow *>(window)->backingStore();
|
||||
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformWindow *>(window)->backingStore();
|
||||
if (backingStore)
|
||||
compositePainter.drawImage(targetRect.topLeft(), backingStore->toImage(), windowRect);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidPlatformScreen;
|
||||
class QAndroidPlatformBackingStore;
|
||||
|
||||
class QAndroidPlatformWindow: public QPlatformWindow
|
||||
{
|
||||
@ -71,10 +72,19 @@ public:
|
||||
void propagateSizeHints();
|
||||
void requestActivateWindow();
|
||||
void updateStatusBarVisibility();
|
||||
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
|
||||
inline bool isRaster() const {
|
||||
return window()->surfaceType() == QSurface::RasterSurface
|
||||
|| window()->surfaceType() == QSurface::RasterGLSurface;
|
||||
}
|
||||
bool isExposed() const;
|
||||
|
||||
virtual void applicationStateChanged(Qt::ApplicationState);
|
||||
|
||||
void setBackingStore(QAndroidPlatformBackingStore *store) { m_backingStore = store; }
|
||||
QAndroidPlatformBackingStore *backingStore() const { return m_backingStore; }
|
||||
|
||||
virtual void repaint(const QRegion &) { }
|
||||
|
||||
protected:
|
||||
void setGeometry(const QRect &rect);
|
||||
|
||||
@ -83,6 +93,8 @@ protected:
|
||||
Qt::WindowState m_windowState;
|
||||
|
||||
WId m_windowId;
|
||||
|
||||
QAndroidPlatformBackingStore *m_backingStore = nullptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include <private/qapplication_p.h>
|
||||
#include <private/qpaintengine_raster_p.h>
|
||||
#include <private/qgraphicseffect_p.h>
|
||||
#include <QtGui/private/qwindow_p.h>
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
@ -1132,6 +1133,7 @@ void QWidgetBackingStore::doSync()
|
||||
widgetTextures = new QPlatformTextureList;
|
||||
findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
|
||||
}
|
||||
qt_window_private(tlw->windowHandle())->compositing = widgetTextures && !widgetTextures->isEmpty();
|
||||
fullUpdatePending = false;
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user