Mercurial > hg > pub > prymula > com
view DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_gl.c @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
line wrap: on
line source
// Copyright 2012-2022 David Robillard <d@drobilla.net> // Copyright 2021-2022 Filipe Coelho <falktx@falktx.com> // SPDX-License-Identifier: ISC #include "../pugl-upstream/src/stub.h" #include "wasm.h" #include "pugl/pugl.h" #include <stdio.h> #include <stdlib.h> #include <EGL/egl.h> // for performance reasons we can keep a single EGL context always active #define PUGL_WASM_SINGLE_EGL_CONTEXT typedef struct { EGLDisplay display; EGLConfig config; EGLContext context; EGLSurface surface; } PuglWasmGlSurface; static EGLint puglWasmGlHintValue(const int value) { return value == PUGL_DONT_CARE ? EGL_DONT_CARE : value; } static int puglWasmGlGetAttrib(const EGLDisplay display, const EGLConfig config, const EGLint attrib) { EGLint value = 0; eglGetConfigAttrib(display, config, attrib, &value); return value; } static PuglStatus puglWasmGlConfigure(PuglView* view) { PuglInternals* const impl = view->impl; const EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (display == EGL_NO_DISPLAY) { return PUGL_CREATE_CONTEXT_FAILED; } int major, minor; if (eglInitialize(display, &major, &minor) != EGL_TRUE) { return PUGL_CREATE_CONTEXT_FAILED; } EGLConfig config; int numConfigs; if (eglGetConfigs(display, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { eglTerminate(display); return PUGL_CREATE_CONTEXT_FAILED; } // clang-format off const EGLint attrs[] = { /* GLX_X_RENDERABLE, True, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, EGL_SAMPLE_BUFFERS, view->hints[PUGL_MULTI_SAMPLE] ? 1 : 0, */ EGL_SAMPLES, puglWasmGlHintValue(view->hints[PUGL_SAMPLES]), EGL_RED_SIZE, puglWasmGlHintValue(view->hints[PUGL_RED_BITS]), EGL_GREEN_SIZE, puglWasmGlHintValue(view->hints[PUGL_GREEN_BITS]), EGL_BLUE_SIZE, puglWasmGlHintValue(view->hints[PUGL_BLUE_BITS]), EGL_ALPHA_SIZE, puglWasmGlHintValue(view->hints[PUGL_ALPHA_BITS]), EGL_DEPTH_SIZE, puglWasmGlHintValue(view->hints[PUGL_DEPTH_BITS]), EGL_STENCIL_SIZE, puglWasmGlHintValue(view->hints[PUGL_STENCIL_BITS]), EGL_NONE }; // clang-format on if (eglChooseConfig(display, attrs, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { eglTerminate(display); return PUGL_CREATE_CONTEXT_FAILED; } PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)calloc(1, sizeof(PuglWasmGlSurface)); impl->surface = surface; surface->display = display; surface->config = config; surface->context = EGL_NO_SURFACE; surface->surface = EGL_NO_CONTEXT; view->hints[PUGL_RED_BITS] = puglWasmGlGetAttrib(display, config, EGL_RED_SIZE); view->hints[PUGL_GREEN_BITS] = puglWasmGlGetAttrib(display, config, EGL_GREEN_SIZE); view->hints[PUGL_BLUE_BITS] = puglWasmGlGetAttrib(display, config, EGL_BLUE_SIZE); view->hints[PUGL_ALPHA_BITS] = puglWasmGlGetAttrib(display, config, EGL_ALPHA_SIZE); view->hints[PUGL_DEPTH_BITS] = puglWasmGlGetAttrib(display, config, EGL_DEPTH_SIZE); view->hints[PUGL_STENCIL_BITS] = puglWasmGlGetAttrib(display, config, EGL_STENCIL_SIZE); view->hints[PUGL_SAMPLES] = puglWasmGlGetAttrib(display, config, EGL_SAMPLES); // double-buffering is always enabled for EGL view->hints[PUGL_DOUBLE_BUFFER] = 1; return PUGL_SUCCESS; } PUGL_WARN_UNUSED_RESULT static PuglStatus puglWasmGlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) { PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; if (!surface || !surface->context || !surface->surface) { return PUGL_FAILURE; } #ifndef PUGL_WASM_SINGLE_EGL_CONTEXT return eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context) ? PUGL_SUCCESS : PUGL_FAILURE; #else return PUGL_SUCCESS; #endif } PUGL_WARN_UNUSED_RESULT static PuglStatus puglWasmGlLeave(PuglView* view, const PuglExposeEvent* expose) { PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; if (expose) { // note: swap buffers always enabled for EGL eglSwapBuffers(surface->display, surface->surface); } #ifndef PUGL_WASM_SINGLE_EGL_CONTEXT return eglMakeCurrent(surface->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) ? PUGL_SUCCESS : PUGL_FAILURE; #else return PUGL_SUCCESS; #endif } static PuglStatus puglWasmGlCreate(PuglView* view) { PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; const EGLDisplay display = surface->display; const EGLConfig config = surface->config; const EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, view->hints[PUGL_CONTEXT_VERSION_MAJOR], EGL_CONTEXT_MAJOR_VERSION, view->hints[PUGL_CONTEXT_VERSION_MAJOR], /* EGL_CONTEXT_MINOR_VERSION, view->hints[PUGL_CONTEXT_VERSION_MINOR], EGL_CONTEXT_OPENGL_DEBUG, (view->hints[PUGL_USE_DEBUG_CONTEXT] ? EGL_TRUE : EGL_FALSE), EGL_CONTEXT_OPENGL_PROFILE_MASK, (view->hints[PUGL_USE_COMPAT_PROFILE] ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT), */ EGL_NONE }; surface->context = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); if (surface->context == EGL_NO_CONTEXT) { return PUGL_CREATE_CONTEXT_FAILED; } surface->surface = eglCreateWindowSurface(display, config, 0, NULL); if (surface->surface == EGL_NO_SURFACE) { return PUGL_CREATE_CONTEXT_FAILED; } #ifdef PUGL_WASM_SINGLE_EGL_CONTEXT eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context); #endif return PUGL_SUCCESS; } static void puglWasmGlDestroy(PuglView* view) { PuglWasmGlSurface* surface = (PuglWasmGlSurface*)view->impl->surface; if (surface) { const EGLDisplay display = surface->display; if (surface->surface != EGL_NO_SURFACE) eglDestroySurface(display, surface->surface); if (surface->context != EGL_NO_CONTEXT) eglDestroyContext(display, surface->context); eglTerminate(display); free(surface); view->impl->surface = NULL; } } const PuglBackend* puglGlBackend(void) { static const PuglBackend backend = {puglWasmGlConfigure, puglWasmGlCreate, puglWasmGlDestroy, puglWasmGlEnter, puglWasmGlLeave, puglStubGetContext}; return &backend; }