Skip to content

Commit

Permalink
Adding WebGL for Emscripten
Browse files Browse the repository at this point in the history
  • Loading branch information
vstanchevici authored and LukasBanana committed Aug 22, 2024
1 parent 45059ea commit 169e366
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#define LLGL_OPENGL_EMSCRIPTEN_NATIVE_HANDLE_H


#include <emscripten/html5.h>


namespace LLGL
{

Expand All @@ -23,7 +26,7 @@ namespace OpenGL
*/
struct RenderSystemNativeHandle
{
int context;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
};


Expand Down
4 changes: 2 additions & 2 deletions include/LLGL/Platform/Emscripten/EmscriptenNativeHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ namespace LLGL
//! Emscripten native handle structure.
struct NativeHandle
{
//! HTML canvas object.
emscripten::val canvas;
//! CSS selector of canvas object.
std::string canvas;
};


Expand Down
99 changes: 23 additions & 76 deletions sources/Renderer/OpenGL/Platform/Emscripten/EmscriptenGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ EmscriptenGLContext::EmscriptenGLContext(
const RendererConfigurationOpenGL& profile,
Surface& surface,
EmscriptenGLContext* sharedContext)
:
display_ { eglGetDisplay(EGL_DEFAULT_DISPLAY) }
{
CreateContext(pixelFormat, profile, sharedContext);
}
Expand All @@ -57,6 +55,7 @@ EmscriptenGLContext::~EmscriptenGLContext()

int EmscriptenGLContext::GetSamples() const
{
int samples_ = 4;
return samples_;
}

Expand All @@ -65,7 +64,7 @@ bool EmscriptenGLContext::GetNativeHandle(void* nativeHandle, std::size_t native
if (nativeHandle != nullptr && nativeHandleSize == sizeof(OpenGL::RenderSystemNativeHandle))
{
auto* nativeHandleGL = reinterpret_cast<OpenGL::RenderSystemNativeHandle*>(nativeHandle);
//nativeHandleGL->context = context_;
nativeHandleGL->context = context_;
return true;
}
return false;
Expand All @@ -78,88 +77,36 @@ bool EmscriptenGLContext::GetNativeHandle(void* nativeHandle, std::size_t native

bool EmscriptenGLContext::SetSwapInterval(int interval)
{
return (eglSwapInterval(display_, interval) == EGL_TRUE);
return true;
}

bool EmscriptenGLContext::SelectConfig(const GLPixelFormat& pixelFormat)
void EmscriptenGLContext::CreateContext(const GLPixelFormat& pixelFormat, const RendererConfigurationOpenGL& profile, EmscriptenGLContext* sharedContext)
{
/* Look for a framebuffer configuration; reduce samples if necessary */
for (samples_ = pixelFormat.samples; samples_ > 1; --samples_)
{
/* Initialize framebuffer configuration */
const EGLint attribs[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
//EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, pixelFormat.depthBits,
EGL_STENCIL_SIZE, pixelFormat.stencilBits,
EGL_SAMPLE_BUFFERS, (samples_ > 1 ? 1 : 0),
EGL_SAMPLES, (samples_ > 1 ? samples_ : 1),
EGL_NONE
};

/* Choose configuration */
EGLint numConfigs = 0;
EGLBoolean success = eglChooseConfig(display_, attribs, &config_, 1, &numConfigs);

/* Reduce number of sample if configuration failed */
if (success == EGL_TRUE && numConfigs >= 1)
{
SetDefaultColorFormat();
DeduceDepthStencilFormat(pixelFormat.depthBits, pixelFormat.stencilBits);
return true;
}
}

/* No suitable configuration found */
return false;
}

void EmscriptenGLContext::CreateContext(
const GLPixelFormat& pixelFormat,
const RendererConfigurationOpenGL& profile,
EmscriptenGLContext* sharedContext)
{
/* Initialize EGL display connection (ignore major/minor output parameters) */
if (!eglInitialize(display_, nullptr, nullptr))
throw std::runtime_error("eglInitialize failed");

/* Select EGL context configuration for pixel format */
if (!SelectConfig(pixelFormat))
throw std::runtime_error("eglChooseConfig failed");

/* Set up EGL profile attributes */
EGLint major = 3, minor = 0;
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
attrs.majorVersion = 2;
attrs.minorVersion = 0;
attrs.alpha = false;
attrs.depth = false;
attrs.stencil = false;
attrs.antialias = false;
attrs.premultipliedAlpha = true;
attrs.preserveDrawingBuffer = false;
attrs.explicitSwapControl = 0;
//attrs.preferLowPowerToHighPerformance = false;
attrs.failIfMajorPerformanceCaveat = false;
attrs.enableExtensionsByDefault = true;


context_ = emscripten_webgl_create_context("!canvas", &attrs);

if (!(profile.majorVersion == 0 && profile.minorVersion == 0))
{
major = profile.majorVersion;
minor = profile.minorVersion;
}

const EGLint contextAttribs[] =
{
EGL_CONTEXT_MAJOR_VERSION, major,
EGL_CONTEXT_MINOR_VERSION, minor,
#ifdef LLGL_DEBUG
EGL_CONTEXT_OPENGL_DEBUG, EGL_TRUE,
EGL_CONTEXT_OPENGL_ROBUST_ACCESS, EGL_TRUE,
#endif
EGL_NONE
};

/* Create EGL context with optional shared EGL context */
EGLContext sharedEGLContext = (sharedContext != nullptr ? sharedContext->context_ : EGL_NO_CONTEXT);
context_ = eglCreateContext(display_, config_, sharedEGLContext, contextAttribs);
if (!context_)
throw std::runtime_error("eglCreateContext failed");
throw std::runtime_error("emscripten_webgl_create_context failed");
}

void EmscriptenGLContext::DeleteContext()
{
eglDestroyContext(display_, context_);
//destroy context_
}


Expand Down
29 changes: 6 additions & 23 deletions sources/Renderer/OpenGL/Platform/Emscripten/EmscriptenGLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

#include "../GLContext.h"
#include "../../OpenGL.h"
#include <EGL/egl.h>

#include <emscripten.h>
#include <emscripten/html5.h>

namespace LLGL
{
Expand All @@ -38,30 +38,16 @@ class EmscriptenGLContext : public GLContext

public:

// Returns the native EGL display.
inline ::EGLDisplay GetEGLDisplay() const
{
return display_;
}

// Returns the native EGL context.
inline ::EGLContext GetEGLContext() const
// Returns the native WebGL context.
inline EMSCRIPTEN_WEBGL_CONTEXT_HANDLE GetWebGLContext() const
{
return context_;
}

// Returns the native EGL configuration.
inline ::EGLConfig GetEGLConfig() const
{
return config_;
}

private:

bool SetSwapInterval(int interval) override;

bool SelectConfig(const GLPixelFormat& pixelFormat);

void CreateContext(
const GLPixelFormat& pixelFormat,
const RendererConfigurationOpenGL& profile,
Expand All @@ -71,10 +57,7 @@ class EmscriptenGLContext : public GLContext

private:

::EGLDisplay display_ = nullptr;
::EGLContext context_ = nullptr;
::EGLConfig config_ = nullptr;
int samples_ = 1;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_ = 0;

};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
*/

#include "EmscriptenGLSwapChainContext.h"
#include "EmscriptenGLContext.h"
#include "../../../../Core/CoreUtils.h"
#include <LLGL/Platform/NativeHandle.h>


namespace LLGL
{

Expand All @@ -35,29 +33,24 @@ bool GLSwapChainContext::MakeCurrentUnchecked(GLSwapChainContext* context)
*/

EmscriptenGLSwapChainContext::EmscriptenGLSwapChainContext(EmscriptenGLContext& context, Surface& surface) :
GLSwapChainContext { context },
display_ { context.GetEGLDisplay() },
context_ { context.GetEGLContext() }
GLSwapChainContext { context }
{
/* Get native surface handle */
NativeHandle nativeHandle;
surface.GetNativeHandle(&nativeHandle, sizeof(nativeHandle));

/* Create drawable surface */
//surface_ = eglCreateWindowSurface(display_, context.GetEGLConfig(), nativeHandle.window, nullptr);

if (!surface_)
throw std::runtime_error("eglCreateWindowSurface failed");

if (!context.GetWebGLContext())
throw std::runtime_error("GetWebGLContext failed");
}

EmscriptenGLSwapChainContext::~EmscriptenGLSwapChainContext()
{
eglDestroySurface(display_, surface_);
//eglDestroySurface(display_, surface_);
}

bool EmscriptenGLSwapChainContext::SwapBuffers()
{
eglSwapBuffers(display_, surface_);
//empty
return true;
}

Expand All @@ -68,10 +61,21 @@ void EmscriptenGLSwapChainContext::Resize(const Extent2D& resolution)

bool EmscriptenGLSwapChainContext::MakeCurrentEGLContext(EmscriptenGLSwapChainContext* context)
{
if (context)
return eglMakeCurrent(context->display_, context->surface_, context->surface_, context->context_);
EMSCRIPTEN_RESULT res = emscripten_webgl_make_context_current(context->context_);

if (res == EMSCRIPTEN_RESULT_SUCCESS)
{
assert(emscripten_webgl_get_current_context() == context->GetGLContext());

int width, height, fs = 0;
emscripten_get_canvas_element_size("#canvas", &width, &height);
//printf("width:%d, height:%d\n", width, height);
//SetViewportSize((ndf32)width, (ndf32)height);
}
else
return eglMakeCurrent(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
throw std::runtime_error("emscripten_webgl_make_context_current failed");

return true;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

#include "../GLSwapChainContext.h"
#include "../../OpenGL.h"
#include <EGL/egl.h>

#include "EmscriptenGLContext.h"

namespace LLGL
{
Expand All @@ -38,9 +37,7 @@ class EmscriptenGLSwapChainContext final : public GLSwapChainContext

private:

::EGLDisplay display_ = nullptr;
::EGLContext context_ = nullptr;
::EGLSurface surface_ = nullptr;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_ = 0;

};

Expand Down

0 comments on commit 169e366

Please sign in to comment.