Add QOffScreenSurface platform API abstraction

This follows the work done in 6ff79478a44fce12ca18832a56db4a370a9ff417.

The API is available by including qoffscreensurface.h, scoped in
the QPlatformInterface namespace. The namespace
exposes platform specific type-safe interfaces that provide:

 a) Factory functions for adopting native contexts, e.g.

    QAndroidPlatformOffscreenSurface::fromNative(ANativeWindow);

 b) Access to underlying native handles, e.g.

    surface->platformInterface<QAndroidPlatformOffscreenSurface>()
                ->nativeSurface()

Fixes: QTBUG-85874
Change-Id: I29c459866e0355a52320d5d473e8b147e050acb3
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Assam Boudjelthia 2020-08-25 11:32:58 +03:00
parent 15db957585
commit fc4a73aa54
15 changed files with 319 additions and 111 deletions

View File

@ -100,7 +100,7 @@ qt_add_module(Gui
kernel/qinputmethod.cpp kernel/qinputmethod.h kernel/qinputmethod_p.h
kernel/qinternalmimedata.cpp kernel/qinternalmimedata_p.h
kernel/qkeymapper.cpp kernel/qkeymapper_p.h
kernel/qoffscreensurface.cpp kernel/qoffscreensurface.h
kernel/qoffscreensurface.cpp kernel/qoffscreensurface.h kernel/qoffscreensurface_p.h kernel/qoffscreensurface_platform.h
kernel/qpaintdevicewindow.cpp kernel/qpaintdevicewindow.h kernel/qpaintdevicewindow_p.h
kernel/qpalette.cpp kernel/qpalette.h
kernel/qpixelformat.cpp kernel/qpixelformat.h
@ -352,6 +352,11 @@ qt_extend_target(Gui CONDITION QT_FEATURE_opengl
rhi/qrhigles2_p_p.h
)
qt_extend_target(Gui CONDITION ANDROID
SOURCES
platform/android/qandroidplatforminterface.cpp
)
#### Keys ignored in scope 2:.:.:gui.pro:QT_FEATURE_opengl:
# MODULE_CONFIG = "opengl"

View File

@ -6,6 +6,8 @@ PRECOMPILED_HEADER = kernel/qt_gui_pch.h
KERNEL_P= kernel
HEADERS += \
kernel/qoffscreensurface_p.h \
kernel/qoffscreensurface_platform.h \
kernel/qtguiglobal.h \
kernel/qtguiglobal_p.h \
kernel/qgenericpluginfactory.h \

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@ -42,7 +42,7 @@
#include "qguiapplication_p.h"
#include "qscreen.h"
#include "qplatformintegration.h"
#include "qplatformoffscreensurface.h"
#include "qoffscreensurface_p.h"
#include "qwindow.h"
#include "qplatformwindow.h"
@ -50,6 +50,18 @@
QT_BEGIN_NAMESPACE
/*!
\fn T QOffScreenSurface::platformInterface<T>()
Returns a platform interface of type T for the surface.
This function provides access to platform specific functionality
of QOffScreenSurface, as defined in the QPlatformInterface namespace.
If the requested interface is not available a \nullptr is returned.
*/
/*!
\class QOffscreenSurface
\inmodule QtGui
@ -91,36 +103,6 @@ QT_BEGIN_NAMESPACE
native surface. For the use cases of QOffscreenSurface (rendering to FBOs, texture
upload) this is not a problem.
*/
class Q_GUI_EXPORT QOffscreenSurfacePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QOffscreenSurface)
public:
QOffscreenSurfacePrivate()
: QObjectPrivate()
, surfaceType(QSurface::OpenGLSurface)
, platformOffscreenSurface(nullptr)
, offscreenWindow(nullptr)
, requestedFormat(QSurfaceFormat::defaultFormat())
, screen(nullptr)
, size(1, 1)
, nativeHandle(nullptr)
{
}
~QOffscreenSurfacePrivate()
{
}
QSurface::SurfaceType surfaceType;
QPlatformOffscreenSurface *platformOffscreenSurface;
QWindow *offscreenWindow;
QSurfaceFormat requestedFormat;
QScreen *screen;
QSize size;
void *nativeHandle;
};
/*!
\since 5.10
@ -228,8 +210,6 @@ void QOffscreenSurface::destroy()
delete d->offscreenWindow;
d->offscreenWindow = nullptr;
}
d->nativeHandle = nullptr;
}
/*!
@ -343,26 +323,6 @@ void QOffscreenSurface::setScreen(QScreen *newScreen)
}
}
/*!
Sets the native handle to which the offscreen surface is connected to \a handle.
The native handle will be resolved in the create() function. Calling
this function after create() will not re-create a native surface.
\note The interpretation of the native handle is platform specific. Only
some platforms will support adopting native handles of offscreen surfaces
and platforms that do not implement this support will ignore the handle.
\since 5.9
\sa nativeHandle()
*/
void QOffscreenSurface::setNativeHandle(void *handle)
{
Q_D(QOffscreenSurface);
d->nativeHandle = handle;
}
/*!
Called when the offscreen surface's screen is destroyed.
@ -394,19 +354,6 @@ QPlatformOffscreenSurface *QOffscreenSurface::handle() const
return d->platformOffscreenSurface;
}
/*!
Returns an optional native handle to which the offscreen surface is connected.
\since 5.9
\sa setNativeHandle()
*/
void *QOffscreenSurface::nativeHandle() const
{
Q_D(const QOffscreenSurface);
return d->nativeHandle;
}
/*!
Returns the platform surface corresponding to the offscreen surface.

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@ -79,8 +79,8 @@ public:
QPlatformOffscreenSurface *handle() const;
void *nativeHandle() const;
void setNativeHandle(void *handle);
template <typename T>
T *platformInterface() const;
Q_SIGNALS:
void screenChanged(QScreen *screen);
@ -97,4 +97,6 @@ private:
QT_END_NAMESPACE
#include <QtGui/qoffscreensurface_platform.h>
#endif // QOFFSCREENSURFACE_H

View File

@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENSURFACE_P_H
#define QOFFSCREENSURFACE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qplatformoffscreensurface.h"
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOffscreenSurfacePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QOffscreenSurface)
public:
QOffscreenSurfacePrivate()
: QObjectPrivate()
, surfaceType(QSurface::OpenGLSurface)
, platformOffscreenSurface(nullptr)
, offscreenWindow(nullptr)
, requestedFormat(QSurfaceFormat::defaultFormat())
, screen(nullptr)
, size(1, 1)
{
}
~QOffscreenSurfacePrivate()
{
}
static QOffscreenSurfacePrivate *get(QOffscreenSurface *surface)
{
return surface ? surface->d_func() : nullptr;
}
QSurface::SurfaceType surfaceType;
QPlatformOffscreenSurface *platformOffscreenSurface;
QWindow *offscreenWindow;
QSurfaceFormat requestedFormat;
QScreen *screen;
QSize size;
};
QT_END_NAMESPACE
#endif // QOFFSCREENSURFACE_P_H

View File

@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOFFSCREENSURFACE_PLATFORM_H
#define QOFFSCREENSURFACE_PLATFORM_H
#include <QtGui/qtguiglobal.h>
#include <QtGui/qoffscreensurface.h>
#if defined(Q_OS_ANDROID)
QT_FORWARD_DECLARE_CLASS(ANativeWindow);
#endif
QT_BEGIN_NAMESPACE
namespace QPlatformInterface {
#if defined(Q_OS_ANDROID)
struct Q_GUI_EXPORT QAndroidPlatformOffscreenSurface
{
QT_DECLARE_PLATFORM_INTERFACE(QAndroidPlatformOffscreenSurface)
static QOffscreenSurface *fromNative(ANativeWindow *nativeSurface);
virtual ANativeWindow *nativeSurface() const = 0;
};
#endif
} // QPlatformInterface
QT_END_NAMESPACE
#endif // QOFFSCREENSURFACE_PLATFORM_H

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@ -49,8 +49,9 @@
// source and binary incompatible with future versions of Qt.
//
#include <QtGui/qtguiglobal.h>
#include "qplatformsurface.h"
#include <QtGui/qoffscreensurface.h>
#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
@ -75,10 +76,30 @@ public:
protected:
QScopedPointer<QPlatformOffscreenSurfacePrivate> d_ptr;
friend class QOffscreenSurfacePrivate;
private:
Q_DISABLE_COPY(QPlatformOffscreenSurface)
};
template <typename T>
T *QOffscreenSurface::platformInterface() const
{
return dynamic_cast<T*>(surfaceHandle());
}
namespace QPlatformInterface::Private {
#if defined(Q_OS_ANDROID)
struct Q_GUI_EXPORT QAndroidOffScreenIntegration
{
QT_DECLARE_PLATFORM_INTERFACE(QAndroidOffScreenIntegration)
virtual QOffscreenSurface *createOffscreenSurface(ANativeWindow *nativeSurface) const = 0;
};
#endif
} // QPlatformInterface::Private
QT_END_NAMESPACE
#endif // QPLATFORMOFFSCREENSURFACE_H

View File

@ -0,0 +1 @@
SOURCES += $$PWD/qandroidplatforminterface.cpp

View File

@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qpa/qplatformoffscreensurface.h>
#include <qpa/qplatformintegration.h>
#include <QtGui/qoffscreensurface_platform.h>
#include <QtGui/private/qguiapplication_p.h>
QT_BEGIN_NAMESPACE
using namespace QPlatformInterface::Private;
#if defined(Q_OS_ANDROID)
QT_DEFINE_PLATFORM_INTERFACE(QAndroidPlatformOffscreenSurface, QOffscreenSurface);
QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(QAndroidOffScreenIntegration);
QOffscreenSurface *QPlatformInterface::QAndroidPlatformOffscreenSurface::fromNative(ANativeWindow *nativeSurface)
{
return QGuiApplicationPrivate::platformIntegration()->call<
&QAndroidOffScreenIntegration::createOffscreenSurface>(nativeSurface);
}
#endif
QT_END_NAMESPACE

View File

@ -3,3 +3,4 @@ darwin:include(darwin/darwin.pri)
win32:include(windows/windows.pri)
unix:include(unix/unix.pri)
macos:include(macos/macos.pri)
android:include(android/android.pri)

View File

@ -44,6 +44,7 @@
#include <QGuiApplication>
#include <QOpenGLContext>
#include <QOffscreenSurface>
#include <QtGui/private/qoffscreensurface_p.h>
#include <QThread>
#include <QtGui/private/qeglpbuffer_p.h>
@ -68,6 +69,8 @@
#include "qandroidsystemlocale.h"
#include "qandroidplatformoffscreensurface.h"
#include <jni.h>
#if QT_CONFIG(vulkan)
#include "qandroidplatformvulkanwindow.h"
#include "qandroidplatformvulkaninstance.h"
@ -322,16 +325,20 @@ QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenS
format.setGreenBufferSize(8);
format.setBlueBufferSize(8);
if (surface->nativeHandle()) {
// Adopt existing offscreen Surface
// The expectation is that nativeHandle is an ANativeWindow* representing
// an android.view.Surface
return new QAndroidPlatformOffscreenSurface(m_eglDisplay, format, surface);
}
return new QEGLPbuffer(m_eglDisplay, format, surface);
}
QOffscreenSurface *QAndroidPlatformIntegration::createOffscreenSurface(ANativeWindow *nativeSurface) const
{
if (!QtAndroid::activity() || !nativeSurface)
return nullptr;
auto *surface = new QOffscreenSurface;
auto *surfacePrivate = QOffscreenSurfacePrivate::get(surface);
surfacePrivate->platformOffscreenSurface = new QAndroidPlatformOffscreenSurface(nativeSurface, m_eglDisplay, surface);
return surface;
}
QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *window) const
{
if (!QtAndroid::activity())

View File

@ -40,19 +40,17 @@
#ifndef QANDROIDPLATFORMINTERATION_H
#define QANDROIDPLATFORMINTERATION_H
#include <QtGui/qtguiglobal.h>
#include "qandroidinputcontext.h"
#include "qandroidplatformscreen.h"
#include <QtGui/qtguiglobal.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformmenu.h>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformoffscreensurface.h>
#include <EGL/egl.h>
#include <jni.h>
#include "qandroidinputcontext.h"
#include "qandroidplatformscreen.h"
#include <memory>
QT_BEGIN_NAMESPACE
@ -75,6 +73,7 @@ protected:
class QAndroidPlatformIntegration : public QPlatformIntegration
, QPlatformInterface::Private::QEGLIntegration
, QPlatformInterface::Private::QAndroidOffScreenIntegration
{
friend class QAndroidPlatformScreen;
@ -94,6 +93,7 @@ public:
QAbstractEventDispatcher *createEventDispatcher() const override;
QAndroidPlatformScreen *screen() { return m_primaryScreen; }
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
QOffscreenSurface *createOffscreenSurface(ANativeWindow *nativeSurface) const override;
void setAvailableGeometry(const QRect &availableGeometry);
void setPhysicalSize(int width, int height);

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@ -39,28 +39,23 @@
#include "qandroidplatformoffscreensurface.h"
#include <QtGui/QOffscreenSurface>
#include <QtGui/private/qeglconvenience_p.h>
#include <android/native_window.h>
QT_BEGIN_NAMESPACE
QAndroidPlatformOffscreenSurface::QAndroidPlatformOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface)
, m_format(format)
, m_display(display)
, m_surface(EGL_NO_SURFACE)
QAndroidPlatformOffscreenSurface::QAndroidPlatformOffscreenSurface(
ANativeWindow *nativeSurface, EGLDisplay display, QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface), m_display(display), m_surface(EGL_NO_SURFACE)
{
// Get native handle
ANativeWindow *surfaceTexture = (ANativeWindow*)offscreenSurface->nativeHandle();
// FIXME: Read surface format properties from native surface using ANativeWindow_getFormat
m_format.setAlphaBufferSize(8);
m_format.setRedBufferSize(8);
m_format.setGreenBufferSize(8);
m_format.setBlueBufferSize(8);
EGLConfig config = q_configFromGLFormat(m_display, m_format, false);
if (config) {
const EGLint attributes[] = {
EGL_NONE
};
m_surface = eglCreateWindowSurface(m_display, config, surfaceTexture, attributes);
if (EGLConfig config = q_configFromGLFormat(m_display, m_format, false)) {
const EGLint attributes[] = { EGL_NONE };
m_surface = eglCreateWindowSurface(m_display, config, nativeSurface, attributes);
}
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@ -41,21 +41,26 @@
#define QANDROIDPLATFORMOFFSCREENSURFACETEXTURE_H
#include <qpa/qplatformoffscreensurface.h>
#include <QtGui/private/qeglplatformcontext_p.h>
#include <QtGui/qoffscreensurface_platform.h>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
class QOffscreenSurface;
class QAndroidPlatformOffscreenSurface : public QPlatformOffscreenSurface
class QAndroidPlatformOffscreenSurface : public QPlatformOffscreenSurface,
public QPlatformInterface::QAndroidPlatformOffscreenSurface
{
public:
QAndroidPlatformOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format,
QOffscreenSurface *offscreenSurface);
QAndroidPlatformOffscreenSurface(ANativeWindow *nativeSurface, EGLDisplay display, QOffscreenSurface *offscreenSurface);
~QAndroidPlatformOffscreenSurface();
QSurfaceFormat format() const override { return m_format; }
bool isValid() const override { return m_surface != EGL_NO_SURFACE; }
EGLSurface surface() const { return m_surface; }
ANativeWindow *nativeSurface() const override { return (ANativeWindow *)surface(); };
private:
QSurfaceFormat m_format;
EGLDisplay m_display;

View File

@ -76,9 +76,8 @@ EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatform
if (surface->surface()->surfaceClass() == QSurface::Window) {
return static_cast<QAndroidPlatformOpenGLWindow *>(surface)->eglSurface(eglConfig());
} else {
auto platformOffscreenSurface = static_cast<QPlatformOffscreenSurface*>(surface);
if (platformOffscreenSurface->offscreenSurface()->nativeHandle())
return static_cast<QAndroidPlatformOffscreenSurface *>(surface)->surface();
if (auto *platformOffscreenSurface = dynamic_cast<QAndroidPlatformOffscreenSurface *>(surface))
return platformOffscreenSurface->surface();
else
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}