9#include <emscripten/bind.h>
10#include <emscripten/val.h>
18 function(
"qtDoNothing", &qtDoNothing);
23QHash<QPlatformSurface *, EMSCRIPTEN_WEBGL_CONTEXT_HANDLE> QWasmOpenGLContext::s_contexts;
28 m_actualFormat.setRenderableType(QSurfaceFormat::OpenGLES);
31 if (m_actualFormat.depthBufferSize() < 0 && m_actualFormat.stencilBufferSize() > 0)
32 m_actualFormat.setDepthBufferSize(16);
34 if (m_actualFormat.stencilBufferSize() < 0 && m_actualFormat.depthBufferSize() > 0)
35 m_actualFormat.setStencilBufferSize(8);
49 return ((format.majorVersion() == 2 && format.minorVersion() == 0) ||
50 (format.majorVersion() == 3 && format.minorVersion() == 0));
55 if (surface ==
nullptr)
57 int context = s_contexts.take(surface);
62void QWasmOpenGLContext::destroyWebGLContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE contextHandle)
70 emscripten::val jsEvents = emscripten::val::module_property(
"JSEvents");
71 emscripten::val savedRemoveAllHandlersOnTargetFunction = jsEvents[
"removeAllHandlersOnTarget"];
72 jsEvents.set(
"removeAllHandlersOnTarget", emscripten::val::module_property(
"qtDoNothing"));
73 emscripten_webgl_destroy_context(contextHandle);
74 jsEvents.set(
"removeAllHandlersOnTarget", savedRemoveAllHandlersOnTargetFunction);
77EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
QWasmOpenGLContext::createEmscriptenContext(
const std::string &canvasSelector,
78 QSurfaceFormat format)
80 EmscriptenWebGLContextAttributes attributes;
81 emscripten_webgl_init_context_attributes(&attributes);
83 attributes.powerPreference = EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE;
84 attributes.failIfMajorPerformanceCaveat =
false;
85 attributes.antialias =
true;
86 attributes.enableExtensionsByDefault =
true;
87 attributes.majorVersion = 2;
88 attributes.minorVersion = 0;
91 const bool useDepthStencil = (format.depthBufferSize() > 0 || format.stencilBufferSize() > 0);
94 attributes.alpha = format.alphaBufferSize() > 0;
95 attributes.depth = useDepthStencil;
96 attributes.stencil = useDepthStencil;
97 EMSCRIPTEN_RESULT contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
99 if (contextResult <= 0) {
102 attributes.majorVersion = 1;
103 contextResult = emscripten_webgl_create_context(canvasSelector.c_str(), &attributes);
106 if (contextResult <= 0) {
107 qWarning() <<
"WebGL context creation failed";
108 return contextResult;
112 EmscriptenWebGLContextAttributes actualAttributes;
113 EMSCRIPTEN_RESULT attributesResult = emscripten_webgl_get_context_attributes(contextResult, &actualAttributes);
114 if (attributesResult == EMSCRIPTEN_RESULT_SUCCESS) {
115 if (actualAttributes.majorVersion == 1) {
116 m_actualFormat.setMajorVersion(2);
117 }
else if (actualAttributes.majorVersion == 2) {
118 m_actualFormat.setMajorVersion(3);
120 m_actualFormat.setMinorVersion(0);
123 return contextResult;
128 return m_actualFormat;
133 return QPlatformOpenGLContext::defaultFramebufferObject(surface);
140 m_madeCurrentSurface = surface;
144 if (m_contextOwningSurface && m_contextOwningSurface != surface)
148 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
149 if (m_contextOwningSurface && s_contexts.contains(m_contextOwningSurface)) {
150 context = s_contexts.value(surface);
152 m_contextOwningSurface = surface;
153 bool isOffscreen = surface->surface()->surfaceClass() == QSurface::Offscreen;
154 auto canvasId = isOffscreen ?
static_cast<QWasmOffscreenSurface *>(surface)->id() :
155 static_cast<QWasmWindow *>(surface)->canvasSelector();
157 context = createEmscriptenContext(canvasId, m_actualFormat);
158 s_contexts.insert(surface, context);
164 return emscripten_webgl_make_context_current(context) == EMSCRIPTEN_RESULT_SUCCESS;
175 m_madeCurrentSurface =
nullptr;
188 if (!isOpenGLVersionSupported(m_actualFormat))
193 if (!m_madeCurrentSurface && !m_contextOwningSurface)
198 if (m_madeCurrentSurface != m_contextOwningSurface)
202 if (!s_contexts.contains(m_contextOwningSurface))
205 return !emscripten_is_webgl_context_lost(s_contexts.value(m_contextOwningSurface));
210 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)