diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_gl.c	Mon Oct 16 21:53:34 2023 +0200
@@ -0,0 +1,228 @@
+// 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;
+}