9#include <emscripten/bind.h>
10#include <emscripten/val.h>
18 function(
"qtDoNothing", &qtDoNothing);
23QWasmOpenGLContext::QWasmOpenGLContext(QOpenGLContext *context)
24 : m_actualFormat(context->format()), m_qGlContext(context)
26 m_actualFormat.setRenderableType(QSurfaceFormat::OpenGLES);
29 if (m_actualFormat.depthBufferSize() < 0 && m_actualFormat.stencilBufferSize() > 0)
30 m_actualFormat.setDepthBufferSize(16);
32 if (m_actualFormat.stencilBufferSize() < 0 && m_actualFormat.depthBufferSize() > 0)
33 m_actualFormat.setStencilBufferSize(8);
41 destroyWebGLContext(m_ownedWebGLContext.handle);
50 return ((format.majorVersion() == 2 && format.minorVersion() == 0) ||
51 (format.majorVersion() == 3 && format.minorVersion() == 0));
54EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
57 if (m_ownedWebGLContext.surface == surface)
58 return m_ownedWebGLContext.handle;
60 if (surface->surface()->surfaceClass() == QSurface::Offscreen) {
64 if (m_ownedWebGLContext.handle)
65 return m_ownedWebGLContext.handle;
70 QOpenGLContextData{ .surface = surface,
71 .handle = createEmscriptenContext(
72 static_cast<QWasmOffscreenSurface *>(surface)->id(),
75 destroyWebGLContext(m_ownedWebGLContext.handle);
78 m_ownedWebGLContext = QOpenGLContextData{
80 .handle = createEmscriptenContext(
static_cast<QWasmWindow *>(surface)->canvasSelector(),
85 EmscriptenWebGLContextAttributes actualAttributes;
87 EMSCRIPTEN_RESULT attributesResult = emscripten_webgl_get_context_attributes(m_ownedWebGLContext.handle, &actualAttributes);
88 if (attributesResult == EMSCRIPTEN_RESULT_SUCCESS) {
89 if (actualAttributes.majorVersion == 1) {
90 m_actualFormat.setMajorVersion(2);
91 }
else if (actualAttributes.majorVersion == 2) {
92 m_actualFormat.setMajorVersion(3);
94 m_actualFormat.setMinorVersion(0);
97 return m_ownedWebGLContext.handle;
100void QWasmOpenGLContext::destroyWebGLContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE contextHandle)
104 emscripten::val jsEvents = emscripten::val::module_property(
"JSEvents");
105 emscripten::val savedRemoveAllHandlersOnTargetFunction = jsEvents[
"removeAllHandlersOnTarget"];
106 jsEvents.set(
"removeAllHandlersOnTarget", emscripten::val::module_property(
"qtDoNothing"));
107 emscripten_webgl_destroy_context(contextHandle);
108 jsEvents.set(
"removeAllHandlersOnTarget", savedRemoveAllHandlersOnTargetFunction);
111EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
113 QSurfaceFormat format)
115 EmscriptenWebGLContextAttributes attributes;
116 emscripten_webgl_init_context_attributes(&attributes);
118 attributes.powerPreference = EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE;
119 attributes.failIfMajorPerformanceCaveat =
false;
120 attributes.antialias =
true;
121 attributes.enableExtensionsByDefault =
true;
122 attributes.majorVersion = 2;
123 attributes.minorVersion = 0;
126 const bool useDepthStencil = (format.depthBufferSize() > 0 || format.stencilBufferSize() > 0);
129 attributes.alpha = format.alphaBufferSize() > 0;
130 attributes.depth = useDepthStencil;
131 attributes.stencil = useDepthStencil;
132 EMSCRIPTEN_RESULT contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
134 if (contextResult <= 0) {
137 attributes.majorVersion = 1;
138 contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
140 return contextResult;
145 return m_actualFormat;
150 return QPlatformOpenGLContext::defaultFramebufferObject(surface);
155 static bool sentSharingWarning =
false;
157 qWarning() <<
"The functionality for sharing OpenGL contexts is limited, see documentation";
158 sentSharingWarning =
true;
161 if (
auto *shareContext = m_qGlContext->shareContext())
162 return shareContext->makeCurrent(surface->surface());
164 const auto context = obtainEmscriptenContext(surface);
168 m_usedWebGLContextHandle = context;
170 return emscripten_webgl_make_context_current(context) == EMSCRIPTEN_RESULT_SUCCESS;
186 return m_qGlContext->shareContext();
191 if (!isOpenGLVersionSupported(m_actualFormat))
196 return !m_usedWebGLContextHandle || !emscripten_is_webgl_context_lost(m_usedWebGLContextHandle);
201 return reinterpret_cast<QFunctionPointer>(eglGetProcAddress(procName));
bool isSharing() const override
bool isValid() const override
void doneCurrent() override
void swapBuffers(QPlatformSurface *surface) override
Reimplement in subclass to native swap buffers calls.
bool makeCurrent(QPlatformSurface *surface) override
QSurfaceFormat format() const override
QFunctionPointer getProcAddress(const char *procName) override
Reimplement in subclass to allow dynamic querying of OpenGL symbols.
GLuint defaultFramebufferObject(QPlatformSurface *surface) const override
Reimplement in subclass if your platform uses framebuffer objects for surfaces.
EMSCRIPTEN_BINDINGS(qwasmopenglcontext)