gl_engine: ensure the gl context switching

This only covers emscripten environment,
need to cover other system.

issue: #3023

Co-Authored-By: Hermet Park <hermet@lottiefiles.com>
This commit is contained in:
Hermet Park 2024-12-31 11:51:46 +09:00 committed by Hermet Park
parent 596de01b12
commit 76203c3dbb
5 changed files with 30 additions and 8 deletions

View file

@ -188,7 +188,7 @@ struct TvgWgEngine : TvgEngineMethod
struct TvgGLEngine : TvgEngineMethod struct TvgGLEngine : TvgEngineMethod
{ {
uintptr_t context = 0; EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = 0;
~TvgGLEngine() override ~TvgGLEngine() override
{ {
#ifdef THORVG_GL_RASTER_SUPPORT #ifdef THORVG_GL_RASTER_SUPPORT
@ -227,9 +227,7 @@ struct TvgGLEngine : TvgEngineMethod
void resize(Canvas* canvas, int w, int h) override void resize(Canvas* canvas, int w, int h) override
{ {
#ifdef THORVG_GL_RASTER_SUPPORT #ifdef THORVG_GL_RASTER_SUPPORT
emscripten_webgl_make_context_current(context); static_cast<GlCanvas*>(canvas)->target((void*)context, 0, w, h, ColorSpace::ABGR8888S);
static_cast<GlCanvas*>(canvas)->target(0, w, h, ColorSpace::ABGR8888S);
#endif #endif
} }
}; };

View file

@ -44,6 +44,7 @@
#include "tvgMath.h" #include "tvgMath.h"
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include <emscripten/html5_webgl.h>
// query GL Error on WebGL is very slow, so disable it on WebGL // query GL Error on WebGL is very slow, so disable it on WebGL
#define GL_CHECK(x) x #define GL_CHECK(x) x
#else #else

View file

@ -74,6 +74,19 @@ void GlRenderer::flush()
} }
void GlRenderer::currentContext()
{
#ifdef __EMSCRIPTEN__
auto targetContext = (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)mContext;
if (emscripten_webgl_get_current_context() != targetContext) {
emscripten_webgl_make_context_current(targetContext);
}
#else
TVGERR("GL_ENGINE", "Maybe missing MakeCurrent() Call?");
#endif
}
GlRenderer::GlRenderer() GlRenderer::GlRenderer()
{ {
} }
@ -785,9 +798,12 @@ bool GlRenderer::clear()
} }
bool GlRenderer::target(int32_t id, uint32_t w, uint32_t h) bool GlRenderer::target(void* context, int32_t id, uint32_t w, uint32_t h)
{ {
if (id == GL_INVALID_VALUE || w == 0 || h == 0) return false; //assume the context zero is invalid
if (!context || id == GL_INVALID_VALUE || w == 0 || h == 0) return false;
currentContext();
flush(); flush();
@ -795,6 +811,7 @@ bool GlRenderer::target(int32_t id, uint32_t w, uint32_t h)
surface.w = w; surface.w = w;
surface.h = h; surface.h = h;
mContext = context;
mTargetFboId = static_cast<GLint>(id); mTargetFboId = static_cast<GLint>(id);
mRootTarget.mWidth = surface.w; mRootTarget.mWidth = surface.w;
@ -811,6 +828,8 @@ bool GlRenderer::sync()
//nothing to be done. //nothing to be done.
if (mRenderPassStack.empty()) return true; if (mRenderPassStack.empty()) return true;
currentContext();
// Blend function for straight alpha // Blend function for straight alpha
GL_CHECK(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GL_CHECK(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
GL_CHECK(glEnable(GL_BLEND)); GL_CHECK(glEnable(GL_BLEND));
@ -860,6 +879,7 @@ RenderRegion GlRenderer::region(RenderData data)
bool GlRenderer::preRender() bool GlRenderer::preRender()
{ {
currentContext();
if (mPrograms.empty()) initShaders(); if (mPrograms.empty()) initShaders();
mRenderPassStack.push(new GlRenderPass(&mRootTarget)); mRenderPassStack.push(new GlRenderPass(&mRootTarget));
@ -1235,6 +1255,7 @@ bool GlRenderer::viewport(const RenderRegion& vp)
bool GlRenderer::preUpdate() bool GlRenderer::preUpdate()
{ {
currentContext();
return true; return true;
} }

View file

@ -79,7 +79,7 @@ public:
ColorSpace colorSpace() override; ColorSpace colorSpace() override;
const RenderSurface* mainSurface() override; const RenderSurface* mainSurface() override;
bool target(int32_t id, uint32_t w, uint32_t h); bool target(void* context, int32_t id, uint32_t w, uint32_t h);
bool sync() override; bool sync() override;
bool clear() override; bool clear() override;
@ -115,7 +115,9 @@ private:
void endRenderPass(RenderCompositor* cmp); void endRenderPass(RenderCompositor* cmp);
void flush(); void flush();
void currentContext();
void* mContext = nullptr;
RenderSurface surface; RenderSurface surface;
GLint mTargetFboId = 0; GLint mTargetFboId = 0;
RenderRegion mViewport; RenderRegion mViewport;

View file

@ -54,7 +54,7 @@ Result GlCanvas::target(void* context, int32_t id, uint32_t w, uint32_t h, Color
auto renderer = static_cast<GlRenderer*>(pImpl->renderer); auto renderer = static_cast<GlRenderer*>(pImpl->renderer);
if (!renderer) return Result::MemoryCorruption; if (!renderer) return Result::MemoryCorruption;
if (!renderer->target(id, w, h)) return Result::Unknown; if (!renderer->target(context, id, w, h)) return Result::Unknown;
pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; pImpl->vport = {0, 0, (int32_t)w, (int32_t)h};
renderer->viewport(pImpl->vport); renderer->viewport(pImpl->vport);