mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
common: fix context corruption among the multiple canvases.
previous implementation didn't consider multiple canvases, multiple canvas shared one renderer engine that brought corrupted contexts. Thus, each canvas instances should have designated renderer engine instances. Now fixed.
This commit is contained in:
parent
56e474ffab
commit
8685c7e0f0
11 changed files with 83 additions and 127 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -23,3 +23,4 @@ testSvg2
|
|||
testAsync
|
||||
testCapi
|
||||
testArc
|
||||
testMultiCanvas
|
||||
|
|
|
@ -28,8 +28,15 @@
|
|||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
static bool initEngine = false;
|
||||
static uint32_t rendererCnt = 0;
|
||||
|
||||
static RenderInitializer renderInit;
|
||||
static void _termEngine()
|
||||
{
|
||||
if (rendererCnt > 0) return;
|
||||
|
||||
//TODO: Clean up global resources
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
|
@ -160,36 +167,44 @@ void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const Rende
|
|||
|
||||
int GlRenderer::init()
|
||||
{
|
||||
return RenderInitializer::init(renderInit, new GlRenderer);
|
||||
if (rendererCnt > 0) return false;
|
||||
if (initEngine) return true;
|
||||
|
||||
//TODO:
|
||||
|
||||
initEngine = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int GlRenderer::term()
|
||||
{
|
||||
if (inst()->mColorProgram.get())
|
||||
if (!initEngine) return true;
|
||||
|
||||
initEngine = false;
|
||||
|
||||
_termEngine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
GlRenderer* GlRenderer::gen()
|
||||
{
|
||||
return new GlRenderer();
|
||||
}
|
||||
|
||||
|
||||
GlRenderer::~GlRenderer()
|
||||
{
|
||||
if (mColorProgram.get())
|
||||
{
|
||||
inst()->mColorProgram.reset(nullptr);
|
||||
mColorProgram.reset(nullptr);
|
||||
}
|
||||
return RenderInitializer::term(renderInit);
|
||||
}
|
||||
|
||||
|
||||
uint32_t GlRenderer::unref()
|
||||
{
|
||||
return RenderInitializer::unref(renderInit);
|
||||
}
|
||||
|
||||
|
||||
uint32_t GlRenderer::ref()
|
||||
{
|
||||
return RenderInitializer::ref(renderInit);
|
||||
}
|
||||
|
||||
|
||||
GlRenderer* GlRenderer::inst()
|
||||
{
|
||||
//We know renderer type, avoid dynamic_cast for performance.
|
||||
return static_cast<GlRenderer*>(RenderInitializer::inst(renderInit));
|
||||
--rendererCnt;
|
||||
if (!initEngine) _termEngine();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,16 +40,14 @@ public:
|
|||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||
bool flush() override;
|
||||
bool clear() override;
|
||||
uint32_t ref() override;
|
||||
uint32_t unref() override;
|
||||
|
||||
static GlRenderer* inst();
|
||||
static GlRenderer* gen();
|
||||
static int init();
|
||||
static int term();
|
||||
|
||||
private:
|
||||
GlRenderer(){};
|
||||
~GlRenderer(){};
|
||||
~GlRenderer();
|
||||
|
||||
void initShaders();
|
||||
void drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
static RenderInitializer renderInit;
|
||||
static bool initEngine = false;
|
||||
static uint32_t rendererCnt = 0;
|
||||
|
||||
struct SwTask : Task
|
||||
{
|
||||
|
@ -84,6 +85,13 @@ struct SwTask : Task
|
|||
}
|
||||
};
|
||||
|
||||
static void _termEngine()
|
||||
{
|
||||
if (rendererCnt > 0) return;
|
||||
|
||||
//TODO: Clean up global resources
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
|
@ -91,8 +99,12 @@ struct SwTask : Task
|
|||
|
||||
SwRenderer::~SwRenderer()
|
||||
{
|
||||
flush();
|
||||
clear();
|
||||
|
||||
if (surface) delete(surface);
|
||||
|
||||
--rendererCnt;
|
||||
if (!initEngine) _termEngine();
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,15 +113,6 @@ bool SwRenderer::clear()
|
|||
for (auto task : tasks) task->get();
|
||||
tasks.clear();
|
||||
|
||||
return flush();
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::flush()
|
||||
{
|
||||
for (auto task : tasks) task->get();
|
||||
tasks.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -202,32 +205,32 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
|||
}
|
||||
|
||||
|
||||
int SwRenderer::init()
|
||||
bool SwRenderer::init()
|
||||
{
|
||||
return RenderInitializer::init(renderInit, new SwRenderer);
|
||||
if (rendererCnt > 0) return false;
|
||||
if (initEngine) return true;
|
||||
|
||||
//TODO:
|
||||
|
||||
initEngine = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int SwRenderer::term()
|
||||
bool SwRenderer::term()
|
||||
{
|
||||
return RenderInitializer::term(renderInit);
|
||||
if (!initEngine) return true;
|
||||
|
||||
initEngine = false;
|
||||
|
||||
_termEngine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SwRenderer::unref()
|
||||
SwRenderer* SwRenderer::gen()
|
||||
{
|
||||
return RenderInitializer::unref(renderInit);
|
||||
}
|
||||
|
||||
|
||||
uint32_t SwRenderer::ref()
|
||||
{
|
||||
return RenderInitializer::ref(renderInit);
|
||||
}
|
||||
|
||||
|
||||
SwRenderer* SwRenderer::inst()
|
||||
{
|
||||
//We know renderer type, avoid dynamic_cast for performance.
|
||||
return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit));
|
||||
++rendererCnt;
|
||||
return new SwRenderer();
|
||||
}
|
||||
|
|
|
@ -36,13 +36,10 @@ public:
|
|||
bool preRender() override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
bool clear() override;
|
||||
bool flush() override;
|
||||
uint32_t ref() override;
|
||||
uint32_t unref() override;
|
||||
|
||||
static SwRenderer* inst();
|
||||
static int init();
|
||||
static int term();
|
||||
static SwRenderer* gen();
|
||||
static bool init();
|
||||
static bool term();
|
||||
|
||||
private:
|
||||
SwSurface* surface = nullptr;
|
||||
|
|
|
@ -35,14 +35,12 @@ struct Canvas::Impl
|
|||
|
||||
Impl(RenderMethod* pRenderer):renderer(pRenderer)
|
||||
{
|
||||
renderer->ref();
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
renderer->flush(); //make it sur async engine working finished.
|
||||
clear();
|
||||
renderer->unref();
|
||||
delete(renderer);
|
||||
}
|
||||
|
||||
Result push(unique_ptr<Paint> paint)
|
||||
|
|
|
@ -46,7 +46,7 @@ struct GlCanvas::Impl
|
|||
/************************************************************************/
|
||||
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
GlCanvas::GlCanvas() : Canvas(GlRenderer::inst()), pImpl(make_unique<Impl>())
|
||||
GlCanvas::GlCanvas() : Canvas(GlRenderer::gen()), pImpl(make_unique<Impl>())
|
||||
#else
|
||||
GlCanvas::GlCanvas() : Canvas(nullptr), pImpl(make_unique<Impl>())
|
||||
#endif
|
||||
|
|
|
@ -64,63 +64,6 @@ public:
|
|||
virtual bool postRender() { return true; }
|
||||
virtual bool clear() { return true; }
|
||||
virtual bool flush() { return true; }
|
||||
virtual uint32_t ref() { return 0; }
|
||||
virtual uint32_t unref() { return 0; }
|
||||
};
|
||||
|
||||
struct RenderInitializer
|
||||
{
|
||||
RenderMethod* pInst = nullptr;
|
||||
uint32_t refCnt = 0;
|
||||
bool initialized = false;
|
||||
|
||||
static bool init(RenderInitializer& renderInit, RenderMethod* engine)
|
||||
{
|
||||
if (renderInit.pInst || renderInit.refCnt > 0) return false;
|
||||
renderInit.pInst = engine;
|
||||
renderInit.refCnt = 0;
|
||||
renderInit.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool term(RenderInitializer& renderInit)
|
||||
{
|
||||
if (!renderInit.pInst || !renderInit.initialized) return false;
|
||||
|
||||
renderInit.initialized = false;
|
||||
|
||||
//Still it's refered....
|
||||
if (renderInit.refCnt > 0) return true;
|
||||
delete(renderInit.pInst);
|
||||
renderInit.pInst = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t unref(RenderInitializer& renderInit)
|
||||
{
|
||||
--renderInit.refCnt;
|
||||
|
||||
//engine has been requested to termination
|
||||
if (!renderInit.initialized && renderInit.refCnt == 0) {
|
||||
if (renderInit.pInst) {
|
||||
delete(renderInit.pInst);
|
||||
renderInit.pInst = nullptr;
|
||||
}
|
||||
}
|
||||
return renderInit.refCnt;
|
||||
}
|
||||
|
||||
static RenderMethod* inst(RenderInitializer& renderInit)
|
||||
{
|
||||
return renderInit.pInst;
|
||||
}
|
||||
|
||||
static uint32_t ref(RenderInitializer& renderInit)
|
||||
{
|
||||
return ++renderInit.refCnt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ struct SwCanvas::Impl
|
|||
/************************************************************************/
|
||||
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
SwCanvas::SwCanvas() : Canvas(SwRenderer::inst()), pImpl(make_unique<Impl>())
|
||||
SwCanvas::SwCanvas() : Canvas(SwRenderer::gen()), pImpl(make_unique<Impl>())
|
||||
#else
|
||||
SwCanvas::SwCanvas() : Canvas(nullptr), pImpl(make_unique<Impl>())
|
||||
#endif
|
||||
|
|
|
@ -20,4 +20,5 @@ all:
|
|||
gcc -o testSvg2 testSvg2.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testArc testArc.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testMultiCanvas testMultiCanvas.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
|
||||
gcc -o testCapi testCapi.c -g `pkg-config --cflags --libs elementary thorvg`
|
||||
|
|
|
@ -50,7 +50,7 @@ void drawGLview(Evas_Object *obj);
|
|||
|
||||
static Eo* createGlView()
|
||||
{
|
||||
elm_config_accel_preference_set("gl");
|
||||
elm_config_accel_preference_set("gl");
|
||||
|
||||
Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test");
|
||||
evas_object_smart_callback_add(win, "delete,request", win_del, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue