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:
Hermet Park 2020-09-05 18:33:23 +09:00 committed by Hermet Park
parent 56e474ffab
commit 8685c7e0f0
11 changed files with 83 additions and 127 deletions

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ testSvg2
testAsync
testCapi
testArc
testMultiCanvas

View file

@ -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();
}

View file

@ -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);

View file

@ -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();
}

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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;
}
};
}

View file

@ -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

View file

@ -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`

View file

@ -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);