summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.cpp19
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.h10
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp55
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.h6
5 files changed, 64 insertions, 28 deletions
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index b92e4566686..9f139ad4464 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -184,7 +184,7 @@ void QWasmIntegration::removeBackingStore(QWindow* window)
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- return new QWasmOpenGLContext(context->format());
+ return new QWasmOpenGLContext(context);
}
#endif
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
index 31adc73cf5f..0191e0b2165 100644
--- a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
@@ -6,10 +6,25 @@
QT_BEGIN_NAMESPACE
QWasmOffscreenSurface::QWasmOffscreenSurface(QOffscreenSurface *offscreenSurface)
- :QPlatformOffscreenSurface(offscreenSurface)
+ : QPlatformOffscreenSurface(offscreenSurface), m_offscreenCanvas(emscripten::val::undefined())
{
+ const auto offscreenCanvasClass = emscripten::val::global("OffscreenCanvas");
+ // The OffscreenCanvas is not supported on some browsers, most notably on Safari.
+ if (!offscreenCanvasClass)
+ return;
+
+ m_offscreenCanvas = offscreenCanvasClass.new_(offscreenSurface->size().width(),
+ offscreenSurface->size().height());
+
+ m_specialTargetId = std::string("!qtoffscreen_") + std::to_string(uintptr_t(this));
+
+ emscripten::val::module_property("specialHTMLTargets")
+ .set(m_specialTargetId, m_offscreenCanvas);
}
-QWasmOffscreenSurface::~QWasmOffscreenSurface() = default;
+QWasmOffscreenSurface::~QWasmOffscreenSurface()
+{
+ emscripten::val::module_property("specialHTMLTargets").delete_(m_specialTargetId);
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.h b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
index 88a64b775a5..38a991f4cee 100644
--- a/src/plugins/platforms/wasm/qwasmoffscreensurface.h
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
@@ -6,6 +6,10 @@
#include <qpa/qplatformoffscreensurface.h>
+#include <emscripten/val.h>
+
+#include <string>
+
QT_BEGIN_NAMESPACE
class QOffscreenSurface;
@@ -14,8 +18,12 @@ class QWasmOffscreenSurface final : public QPlatformOffscreenSurface
public:
explicit QWasmOffscreenSurface(QOffscreenSurface *offscreenSurface);
~QWasmOffscreenSurface() final;
-private:
+ const std::string &id() const { return m_specialTargetId; }
+
+private:
+ std::string m_specialTargetId;
+ emscripten::val m_offscreenCanvas;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
index 3dfb201367a..80e842f83dc 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qwasmopenglcontext.h"
+
+#include "qwasmoffscreensurface.h"
#include "qwasmintegration.h"
#include <EGL/egl.h>
#include <emscripten/bind.h>
@@ -18,23 +20,22 @@ EMSCRIPTEN_BINDINGS(qwasmopenglcontext)
QT_BEGIN_NAMESPACE
-QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format)
- : m_requestedFormat(format)
+QWasmOpenGLContext::QWasmOpenGLContext(QOpenGLContext *context)
+ : m_requestedFormat(context->format()), m_qGlContext(context)
{
m_requestedFormat.setRenderableType(QSurfaceFormat::OpenGLES);
// if we set one, we need to set the other as well since in webgl, these are tied together
- if (format.depthBufferSize() < 0 && format.stencilBufferSize() > 0)
- m_requestedFormat.setDepthBufferSize(16);
-
- if (format.stencilBufferSize() < 0 && format.depthBufferSize() > 0)
- m_requestedFormat.setStencilBufferSize(8);
+ if (m_requestedFormat.depthBufferSize() < 0 && m_requestedFormat.stencilBufferSize() > 0)
+ m_requestedFormat.setDepthBufferSize(16);
+ if (m_requestedFormat.stencilBufferSize() < 0 && m_requestedFormat.depthBufferSize() > 0)
+ m_requestedFormat.setStencilBufferSize(8);
}
QWasmOpenGLContext::~QWasmOpenGLContext()
{
- if (!m_context)
+ if (!m_webGLContext)
return;
// Destroy GL context. Work around bug in emscripten_webgl_destroy_context
@@ -44,9 +45,9 @@ QWasmOpenGLContext::~QWasmOpenGLContext()
emscripten::val savedRemoveAllHandlersOnTargetFunction =
jsEvents["removeAllHandlersOnTarget"];
jsEvents.set("removeAllHandlersOnTarget", emscripten::val::module_property("qtDoNothing"));
- emscripten_webgl_destroy_context(m_context);
+ emscripten_webgl_destroy_context(m_webGLContext);
jsEvents.set("removeAllHandlersOnTarget", savedRemoveAllHandlersOnTargetFunction);
- m_context = 0;
+ m_webGLContext = 0;
}
bool QWasmOpenGLContext::isOpenGLVersionSupported(QSurfaceFormat format)
@@ -61,18 +62,28 @@ bool QWasmOpenGLContext::isOpenGLVersionSupported(QSurfaceFormat format)
bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface)
{
- if (m_context && m_surface == surface)
+ if (m_webGLContext && m_surface == surface)
return true;
- // TODO(mikolajboc): Use OffscreenCanvas if available.
- if (surface->surface()->surfaceClass() == QSurface::Offscreen)
- return false;
-
m_surface = surface;
-
- auto *window = static_cast<QWasmWindow *>(surface);
- m_context = createEmscriptenContext(window->canvasSelector(), m_requestedFormat);
- return true;
+ if (surface->surface()->surfaceClass() == QSurface::Offscreen) {
+ if (const auto *shareContext = m_qGlContext->shareContext()) {
+ // Since there are no resource sharing capabilities with WebGL whatsoever, we use the
+ // same actual underlaying WebGL context. This is not perfect, but it works in most
+ // cases.
+ m_webGLContext =
+ static_cast<QWasmOpenGLContext *>(shareContext->handle())->m_webGLContext;
+ } else {
+ // The non-shared offscreen context is heavily limited on WASM, but we provide it anyway
+ // for potential pixel readbacks.
+ m_webGLContext = createEmscriptenContext(
+ static_cast<QWasmOffscreenSurface *>(surface)->id(), m_requestedFormat);
+ }
+ } else {
+ m_webGLContext = createEmscriptenContext(
+ static_cast<QWasmWindow *>(surface)->canvasSelector(), m_requestedFormat);
+ }
+ return m_webGLContext > 0;
}
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
@@ -116,7 +127,7 @@ bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface)
if (!maybeCreateEmscriptenContext(surface))
return false;
- return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
+ return emscripten_webgl_make_context_current(m_webGLContext) == EMSCRIPTEN_RESULT_SUCCESS;
}
void QWasmOpenGLContext::swapBuffers(QPlatformSurface *surface)
@@ -132,7 +143,7 @@ void QWasmOpenGLContext::doneCurrent()
bool QWasmOpenGLContext::isSharing() const
{
- return false;
+ return m_qGlContext->shareContext();
}
bool QWasmOpenGLContext::isValid() const
@@ -142,7 +153,7 @@ bool QWasmOpenGLContext::isValid() const
// Note: we get isValid() calls before we see the surface and can
// create a native context, so no context is also a valid state.
- return !m_context || !emscripten_is_webgl_context_lost(m_context);
+ return !m_webGLContext || !emscripten_is_webgl_context_lost(m_webGLContext);
}
QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName)
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h
index ac456d90e4f..d51caf08b12 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.h
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h
@@ -8,11 +8,12 @@
QT_BEGIN_NAMESPACE
+class QOpenGLContext;
class QPlatformScreen;
class QWasmOpenGLContext : public QPlatformOpenGLContext
{
public:
- QWasmOpenGLContext(const QSurfaceFormat &format);
+ explicit QWasmOpenGLContext(QOpenGLContext *context);
~QWasmOpenGLContext();
QSurfaceFormat format() const override;
@@ -32,7 +33,8 @@ private:
QSurfaceFormat m_requestedFormat;
QPlatformSurface *m_surface = nullptr;
- EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
+ QOpenGLContext *m_qGlContext;
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_webGLContext = 0;
};
QT_END_NAMESPACE