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

View file

@ -44,6 +44,7 @@
#include "tvgMath.h"
#ifdef __EMSCRIPTEN__
#include <emscripten/html5_webgl.h>
// query GL Error on WebGL is very slow, so disable it on WebGL
#define GL_CHECK(x) x
#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()
{
}
@ -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();
@ -795,6 +811,7 @@ bool GlRenderer::target(int32_t id, uint32_t w, uint32_t h)
surface.w = w;
surface.h = h;
mContext = context;
mTargetFboId = static_cast<GLint>(id);
mRootTarget.mWidth = surface.w;
@ -811,6 +828,8 @@ bool GlRenderer::sync()
//nothing to be done.
if (mRenderPassStack.empty()) return true;
currentContext();
// Blend function for straight alpha
GL_CHECK(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
GL_CHECK(glEnable(GL_BLEND));
@ -860,6 +879,7 @@ RenderRegion GlRenderer::region(RenderData data)
bool GlRenderer::preRender()
{
currentContext();
if (mPrograms.empty()) initShaders();
mRenderPassStack.push(new GlRenderPass(&mRootTarget));
@ -1235,6 +1255,7 @@ bool GlRenderer::viewport(const RenderRegion& vp)
bool GlRenderer::preUpdate()
{
currentContext();
return true;
}

View file

@ -79,7 +79,7 @@ public:
ColorSpace colorSpace() 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 clear() override;
@ -115,7 +115,9 @@ private:
void endRenderPass(RenderCompositor* cmp);
void flush();
void currentContext();
void* mContext = nullptr;
RenderSurface surface;
GLint mTargetFboId = 0;
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);
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};
renderer->viewport(pImpl->vport);