Android: Enable Adoption of ANativeWindow handle as a QOffscreenSurface

This is done by adding an API to QOffscreenSurface to enable setting a
native handle which can represent a native offscreen surface.  When
using the TexureView it is necessary to render to SurfaceTexture objects
which are exposed as offscreen window surfaces.  After wraping a
SurfaceTexture in a android.view.Surface object and passing it to C++
via the JNI, it is possible to get the needed ANativeWindow* handle
required to pass to eglCreateWindowSurface. So by setting this native
handle Qt can then render to this "native" offscreen surface.

Change-Id: If7fc5ac7ac588fe6c3a6fb883ea7e439d095470f
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
This commit is contained in:
Andy Nichols 2016-12-06 22:36:30 +01:00 committed by Andy Nichols
parent b750a3786f
commit 9d8db91ada
7 changed files with 203 additions and 5 deletions

View File

@ -102,6 +102,7 @@ public:
, requestedFormat(QSurfaceFormat::defaultFormat())
, screen(0)
, size(1, 1)
, nativeHandle(nullptr)
{
}
@ -115,6 +116,7 @@ public:
QSurfaceFormat requestedFormat;
QScreen *screen;
QSize size;
void *nativeHandle;
};
@ -217,6 +219,8 @@ void QOffscreenSurface::destroy()
delete d->offscreenWindow;
d->offscreenWindow = 0;
}
d->nativeHandle = nullptr;
}
/*!
@ -330,6 +334,26 @@ void QOffscreenSurface::setScreen(QScreen *newScreen)
}
}
/*!
Sets the native handle to which the offscreen surface is connected.
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.
@ -361,6 +385,19 @@ 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

@ -79,6 +79,9 @@ public:
QPlatformOffscreenSurface *handle() const;
void *nativeHandle() const;
void setNativeHandle(void *handle);
Q_SIGNALS:
void screenChanged(QScreen *screen);

View File

@ -43,7 +43,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformbackingstore.cpp \
$$PWD/qandroidplatformopenglcontext.cpp \
$$PWD/qandroidplatformforeignwindow.cpp \
$$PWD/qandroideventdispatcher.cpp
$$PWD/qandroideventdispatcher.cpp \
$$PWD/qandroidplatformoffscreensurface.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androiddeadlockprotector.h \
@ -71,7 +72,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformbackingstore.h \
$$PWD/qandroidplatformopenglcontext.h \
$$PWD/qandroidplatformforeignwindow.h \
$$PWD/qandroideventdispatcher.h
$$PWD/qandroideventdispatcher.h \
$$PWD/qandroidplatformoffscreensurface.h
qtConfig(android-style-assets): SOURCES += $$PWD/extract.cpp
else: SOURCES += $$PWD/extract-dummy.cpp

View File

@ -65,6 +65,7 @@
#include "qandroidplatformservices.h"
#include "qandroidplatformtheme.h"
#include "qandroidsystemlocale.h"
#include "qandroidplatformoffscreensurface.h"
#include <QtPlatformHeaders/QEGLNativeContext>
@ -262,12 +263,20 @@ QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenS
{
if (!QtAndroid::activity())
return nullptr;
QSurfaceFormat format(surface->requestedFormat());
format.setAlphaBufferSize(8);
format.setRedBufferSize(8);
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);
}

View File

@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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 "qandroidplatformoffscreensurface.h"
#include <QtGui/QOffscreenSurface>
#include <QtEglSupport/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)
{
// Get native handle
ANativeWindow *surfaceTexture = (ANativeWindow*)offscreenSurface->nativeHandle();
EGLConfig config = q_configFromGLFormat(m_display, m_format, false);
if (config) {
const EGLint attributes[] = {
EGL_NONE
};
m_surface = eglCreateWindowSurface(m_display, config, surfaceTexture, attributes);
}
}
QAndroidPlatformOffscreenSurface::~QAndroidPlatformOffscreenSurface()
{
eglDestroySurface(m_display, m_surface);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 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 QANDROIDPLATFORMOFFSCREENSURFACETEXTURE_H
#define QANDROIDPLATFORMOFFSCREENSURFACETEXTURE_H
#include <qpa/qplatformoffscreensurface.h>
#include <QtEglSupport/private/qeglplatformcontext_p.h>
QT_BEGIN_NAMESPACE
class QOffscreenSurface;
class QAndroidPlatformOffscreenSurface : public QPlatformOffscreenSurface
{
public:
QAndroidPlatformOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format,
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; }
private:
QSurfaceFormat m_format;
EGLDisplay m_display;
EGLSurface m_surface;
};
QT_END_NAMESPACE
#endif // QANDROIDPLATFORMOFFSCREENSURFACETEXTURE_H

View File

@ -41,11 +41,13 @@
#include "qandroidplatformopenglcontext.h"
#include "qandroidplatformopenglwindow.h"
#include "qandroidplatformintegration.h"
#include "qandroidplatformoffscreensurface.h"
#include <QtEglSupport/private/qeglpbuffer_p.h>
#include <QSurface>
#include <QtGui/private/qopenglcontext_p.h>
#include <QtGui/QOffscreenSurface>
QT_BEGIN_NAMESPACE
@ -110,10 +112,15 @@ bool QAndroidPlatformOpenGLContext::makeCurrent(QPlatformSurface *surface)
EGLSurface QAndroidPlatformOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
{
if (surface->surface()->surfaceClass() == QSurface::Window)
if (surface->surface()->surfaceClass() == QSurface::Window) {
return static_cast<QAndroidPlatformOpenGLWindow *>(surface)->eglSurface(eglConfig());
else
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
} else {
auto platformOffscreenSurface = static_cast<QPlatformOffscreenSurface*>(surface);
if (platformOffscreenSurface->offscreenSurface()->nativeHandle())
return static_cast<QAndroidPlatformOffscreenSurface *>(surface)->surface();
else
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
}
QT_END_NAMESPACE