summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@qt.io>2018-01-07 01:58:08 +0100
committerLorn Potter <lorn.potter@gmail.com>2018-01-08 20:52:31 +0000
commit3be329312755532f1e4a9b4a65e52250ff88f3b7 (patch)
tree4fd5c8f1ee50dfd5c9a52e6dfa9277ed46799509
parent398072c302ee0a5989617c21b4d4f1676021ec4c (diff)
wasm: implement OpenGL context using html5.h API
The emscripten html5.h API maps more directly to the WebGL API than EGL. This gives us access to all WebGL context attributes, and also opens up for supporting multiple canvases. Change-Id: I560174b47c6f24a48625fcc6c8ed312cfcf96121 Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
-rw-r--r--src/plugins/platforms/html5/html5.pro6
-rw-r--r--src/plugins/platforms/html5/qhtml5integration.cpp8
-rw-r--r--src/plugins/platforms/html5/qhtml5openglcontext.cpp143
-rw-r--r--src/plugins/platforms/html5/qhtml5openglcontext.h63
-rw-r--r--src/plugins/platforms/html5/qhtml5screen.cpp132
-rw-r--r--src/plugins/platforms/html5/qhtml5screen.h15
6 files changed, 219 insertions, 148 deletions
diff --git a/src/plugins/platforms/html5/html5.pro b/src/plugins/platforms/html5/html5.pro
index cbac765d2f..8e69d645d3 100644
--- a/src/plugins/platforms/html5/html5.pro
+++ b/src/plugins/platforms/html5/html5.pro
@@ -19,7 +19,8 @@ SOURCES = main.cpp \
qhtml5eventtranslator.cpp \
qhtml5eventdispatcher.cpp \
qhtml5compositor.cpp \
- qhtml5cursor.cpp
+ qhtml5cursor.cpp \
+ qhtml5openglcontext.cpp
HEADERS = qhtml5integration.h \
qhtml5window.h \
@@ -29,7 +30,8 @@ HEADERS = qhtml5integration.h \
qhtml5eventdispatcher.h \
qhtml5compositor.h \
qhtml5stylepixmaps_p.h \
- qhtml5cursor.h
+ qhtml5cursor.h \
+ qhtml5openglcontext.h
RESOURCES += fonts/html5fonts.qrc
diff --git a/src/plugins/platforms/html5/qhtml5integration.cpp b/src/plugins/platforms/html5/qhtml5integration.cpp
index cc501cd833..598b3baf5d 100644
--- a/src/plugins/platforms/html5/qhtml5integration.cpp
+++ b/src/plugins/platforms/html5/qhtml5integration.cpp
@@ -31,6 +31,7 @@
#include "qhtml5eventtranslator.h"
#include "qhtml5eventdispatcher.h"
#include "qhtml5compositor.h"
+#include "qhtml5openglcontext.h"
#include "qhtml5window.h"
#ifndef QT_NO_OPENGL
@@ -94,7 +95,7 @@ void emscriptenOutput(QtMsgType type, const QMessageLogContext &context, const Q
QHTML5Integration::QHTML5Integration()
: mFontDb(0),
mCompositor(new QHtml5Compositor),
- mScreen(new QHTML5Screen(EGL_DEFAULT_DISPLAY, mCompositor)),
+ mScreen(new QHTML5Screen(mCompositor)),
m_eventDispatcher(0)
{
qSetMessagePattern(QString("(%{function}:%{line}) - %{message}"));
@@ -102,8 +103,8 @@ QHTML5Integration::QHTML5Integration()
globalHtml5Integration = this;
- screenAdded(mScreen);
updateQScreenAndCanvasRenderSize();
+ screenAdded(mScreen);
emscripten_set_resize_callback(0, (void *)this, 1, uiEvent_cb);
m_eventTranslator = new QHTML5EventTranslator();
@@ -170,10 +171,11 @@ QPlatformBackingStore *QHTML5Integration::createPlatformBackingStore(QWindow *wi
return nullptr;
#endif
}
+
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QHTML5Integration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- return static_cast<QHTML5Screen *>(context->screen()->handle())->platformContext();
+ return new QHTML5OpenGLContext(context->format());
}
#endif
diff --git a/src/plugins/platforms/html5/qhtml5openglcontext.cpp b/src/plugins/platforms/html5/qhtml5openglcontext.cpp
new file mode 100644
index 0000000000..d560e7cea9
--- /dev/null
+++ b/src/plugins/platforms/html5/qhtml5openglcontext.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QHTML5OpenGLContext.h"
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+QHTML5OpenGLContext::QHTML5OpenGLContext(const QSurfaceFormat &format)
+ :m_requestedFormat(format)
+{
+ m_requestedFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+}
+
+QHTML5OpenGLContext::~QHTML5OpenGLContext()
+{
+ if (m_context)
+ emscripten_webgl_destroy_context(m_context);
+}
+
+void QHTML5OpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface)
+{
+ // Native emscripten contexts are tied to a single surface. Recreate
+ // the context if the surface is changed.
+ if (surface != m_surface) {
+ m_surface = surface;
+
+ // Destroy existing context
+ if (m_context)
+ emscripten_webgl_destroy_context(m_context);
+
+ // Create new context
+ const char *canvasId = 0; // (use default canvas) FIXME: get the actual canvas from the surface.
+ m_context = createEmscriptenContext(canvasId, m_requestedFormat);
+
+ // Register context-lost callback.
+ auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL
+ {
+ Q_UNUSED(eventType);
+ Q_UNUSED(reserved);
+ // The application may get contex-lost if e.g. moved to the background. Set
+ // m_contextLost which will make isValid() return false. Application code will
+ // then detect this and recrate the the context, resulting in a new QHTML5OpenGLContext
+ // instance.
+ reinterpret_cast<QHTML5OpenGLContext *>(userData)->m_contextLost = true;
+ return true;
+ };
+ bool capture = true;
+ emscripten_set_webglcontextlost_callback(canvasId, this, capture, callback);
+ }
+}
+
+EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QHTML5OpenGLContext::createEmscriptenContext(const char *canvasId, QSurfaceFormat format)
+{
+ EmscriptenWebGLContextAttributes attributes;
+ emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes
+
+ attributes.preferLowPowerToHighPerformance = false;
+ attributes.failIfMajorPerformanceCaveat = false;
+ attributes.antialias = true;
+ attributes.enableExtensionsByDefault = true;
+
+ // WebGL offers enable/disable control but not size control for these
+ attributes.alpha = format.alphaBufferSize() > 0;
+ attributes.depth = format.depthBufferSize() > 0;
+ attributes.stencil = format.stencilBufferSize() > 0;
+
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId, &attributes);
+
+ return context;
+}
+
+QSurfaceFormat QHTML5OpenGLContext::format() const
+{
+ return m_requestedFormat;
+}
+
+GLuint QHTML5OpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
+{
+ return QPlatformOpenGLContext::defaultFramebufferObject(surface);
+}
+
+bool QHTML5OpenGLContext::makeCurrent(QPlatformSurface *surface)
+{
+ maybeRecreateEmscriptenContext(surface);
+
+ return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
+}
+
+void QHTML5OpenGLContext::swapBuffers(QPlatformSurface *surface)
+{
+ Q_UNUSED(surface);
+ // No swapbuffers on WebGl
+}
+
+void QHTML5OpenGLContext::doneCurrent()
+{
+ // No doneCurrent on WebGl
+}
+
+bool QHTML5OpenGLContext::isSharing() const
+{
+ return false;
+}
+
+bool QHTML5OpenGLContext::isValid() const
+{
+ return (m_contextLost == false);
+}
+
+QFunctionPointer QHTML5OpenGLContext::getProcAddress(const char *procName)
+{
+ return reinterpret_cast<QFunctionPointer>(eglGetProcAddress(procName));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/html5/qhtml5openglcontext.h b/src/plugins/platforms/html5/qhtml5openglcontext.h
new file mode 100644
index 0000000000..d3793413ed
--- /dev/null
+++ b/src/plugins/platforms/html5/qhtml5openglcontext.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) 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.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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformopenglcontext.h>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHTML5OpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ QHTML5OpenGLContext(const QSurfaceFormat &format);
+ ~QHTML5OpenGLContext();
+
+ QSurfaceFormat format() const override;
+ void swapBuffers(QPlatformSurface *surface) override;
+ GLuint defaultFramebufferObject(QPlatformSurface *surface) const override;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+ bool isSharing() const override;
+ bool isValid() const override;
+ QFunctionPointer getProcAddress(const char *procName) override;
+
+private:
+ void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
+ static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const char *canvasId, QSurfaceFormat format);
+
+ bool m_contextLost = false;
+ QSurfaceFormat m_requestedFormat;
+ QPlatformSurface *m_surface = nullptr;
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
+};
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/html5/qhtml5screen.cpp b/src/plugins/platforms/html5/qhtml5screen.cpp
index 086246c452..260c363724 100644
--- a/src/plugins/platforms/html5/qhtml5screen.cpp
+++ b/src/plugins/platforms/html5/qhtml5screen.cpp
@@ -48,136 +48,21 @@
QT_BEGIN_NAMESPACE
-// #define QEGL_EXTRA_DEBUG
-
-#ifndef QT_NO_OPENGL
-
-class QHtml5Context : public QEGLPlatformContext
-{
-public:
- QHtml5Context(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
- : QEGLPlatformContext(format, share, display, 0, QVariant(), QEGLPlatformContext::NoSurfaceless)
- {
- }
-
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override
- {
- QHtml5Window *window = static_cast<QHtml5Window *>(surface);
- QHTML5Screen *screen = static_cast<QHTML5Screen *>(window->screen());
- return screen->surface();
- }
-};
-
-#endif
-
-QHTML5Screen::QHTML5Screen(EGLNativeDisplayType display, QHtml5Compositor *compositor)
+QHTML5Screen::QHTML5Screen(QHtml5Compositor *compositor)
: mCompositor(compositor)
, m_depth(32)
- , m_format(QImage::Format_Invalid)
- , m_platformContext(0)
- , m_context(0)
- , m_surface(0)
+ , m_format(QImage::Format_RGB32)
{
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglScreen %p\n", this);
-#endif
-
- EGLint major, minor;
-
- if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API))) {
- qWarning("Could not bind GL_ES API\n");
- qFatal("EGL error");
- }
-
- m_dpy = eglGetDisplay(display);
- if (Q_UNLIKELY(m_dpy == EGL_NO_DISPLAY)) {
- qWarning("Could not open egl display\n");
- qFatal("EGL error");
- }
- qWarning("Opened display %p\n", m_dpy);
-
- if (Q_UNLIKELY(!eglInitialize(m_dpy, &major, &minor))) {
- qWarning("Could not initialize egl display\n");
- qFatal("EGL error");
- }
-
- qWarning("Initialized display %d %d\n", major, minor);
-
mCompositor->setScreen(this);
}
QHTML5Screen::~QHTML5Screen()
{
- if (m_surface)
- eglDestroySurface(m_dpy, m_surface);
- eglTerminate(m_dpy);
-}
-
-void QHTML5Screen::createAndSetPlatformContext() const {
- const_cast<QHTML5Screen *>(this)->createAndSetPlatformContext();
-}
-
-void QHTML5Screen::createAndSetPlatformContext()
-{
- QSurfaceFormat platformFormat;
-
- QByteArray depthString = qgetenv("QT_QPA_EGLFS_DEPTH");
- if (depthString.toInt() == 16) {
- platformFormat.setDepthBufferSize(16);
- platformFormat.setRedBufferSize(5);
- platformFormat.setGreenBufferSize(6);
- platformFormat.setBlueBufferSize(5);
- m_depth = 16;
- m_format = QImage::Format_RGB16;
- } else {
- platformFormat.setDepthBufferSize(24);
- platformFormat.setStencilBufferSize(8);
- platformFormat.setRedBufferSize(8);
- platformFormat.setGreenBufferSize(8);
- platformFormat.setBlueBufferSize(8);
- m_depth = 32;
- m_format = QImage::Format_RGB32;
- }
-
- if (!qEnvironmentVariableIsEmpty("QT_QPA_EGLFS_MULTISAMPLE"))
- platformFormat.setSamples(4);
-
- EGLConfig config = q_configFromGLFormat(m_dpy, platformFormat);
-
- EGLNativeWindowType eglWindow = 0;
-
-#ifdef QEGL_EXTRA_DEBUG
- q_printEglConfig(m_dpy, config);
-#endif
-
- m_surface = eglCreateWindowSurface(m_dpy, config, eglWindow, NULL);
- if (Q_UNLIKELY(m_surface == EGL_NO_SURFACE)) {
- qWarning("Could not create the egl surface: error = 0x%x\n", eglGetError());
- eglTerminate(m_dpy);
- qFatal("EGL error");
- }
-
- QEGLPlatformContext *platformContext = new QHtml5Context(platformFormat, 0, m_dpy);
- m_platformContext = platformContext;
-
- EGLint w,h; // screen size detection
- eglQuerySurface(m_dpy, m_surface, EGL_WIDTH, &w);
- eglQuerySurface(m_dpy, m_surface, EGL_HEIGHT, &h);
-
- m_geometry = QRect(0,0,w,h);
-
- //m_context.reset(new QOpenGLContext);
- //m_context->setFormat(platformFormat);
- //m_context->setScreen(screen);
- //m_context->create();
}
QRect QHTML5Screen::geometry() const
{
- if (m_geometry.isNull()) {
- createAndSetPlatformContext();
- }
return m_geometry;
}
@@ -188,8 +73,6 @@ int QHTML5Screen::depth() const
QImage::Format QHTML5Screen::format() const
{
- if (m_format == QImage::Format_Invalid)
- createAndSetPlatformContext();
return m_format;
}
@@ -198,17 +81,6 @@ QPlatformCursor *QHTML5Screen::cursor() const
return const_cast<QHtml5Cursor *>(&m_cursor);
}
-#ifndef QT_NO_OPENGL
-QPlatformOpenGLContext *QHTML5Screen::platformContext() const
-{
- if (!m_platformContext) {
- QHTML5Screen *that = const_cast<QHTML5Screen *>(this);
- that->createAndSetPlatformContext();
- }
- return m_platformContext;
-}
-#endif
-
void QHTML5Screen::resizeMaximizedWindows()
{
QList<QWindow*> windows = QGuiApplication::allWindows();
diff --git a/src/plugins/platforms/html5/qhtml5screen.h b/src/plugins/platforms/html5/qhtml5screen.h
index 292f771c61..444f7797c3 100644
--- a/src/plugins/platforms/html5/qhtml5screen.h
+++ b/src/plugins/platforms/html5/qhtml5screen.h
@@ -37,8 +37,6 @@
#include <QScopedPointer>
#include <QtCore/QTextStream>
-#include <QtEglSupport/private/qt_egl_p.h>
-
QT_BEGIN_NAMESPACE
class QPlatformOpenGLContext;
@@ -52,15 +50,13 @@ class QHTML5Screen : public QObject, public QPlatformScreen
Q_OBJECT
public:
- QHTML5Screen(EGLNativeDisplayType display, QHtml5Compositor *compositor);
+ QHTML5Screen(QHtml5Compositor *compositor);
~QHTML5Screen();
QRect geometry() const override;
int depth() const override;
QImage::Format format() const override;
QPlatformCursor *cursor() const override;
- QPlatformOpenGLContext *platformContext() const;
- EGLSurface surface() const { return m_surface; }
void resizeMaximizedWindows();
QWindow *topWindow() const;
@@ -85,22 +81,15 @@ protected:
//QRegion mRepaintRegion;
private:
- void createAndSetPlatformContext() const;
- void createAndSetPlatformContext();
bool mUpdatePending;
private:
QHtml5Compositor *mCompositor;
- QRect m_geometry;
+ QRect m_geometry = QRect(0, 0, 100, 100);
int m_depth;
QImage::Format m_format;
- QPlatformOpenGLContext *m_platformContext;
- QScopedPointer<QOpenGLContext> m_context;
QHtml5Cursor m_cursor;
-
- EGLDisplay m_dpy;
- EGLSurface m_surface;
};
//Q_DECLARE_OPERATORS_FOR_FLAGS(QHTML5Screen::Flags)