From 142470237eab41e957088519b97c256f550f770b Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 12 Jun 2019 15:43:34 -0700 Subject: [PATCH] html5 glcontext --- src/amalgamated.cpp | 1 + src/glcontext_html5.cpp | 191 ++++++++++++++++++++++++++++++++++++++++ src/glcontext_html5.h | 47 ++++++++++ src/renderer_gl.h | 9 +- 4 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 src/glcontext_html5.cpp create mode 100644 src/glcontext_html5.h diff --git a/src/amalgamated.cpp b/src/amalgamated.cpp index e88d7051b..77bf62c2f 100644 --- a/src/amalgamated.cpp +++ b/src/amalgamated.cpp @@ -9,6 +9,7 @@ #include "glcontext_egl.cpp" #include "glcontext_glx.cpp" #include "glcontext_wgl.cpp" +#include "glcontext_html5.cpp" #include "nvapi.cpp" #include "renderer_d3d11.cpp" #include "renderer_d3d12.cpp" diff --git a/src/glcontext_html5.cpp b/src/glcontext_html5.cpp new file mode 100644 index 000000000..474c19604 --- /dev/null +++ b/src/glcontext_html5.cpp @@ -0,0 +1,191 @@ +/* + * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "bgfx_p.h" + +#if BGFX_CONFIG_RENDERER_OPENGLES +# include "renderer_gl.h" + +# if BGFX_USE_HTML5 + +#include +#include + +// from emscripten gl.c, because we're not going to go +// through egl +extern "C" void* emscripten_GetProcAddress(const char *name_); + +namespace bgfx { namespace gl +{ + +# define GL_IMPORT(_optional, _proto, _func, _import) _proto _func = NULL +# include "glimports.h" + + static EmscriptenWebGLContextAttributes s_attrs; + + struct SwapChainGL + { + SwapChainGL(int _context, const char* _canvas) + : m_context(_context) + { + BX_ALLOC(g_allocator, strlen(_canvas) + 1); + strcpy(m_canvas, _canvas); + + makeCurrent(); + GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) ); + GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) ); + swapBuffers(); + GL_CHECK(glClear(GL_COLOR_BUFFER_BIT) ); + swapBuffers(); + } + + ~SwapChainGL() + { + emscripten_webgl_destroy_context(m_context); + BX_FREE(g_allocator, m_canvas); + } + + void makeCurrent() + { + emscripten_webgl_make_context_current(m_context); + } + + void swapBuffers() + { + // There is no swapBuffers equivalent. A swap happens whenever control is returned back + // to the browser. + } + + int m_context; + char* m_canvas; + }; + + void GlContext::create(uint32_t _width, uint32_t _height) + { + // assert? + if (m_primary != NULL) + return; + + const char* canvas = (const char*) g_platformData.nwh; // if 0, Module.canvas is used + + m_primary = createSwapChain((void*)canvas); + + if (_width && _height) + emscripten_set_canvas_element_size(canvas, (int)_width, (int)_height); + + makeCurrent(m_primary); + } + + void GlContext::destroy() + { + if (m_primary) + { + if (m_current == m_primary) + m_current = NULL; + BX_DELETE(g_allocator, m_primary); + m_primary = NULL; + } + } + + void GlContext::resize(uint32_t _width, uint32_t _height, uint32_t /* _flags */) + { + if (m_primary == NULL) + return; + + emscripten_set_canvas_element_size(m_primary->m_canvas, (int) _width, (int) _height); + } + + SwapChainGL* GlContext::createSwapChain(void* _nwh) + { + emscripten_webgl_init_context_attributes(&s_attrs); + + s_attrs.alpha = false; + s_attrs.depth = true; + s_attrs.stencil = true; + s_attrs.enableExtensionsByDefault = true; + + // let emscripten figure out the best WebGL context to create + // TODO this isn't necessarily the right thing, I don't think the code actually does the fallback like it should + s_attrs.majorVersion = 0; + s_attrs.majorVersion = 0; + + const char* canvas = (const char*) _nwh; + + int context = emscripten_webgl_create_context(canvas, &s_attrs); + + if (context <= 0) + { + BX_TRACE("Failed to create WebGL context. (Canvas handle: '%s', error %d)", canvas, (int)context); + return NULL; + } + + int result = emscripten_webgl_make_context_current(context); + if (EMSCRIPTEN_RESULT_SUCCESS != result) + { + BX_TRACE("emscripten_webgl_make_context_current failed (%d)", result); + return NULL; + } + + SwapChainGL* swapChain = BX_NEW(g_allocator, SwapChainGL)(context, canvas); + + import(); + + return swapChain; + } + + uint64_t GlContext::getCaps() const + { + return BGFX_CAPS_SWAP_CHAIN; + } + + void GlContext::destroySwapChain(SwapChainGL* _swapChain) + { + BX_DELETE(g_allocator, _swapChain); + } + + void GlContext::swap(SwapChainGL* /* _swapChain */) + { + } + + void GlContext::makeCurrent(SwapChainGL* _swapChain) + { + if (m_current != _swapChain) + { + m_current = _swapChain; + + if (NULL == _swapChain) + { + if (NULL != m_primary) + { + m_primary->makeCurrent(); + } + } + else + { + _swapChain->makeCurrent(); + } + } + } + + void GlContext::import() + { + BX_TRACE("Import:"); +# define GL_EXTENSION(_optional, _proto, _func, _import) \ + { \ + if (NULL == _func) \ + { \ + _func = (_proto)emscripten_GetProcAddress(#_import); \ + BX_TRACE("\t%p " #_func " (" #_import ")", _func); \ + BGFX_FATAL(_optional || NULL != _func, Fatal::UnableToInitialize, "Failed to create WebGL/OpenGLES context. GetProcAddress(\"%s\")", #_import); \ + } \ + } + +# include "glimports.h" + } + +} /* namespace gl */ } // namespace bgfx + +# endif // BGFX_USE_EGL +#endif // (BGFX_CONFIG_RENDERER_OPENGLES || BGFX_CONFIG_RENDERER_OPENGL) diff --git a/src/glcontext_html5.h b/src/glcontext_html5.h new file mode 100644 index 000000000..9475970a5 --- /dev/null +++ b/src/glcontext_html5.h @@ -0,0 +1,47 @@ +/* + * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#ifndef BGFX_GLCONTEXT_HTML5_H_HEADER_GUARD +#define BGFX_GLCONTEXT_HTML5_H_HEADER_GUARD + +#if BGFX_USE_HTML5 + +namespace bgfx { namespace gl +{ + struct SwapChainGL; + + struct GlContext + { + GlContext() + : m_current(NULL) + , m_primary(NULL) + { + } + + void create(uint32_t _width, uint32_t _height); + void destroy(); + void resize(uint32_t _width, uint32_t _height, uint32_t _flags); + + uint64_t getCaps() const; + SwapChainGL* createSwapChain(void* _nwh); + void destroySwapChain(SwapChainGL* _swapChain); + void swap(SwapChainGL* _swapChain = NULL); + void makeCurrent(SwapChainGL* _swapChain = NULL); + + void import(); + + bool isValid() const + { + return NULL != m_primary; + } + + SwapChainGL* m_current; + SwapChainGL* m_primary; + }; +} /* namespace gl */ } // namespace bgfx + +#endif // BGFX_USE_HTML5 + +#endif // BGFX_GLCONTEXT_HTML5_H_HEADER_GUARD diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 6c53ff3e3..dd3066df2 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -9,7 +9,6 @@ #define BGFX_USE_EGL (BGFX_CONFIG_RENDERER_OPENGLES && (0 \ || BX_PLATFORM_ANDROID \ || BX_PLATFORM_BSD \ - || BX_PLATFORM_EMSCRIPTEN \ || BX_PLATFORM_LINUX \ || BX_PLATFORM_NX \ || BX_PLATFORM_RPI \ @@ -17,6 +16,10 @@ || BX_PLATFORM_WINDOWS \ ) ) +#define BGFX_USE_HTML5 (BGFX_CONFIG_RENDERER_OPENGLES && (0 \ + || BX_PLATFORM_EMSCRIPTEN \ + ) ) + #define BGFX_USE_WGL (BGFX_CONFIG_RENDERER_OPENGL && BX_PLATFORM_WINDOWS) #define BGFX_USE_GLX (BGFX_CONFIG_RENDERER_OPENGL && (0 \ || BX_PLATFORM_BSD \ @@ -125,6 +128,10 @@ typedef uint64_t GLuint64; # include "glcontext_egl.h" # endif // BGFX_USE_EGL +# if BGFX_USE_HTML5 +# include "glcontext_html5.h" +# endif // BGFX_USE_EGL + # if BX_PLATFORM_EMSCRIPTEN # include # endif // BX_PLATFORM_EMSCRIPTEN