common: fix context corruption among the multiple canvases.
authorHermet Park <chuneon.park@samsung.com>
Sat, 5 Sep 2020 09:33:23 +0000 (18:33 +0900)
committerHermet Park <chuneon.park@samsung.com>
Sat, 5 Sep 2020 09:57:22 +0000 (18:57 +0900)
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.

Change-Id: I2649d55c4ba3bd44853006332b2ee83096906abe

.gitignore
src/lib/gl_engine/tvgGlRenderer.cpp
src/lib/gl_engine/tvgGlRenderer.h
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwRenderer.h
src/lib/tvgCanvasImpl.h
src/lib/tvgGlCanvas.cpp
src/lib/tvgRender.h
src/lib/tvgSwCanvas.cpp
test/makefile
test/testCommon.h

index 53a53b5..0234166 100644 (file)
@@ -23,3 +23,4 @@ testSvg2
 testAsync
 testCapi
 testArc
+testMultiCanvas
index f6b31d4..9e9f8ef 100644 (file)
 /************************************************************************/
 /* 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())
-    {
-        inst()->mColorProgram.reset(nullptr);
-    }
-    return RenderInitializer::term(renderInit);
-}
+    if (!initEngine) return true;
 
+    initEngine = false;
 
-uint32_t GlRenderer::unref()
-{
-    return RenderInitializer::unref(renderInit);
+   _termEngine();
+
+    return true;
 }
 
 
-uint32_t GlRenderer::ref()
+GlRenderer* GlRenderer::gen()
 {
-    return RenderInitializer::ref(renderInit);
+    return new GlRenderer();
 }
 
 
-GlRenderer* GlRenderer::inst()
+GlRenderer::~GlRenderer()
 {
-    //We know renderer type, avoid dynamic_cast for performance.
-    return static_cast<GlRenderer*>(RenderInitializer::inst(renderInit));
+    if (mColorProgram.get())
+    {
+        mColorProgram.reset(nullptr);
+    }
+
+    --rendererCnt;
+    if (!initEngine) _termEngine();
 }
 
 
index 9a86bae..a0f5715 100644 (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);
index 24b5a16..e69aaa4 100644 (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,21 +99,16 @@ struct SwTask : Task
 
 SwRenderer::~SwRenderer()
 {
-    flush();
-    if (surface) delete(surface);
-}
+    clear();
 
+    if (surface) delete(surface);
 
-bool SwRenderer::clear()
-{
-    for (auto task : tasks) task->get();
-    tasks.clear();
-
-    return flush();
+    --rendererCnt;
+    if (!initEngine) _termEngine();
 }
 
 
-bool SwRenderer::flush()
+bool SwRenderer::clear()
 {
     for (auto task : tasks) task->get();
     tasks.clear();
@@ -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:
 
-int SwRenderer::term()
-{
-    return RenderInitializer::term(renderInit);
+    initEngine = true;
+
+    return true;
 }
 
 
-uint32_t SwRenderer::unref()
+bool SwRenderer::term()
 {
-    return RenderInitializer::unref(renderInit);
-}
+    if (!initEngine) return true;
 
+    initEngine = false;
 
-uint32_t SwRenderer::ref()
-{
-    return RenderInitializer::ref(renderInit);
-}
+   _termEngine();
 
+    return true;
+}
 
-SwRenderer* SwRenderer::inst()
+SwRenderer* SwRenderer::gen()
 {
-    //We know renderer type, avoid dynamic_cast for performance.
-    return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit));
+    ++rendererCnt;
+    return new SwRenderer();
 }
index 8f4abab..35fce30 100644 (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;
index 4e15ace..d5b1b76 100644 (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)
index 7f267a4..235bacb 100644 (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
index c379d0e..9beb72b 100644 (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;
-    }
-
 };
 
 }
index b56beb4..5e6af44 100644 (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
index f48278d..2bdd549 100644 (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`
index a5f222e..5dd70cd 100644 (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);