10#include <emscripten/bind.h>
11#include <emscripten/val.h>
19 function(
"qtDoNothing", &qtDoNothing);
24QHash<QPlatformSurface *, EMSCRIPTEN_WEBGL_CONTEXT_HANDLE> QWasmOpenGLContext::s_contexts;
29 m_actualFormat.setRenderableType(QSurfaceFormat::OpenGLES);
32 if (m_actualFormat.depthBufferSize() < 0 && m_actualFormat.stencilBufferSize() > 0)
33 m_actualFormat.setDepthBufferSize(16);
35 if (m_actualFormat.stencilBufferSize() < 0 && m_actualFormat.depthBufferSize() > 0)
36 m_actualFormat.setStencilBufferSize(8);
50 return ((format.majorVersion() == 2 && format.minorVersion() == 0) ||
51 (format.majorVersion() == 3 && format.minorVersion() == 0));
56 if (surface ==
nullptr)
58 int context = s_contexts.take(surface);
63void QWasmOpenGLContext::destroyWebGLContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE contextHandle)
71 emscripten::val jsEvents = emscripten::val::module_property(
"JSEvents");
72 emscripten::val savedRemoveAllHandlersOnTargetFunction = jsEvents[
"removeAllHandlersOnTarget"];
73 jsEvents.set(
"removeAllHandlersOnTarget", emscripten::val::module_property(
"qtDoNothing"));
74 emscripten_webgl_destroy_context(contextHandle);
75 jsEvents.set(
"removeAllHandlersOnTarget", savedRemoveAllHandlersOnTargetFunction);
78EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
QWasmOpenGLContext::createEmscriptenContext(
const std::string &canvasSelector,
79 QSurfaceFormat format)
81 EmscriptenWebGLContextAttributes attributes;
82 emscripten_webgl_init_context_attributes(&attributes);
84 attributes.powerPreference = EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE;
85 attributes.failIfMajorPerformanceCaveat =
false;
86 attributes.antialias =
true;
87 attributes.enableExtensionsByDefault =
true;
88 attributes.majorVersion = 2;
89 attributes.minorVersion = 0;
92 const bool useDepthStencil = (format.depthBufferSize() > 0 || format.stencilBufferSize() > 0);
95 attributes.alpha = format.alphaBufferSize() > 0;
96 attributes.depth = useDepthStencil;
97 attributes.stencil = useDepthStencil;
98 EMSCRIPTEN_RESULT contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
100 if (contextResult <= 0) {
103 attributes.majorVersion = 1;
104 contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
107 if (contextResult <= 0) {
108 qWarning() <<
"WebGL context creation failed";
109 return contextResult;
113 EmscriptenWebGLContextAttributes actualAttributes;
114 EMSCRIPTEN_RESULT attributesResult = emscripten_webgl_get_context_attributes(contextResult, &actualAttributes);
115 if (attributesResult == EMSCRIPTEN_RESULT_SUCCESS) {
116 if (actualAttributes.majorVersion == 1) {
117 m_actualFormat.setMajorVersion(2);
118 }
else if (actualAttributes.majorVersion == 2) {
119 m_actualFormat.setMajorVersion(3);
121 m_actualFormat.setMinorVersion(0);
124 return contextResult;
129 return m_actualFormat;
134 return QPlatformOpenGLContext::defaultFramebufferObject(surface);
141 m_madeCurrentSurface = surface;
145 if (m_contextOwningSurface && m_contextOwningSurface != surface)
149 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
150 if (m_contextOwningSurface && s_contexts.contains(m_contextOwningSurface)) {
151 context = s_contexts.value(surface);
153 m_contextOwningSurface = surface;
154 bool isOffscreen = surface->surface()->surfaceClass() == QSurface::Offscreen;
155 auto canvasId = isOffscreen ?
static_cast<QWasmOffscreenSurface *>(surface)->id() :
156 static_cast<QWasmWindow *>(surface)->canvasSelector();
158 context = createEmscriptenContext(canvasId, m_actualFormat);
159 s_contexts.insert(surface, context);
165 return emscripten_webgl_make_context_current(context) == EMSCRIPTEN_RESULT_SUCCESS;
176 m_madeCurrentSurface =
nullptr;
189 if (!isOpenGLVersionSupported(m_actualFormat))
194 if (!m_madeCurrentSurface && !m_contextOwningSurface)
199 if (m_madeCurrentSurface != m_contextOwningSurface)
203 if (!s_contexts.contains(m_contextOwningSurface))
206 return !emscripten_is_webgl_context_lost(s_contexts.value(m_contextOwningSurface));
211 return reinterpret_cast<QFunctionPointer>(eglGetProcAddress(procName));
static void destroyWebGLContext(QPlatformSurface *surface)
bool isSharing() const override
bool isValid() const override
void doneCurrent() override
QWasmOpenGLContext(QOpenGLContext *context)
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)