Revert "Revert "evas vg: lottie rendering optimization"" 97/262197/2
authorHermet Park <chuneon.park@samsung.com>
Wed, 4 Aug 2021 03:07:09 +0000 (12:07 +0900)
committerHermet Park <chuneon.park@samsung.com>
Thu, 5 Aug 2021 01:24:45 +0000 (01:24 +0000)
This reverts commit 5aecd0c3d221a402340e59f5ba7ec8ccb4f8ff07.

Change-Id: I7c3abc8c1f6599434ebacf15c918fff7a1392c0c

src/lib/evas/canvas/efl_canvas_vg_container.c
src/lib/evas/canvas/evas_vg_private.h
src/static_libs/vg_common/vg_common_json.c

index a28b350..cb3430b 100644 (file)
@@ -36,7 +36,7 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *obj,
    if (!nd || !nd->data) return;
    cd = nd->data;
 
-   tvg_scene_clear(cd->scene, EINA_FALSE);
+   if (!cd->master_scene) tvg_scene_clear(cd->scene, EINA_FALSE);
 
    if (!nd->visibility) return;
 
index a341b57..fa5839b 100644 (file)
@@ -99,6 +99,7 @@ struct _Efl_Canvas_Vg_Container_Data
    Vg_Comp comp;                    //Composite target data
 
    Tvg_Paint *scene;
+   Eina_Bool  master_scene: 1; //Defines if scene is handled outside efl_canvas_vg_container.c. If true scene won't be cleared on render_pre.
 };
 
 struct _Efl_Canvas_Vg_Gradient_Data
index 1bd7465..70aec3b 100644 (file)
@@ -18,154 +18,112 @@ _get_key_val(void *key)
 }
 
 static void
-_construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *layer, int depth EINA_UNUSED)
+_construct_drawable_nodes(Tvg_Paint *parent, const LOTLayerNode *layer, int depth EINA_UNUSED)
 {
    if (!parent) return;
 
-   //This list is used for layer order verification
-   Eina_List *list = (Eina_List*) efl_canvas_vg_container_children_direct_get(parent);
+   tvg_scene_reserve(parent, layer->mNodeList.size);
 
    for (unsigned int i = 0; i < layer->mNodeList.size; i++)
      {
-        if (i > 0) list = eina_list_next(list);
-
         LOTNode *node = layer->mNodeList.ptr[i];
         if (!node) continue;
 
-        //Image object
-        if (node->mImageInfo.data)
-          {
-             char *key = _get_key_val(node);
-             Efl_Canvas_Vg_Image *image = efl_key_data_get(parent, key);
-             if (!image)
-               {
-                  image = efl_add(EFL_CANVAS_VG_IMAGE_CLASS, parent);
-                  efl_key_data_set(parent, key, image);
-               }
 #if DEBUG
         for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p)\n", efl_class_name_get(efl_class_get(image)), image);
+        printf("[node %03d] type:%s\n", i, (node->mImageInfo.data)?"image":"shape");
 #endif
-             Eina_Matrix3 m;
-             eina_matrix3_identity(&m);
-             eina_matrix3_values_set( &m,
-                                      node->mImageInfo.mMatrix.m11,  node->mImageInfo.mMatrix.m12, node->mImageInfo.mMatrix.m13,
-                                      node->mImageInfo.mMatrix.m21,  node->mImageInfo.mMatrix.m22, node->mImageInfo.mMatrix.m23,
-                                      node->mImageInfo.mMatrix.m31,  node->mImageInfo.mMatrix.m32, node->mImageInfo.mMatrix.m33);
-             efl_canvas_vg_node_transformation_set(image, &m);
-             efl_canvas_vg_image_data_set(image, node->mImageInfo.data, EINA_SIZE2D(node->mImageInfo.width, node->mImageInfo.height));
-             evas_vg_node_color_set(image, node->mImageInfo.mAlpha, node->mImageInfo.mAlpha, node->mImageInfo.mAlpha, node->mImageInfo.mAlpha);
-             evas_vg_node_visible_set(image, EINA_TRUE);
-
-             continue;
-          }
-
-        char *key = _get_key_val(node);
-        Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key);
-        if (!shape)
-          {
-             shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
-             efl_key_data_set(parent, key, shape);
-          }
-        else
-          {
-             evas_vg_shape_reset(shape);
 
-             //Layer order is mismatched!
-             if (eina_list_data_get(list) != shape)
-                evas_vg_node_raise(shape);
-          }
-
-        //Skip Invisible Stroke?
-        if (node->mStroke.enable && node->mStroke.width == 0)
+        //Image object
+        if (node->mImageInfo.data)
           {
-             evas_vg_node_visible_set(shape, EINA_FALSE);
+             Tvg_Paint* picture = tvg_picture_new();
+             Tvg_Matrix tvg_matrix = {
+                node->mImageInfo.mMatrix.m11,  node->mImageInfo.mMatrix.m12, node->mImageInfo.mMatrix.m13,
+                node->mImageInfo.mMatrix.m21,  node->mImageInfo.mMatrix.m22, node->mImageInfo.mMatrix.m23,
+                node->mImageInfo.mMatrix.m31,  node->mImageInfo.mMatrix.m32, node->mImageInfo.mMatrix.m33
+             };
+             tvg_paint_transform(picture, &tvg_matrix);
+             tvg_picture_load_raw(picture, (uint32_t *)node->mImageInfo.data, node->mImageInfo.width, node->mImageInfo.height, EINA_FALSE);
+             tvg_paint_set_opacity(picture, node->mImageInfo.mAlpha);
+             tvg_scene_push(parent, picture);
              continue;
           }
 
+        Tvg_Paint* shape = tvg_shape_new();
+
         const float *data = node->mPath.ptPtr;
         if (!data) continue;
 
-        if (node->keypath) efl_key_data_set(shape, "_lot_node_name", node->keypath);
-        evas_vg_node_visible_set(shape, EINA_TRUE);
-#if DEBUG
-        for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p) keypath : %s\n", efl_class_name_get(efl_class_get(shape)), shape, node->keypath);
-#endif
         //0: Path
-        efl_gfx_path_reserve(shape, node->mPath.elmCount, node->mPath.ptCount);
+        uint32_t cmdCnt = node->mPath.elmCount;
+        uint32_t ptsCnt = node->mPath.ptCount * sizeof(float) / sizeof(Tvg_Point);
+        Tvg_Path_Command cmds[cmdCnt];
+        Tvg_Point pts[ptsCnt];
 
-        for (size_t i = 0; i < node->mPath.elmCount; i++)
+        uint32_t cmd_i = 0, pts_i = 0;
+        for (uint32_t i = 0; i < cmdCnt; i++)
           {
-             switch (node->mPath.elmPtr[i])
-               {
-                case 0:
-                   evas_vg_shape_append_move_to(shape, data[0], data[1]);
-                   data += 2;
-                   break;
-                case 1:
-                   evas_vg_shape_append_line_to(shape, data[0], data[1]);
-                   data += 2;
-                   break;
-                case 2:
-                   evas_vg_shape_append_cubic_to(shape, data[4], data[5], data[0], data[1], data[2], data[3]);
-                   data += 6;
-                   break;
-                case 3:
-                   evas_vg_shape_append_close(shape);
-                   break;
-                default:
-                   ERR("No reserved path type = %d", node->mPath.elmPtr[i]);
-               }
+            switch (node->mPath.elmPtr[i])
+              {
+               case 0:
+                  cmds[cmd_i++] = TVG_PATH_COMMAND_MOVE_TO;
+                  pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+                  data += 2;
+                  break;
+               case 1:
+                  cmds[cmd_i++] = TVG_PATH_COMMAND_LINE_TO;
+                  pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+                  data += 2;
+                  break;
+               case 2:
+                  cmds[cmd_i++] = TVG_PATH_COMMAND_CUBIC_TO;
+                  pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+                  pts[pts_i++] = (Tvg_Point){data[2], data[3]};
+                  pts[pts_i++] = (Tvg_Point){data[4], data[5]};
+                  data += 6;
+                  break;
+               case 3:
+                  cmds[cmd_i++] = TVG_PATH_COMMAND_CLOSE;
+                  break;
+               default:
+                  ERR("No reserved path type = %d", node->mPath.elmPtr[i]);
+              }
           }
+        tvg_shape_append_path(shape, cmds, cmd_i, pts, pts_i);
 
         //1: Stroke
         if (node->mStroke.enable)
           {
              //Stroke Width
-             evas_vg_shape_stroke_width_set(shape, node->mStroke.width);
+             tvg_shape_set_stroke_width(shape, node->mStroke.width);
 
              //Stroke Cap
-             Efl_Gfx_Cap cap;
+             Tvg_Stroke_Cap cap;
              switch (node->mStroke.cap)
                {
-                case CapFlat: cap = EFL_GFX_CAP_BUTT; break;
-                case CapSquare: cap = EFL_GFX_CAP_SQUARE; break;
-                case CapRound: cap = EFL_GFX_CAP_ROUND; break;
-                default: cap = EFL_GFX_CAP_BUTT; break;
+                case CapFlat: cap = TVG_STROKE_CAP_BUTT; break;
+                case CapSquare: cap = TVG_STROKE_CAP_SQUARE; break;
+                case CapRound: cap = TVG_STROKE_CAP_ROUND; break;
+                default: cap = TVG_STROKE_CAP_BUTT; break;
                }
-             evas_vg_shape_stroke_cap_set(shape, cap);
+             tvg_shape_set_stroke_cap(shape, cap);
 
              //Stroke Join
-             Efl_Gfx_Join join;
+             Tvg_Stroke_Join join;
              switch (node->mStroke.join)
                {
-                case JoinMiter: join = EFL_GFX_JOIN_MITER; break;
-                case JoinBevel: join = EFL_GFX_JOIN_BEVEL; break;
-                case JoinRound: join = EFL_GFX_JOIN_ROUND; break;
-                default: join = EFL_GFX_JOIN_MITER; break;
+                case JoinMiter: join = TVG_STROKE_JOIN_MITER; break;
+                case JoinBevel: join = TVG_STROKE_JOIN_BEVEL; break;
+                case JoinRound: join = TVG_STROKE_JOIN_ROUND; break;
+                default: join = TVG_STROKE_JOIN_MITER; break;
                }
-             evas_vg_shape_stroke_join_set(shape, join);
-
-             #ifndef HAVE_THORVG
-             efl_gfx_shape_stroke_miterlimit_set(shape, node->mStroke.miterLimit);
-             #endif
+             tvg_shape_set_stroke_join(shape, join);
 
              //Stroke Dash
              if (node->mStroke.dashArraySize > 0)
                {
-                  int size = (node->mStroke.dashArraySize / 2);
-                  Evas_Vg_Dash *dash = malloc(sizeof(Efl_Gfx_Dash) * size);
-                  if (dash)
-                    {
-                       for (int i = 0; i <= size; i+=2)
-                         {
-                            dash[i].length = node->mStroke.dashArray[i];
-                            dash[i].gap = node->mStroke.dashArray[i + 1];
-                         }
-                       evas_vg_shape_stroke_dash_set(shape, dash, size);
-                       free(dash);
-                    }
+                  tvg_shape_set_stroke_dash(shape, node->mStroke.dashArray, node->mStroke.dashArraySize);
                }
           }
 
@@ -174,48 +132,25 @@ _construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *l
           {
            case BrushSolid:
              {
-                float pa = ((float)node->mColor.a) / 255;
-                int r = (int)(((float) node->mColor.r) * pa);
-                int g = (int)(((float) node->mColor.g) * pa);
-                int b = (int)(((float) node->mColor.b) * pa);
-                int a = node->mColor.a;
-
                 if (node->mStroke.enable)
-                  evas_vg_shape_stroke_color_set(shape, r, g, b, a);
+                  tvg_shape_set_stroke_color(shape, node->mColor.r, node->mColor.g, node->mColor.b, node->mColor.a);
                 else
-                  evas_vg_node_color_set(shape, r, g, b, a);
+                  tvg_shape_set_fill_color(shape, node->mColor.r, node->mColor.g, node->mColor.b, node->mColor.a);
              }
              break;
            case BrushGradient:
              {
-                Efl_Canvas_Vg_Gradient* grad = NULL;
+                Tvg_Gradient* grad = NULL;
 
                 if (node->mGradient.type == GradientLinear)
                   {
-                     char *key = _get_key_val(shape);
-                     grad = efl_key_data_get(shape, key);
-                     if (!grad)
-                       {
-                          grad = efl_add(EFL_CANVAS_VG_GRADIENT_LINEAR_CLASS, parent);
-                          efl_key_data_set(shape, key, grad);
-                       }
-                     evas_vg_node_visible_set(grad, EINA_TRUE);
-                     evas_vg_gradient_linear_start_set(grad, node->mGradient.start.x, node->mGradient.start.y);
-                     evas_vg_gradient_linear_end_set(grad, node->mGradient.end.x, node->mGradient.end.y);
+                     grad = tvg_linear_gradient_new();
+                     tvg_linear_gradient_set(grad, node->mGradient.start.x, node->mGradient.start.y, node->mGradient.end.x, node->mGradient.end.y);
                   }
                 else if (node->mGradient.type == GradientRadial)
                   {
-                     char *key = _get_key_val(shape);
-                     grad = efl_key_data_get(shape, key);
-                     if (!grad)
-                       {
-                          grad = efl_add(EFL_CANVAS_VG_GRADIENT_RADIAL_CLASS, parent);
-                          efl_key_data_set(shape, key, grad);
-                       }
-                     evas_vg_node_visible_set(grad, EINA_TRUE);
-                     evas_vg_gradient_radial_center_set(grad, node->mGradient.center.x, node->mGradient.center.y);
-                     evas_vg_gradient_radial_focal_set(grad, node->mGradient.focal.x, node->mGradient.focal.y);
-                     evas_vg_gradient_radial_radius_set(grad, node->mGradient.cradius);
+                     grad = tvg_radial_gradient_new();
+                     tvg_radial_gradient_set(grad, node->mGradient.center.x, node->mGradient.center.y, node->mGradient.cradius);
                   }
                 else
                   ERR("No reserved gradient type = %d", node->mGradient.type);
@@ -223,25 +158,35 @@ _construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *l
                 if (grad)
                   {
                      //Gradient Stop
-                     Evas_Vg_Gradient_Stop* stops = malloc(sizeof(Efl_Gfx_Gradient_Stop) * node->mGradient.stopCount);
+                     Tvg_Color_Stop *stops = malloc(sizeof(Tvg_Color_Stop) * node->mGradient.stopCount);
                      if (stops)
                        {
                           for (unsigned int i = 0; i < node->mGradient.stopCount; i++)
                             {
                                stops[i].offset = node->mGradient.stopPtr[i].pos;
-                               float pa = ((float)node->mGradient.stopPtr[i].a) / 255;
-                               stops[i].r = (int)(((float)node->mGradient.stopPtr[i].r) * pa);
-                               stops[i].g = (int)(((float)node->mGradient.stopPtr[i].g) * pa);
-                               stops[i].b = (int)(((float)node->mGradient.stopPtr[i].b) * pa);
+                               stops[i].r = node->mGradient.stopPtr[i].r;
+                               stops[i].g = node->mGradient.stopPtr[i].g;
+                               stops[i].b = node->mGradient.stopPtr[i].b;
                                stops[i].a = node->mGradient.stopPtr[i].a;
                             }
-                          evas_vg_gradient_stop_set(grad, stops, node->mGradient.stopCount);
+                          tvg_gradient_set_color_stops(grad, stops, node->mGradient.stopCount);
                           free(stops);
                        }
+
                      if (node->mStroke.enable)
-                       efl_canvas_vg_shape_stroke_fill_set(shape, grad);
+                       {
+                          if (node->mGradient.type == GradientLinear)
+                             tvg_shape_set_stroke_linear_gradient(shape, grad);
+                          else if (node->mGradient.type == GradientRadial)
+                             tvg_shape_set_stroke_radial_gradient(shape, grad);
+                       }
                      else
-                       efl_canvas_vg_shape_fill_set(shape, grad);
+                       {
+                          if (node->mGradient.type == GradientLinear)
+                              tvg_shape_set_linear_gradient(shape, grad);
+                          else if (node->mGradient.type == GradientRadial)
+                              tvg_shape_set_radial_gradient(shape, grad);
+                       }
                   }
              }
              break;
@@ -251,119 +196,85 @@ _construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *l
 
         //3: Fill Rule
         if (node->mFillRule == FillEvenOdd)
-           evas_vg_shape_fill_rule_set(shape, EVAS_VG_FILL_RULE_ODD_EVEN);
+          tvg_shape_set_fill_rule(shape, TVG_FILL_RULE_EVEN_ODD);
         else if (node->mFillRule == FillWinding)
-           evas_vg_shape_fill_rule_set(shape, EVAS_VG_FILL_RULE_WINDING);
+          tvg_shape_set_fill_rule(shape, TVG_FILL_RULE_WINDING);
+
+        tvg_scene_push(parent, shape);
      }
 }
 
 static void
-_construct_mask_nodes(Efl_Canvas_Vg_Container *parent, LOTMask *mask, int depth EINA_UNUSED)
+_construct_mask_nodes(Tvg_Paint *parent, LOTMask *mask, int depth EINA_UNUSED)
 {
    const float *data = mask->mPath.ptPtr;
    if (!data) return;
 
-   char *key = _get_key_val(mask);
-   Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key);
-   if (!shape)
-     {
-        shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
-        efl_key_data_set(parent, key, shape);
-     }
-   else
-     evas_vg_shape_reset(shape);
-
-#if DEBUG
-        for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p)\n", efl_class_name_get(efl_class_get(shape)), shape);
-#endif
+   Tvg_Paint* shape = tvg_shape_new();
 
-   evas_vg_node_visible_set(shape, EINA_TRUE);
-   efl_gfx_path_reserve(shape, mask->mPath.elmCount, mask->mPath.ptCount);
+   //Path
+   uint32_t cmdCnt = mask->mPath.elmCount;
+   uint32_t ptsCnt = mask->mPath.ptCount * sizeof(float) / sizeof(Tvg_Point);
+   Tvg_Path_Command cmds[cmdCnt];
+   Tvg_Point pts[ptsCnt];
 
-   for (size_t i = 0; i < mask->mPath.elmCount; i++)
+   uint32_t cmd_i = 0, pts_i = 0;
+   for (uint32_t i = 0; i < cmdCnt; i++)
      {
-        switch (mask->mPath.elmPtr[i])
-          {
-           case 0:
-              evas_vg_shape_append_move_to(shape, data[0], data[1]);
-              data += 2;
-              break;
-           case 1:
-              evas_vg_shape_append_line_to(shape, data[0], data[1]);
-              data += 2;
-              break;
-           case 2:
-              evas_vg_shape_append_cubic_to(shape, data[4], data[5], data[0], data[1], data[2], data[3]);
-              data += 6;
-              break;
-           case 3:
-              evas_vg_shape_append_close(shape);
-              break;
-           default:
-              ERR("No reserved path type = %d", mask->mPath.elmPtr[i]);
-              break;
-          }
+       switch (mask->mPath.elmPtr[i])
+         {
+          case 0:
+             cmds[cmd_i++] = TVG_PATH_COMMAND_MOVE_TO;
+             pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+             data += 2;
+             break;
+          case 1:
+             cmds[cmd_i++] = TVG_PATH_COMMAND_LINE_TO;
+             pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+             data += 2;
+             break;
+          case 2:
+             cmds[cmd_i++] = TVG_PATH_COMMAND_CUBIC_TO;
+             pts[pts_i++] = (Tvg_Point){data[0], data[1]};
+             pts[pts_i++] = (Tvg_Point){data[2], data[3]};
+             pts[pts_i++] = (Tvg_Point){data[4], data[5]};
+             data += 6;
+             break;
+          case 3:
+             cmds[cmd_i++] = TVG_PATH_COMMAND_CLOSE;
+             break;
+          default:
+             ERR("No reserved path type = %d", mask->mPath.elmPtr[i]);
+         }
      }
+   tvg_shape_append_path(shape, cmds, cmd_i, pts, pts_i);
+
    //White color and alpha setting
-   float pa = ((float)mask->mAlpha) / 255;
-   int r = (int) (255.0f * pa);
-   int g = (int) (255.0f * pa);
-   int b = (int) (255.0f * pa);
-   int a = mask->mAlpha;
-   evas_vg_node_color_set(shape, r, g, b, a);
+   tvg_shape_set_fill_color(shape, 255, 255, 255, mask->mAlpha);
+
+   tvg_scene_push(parent, shape);
 }
 
-static Efl_Canvas_Vg_Container*
-_construct_masks(Efl_Canvas_Vg_Container *mtarget, LOTMask *masks, unsigned int mask_cnt, int depth)
+static Tvg_Paint*
+_construct_masks(Tvg_Paint *mtarget, LOTMask *masks, unsigned int mask_cnt, int depth)
 {
-   char *key = NULL;
-
-   Efl_Canvas_Vg_Container *msource = NULL;
-
-   key = _get_key_val(mtarget);
-   msource = efl_key_data_get(mtarget, key);
-   if (!msource)
-     {
-        msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget);
-        efl_key_data_set(mtarget, key, msource);
-     }
-   evas_vg_node_visible_set(msource, EINA_TRUE);
-
-#if DEBUG
-        for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p), base mask => %p\n", efl_class_name_get(efl_class_get(msource)), msource, mtarget);
-        depth++;
-#endif
-
-   //FIXME : EFL_GFX_VG_COMPOSITE_METHOD_ALPHA option is temporary
-   //Currently matte alpha implements is same the mask intersect implement.
-   //It has been implemented as a multiplication calculation.
-   efl_canvas_vg_node_comp_method_set(mtarget, msource, EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA);
-
+   Tvg_Paint *msource = tvg_scene_new();
+   tvg_paint_set_composite_method(mtarget, msource, TVG_COMPOSITE_METHOD_ALPHA_MASK);
    mtarget = msource;
 
    //Make mask layers
    for (unsigned int i = 0; i < mask_cnt; i++)
      {
-        LOTMask *mask = &masks[i];;
-        key = _get_key_val(mask);
-        msource = efl_key_data_get(mtarget, key);
-
-        if (!msource)
-          {
-             msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget);
-             efl_key_data_set(mtarget, key, msource);
-          }
-        evas_vg_node_visible_set(msource, EINA_TRUE);
+        LOTMask *mask = &masks[i];
+        _construct_mask_nodes(msource, mask, depth + 1);
 
 #if DEBUG
         for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p), real mask:%d => %p\n", efl_class_name_get(efl_class_get(msource)), msource, mask->mMode, mtarget);
+        printf("[mask %03d] mode:%d\n", i, mask->mMode);
 #endif
 
-        _construct_mask_nodes(msource, mask, depth + 1);
-
+        //FIX_TVG: mask->mMode not supported
+#if 0
         Efl_Gfx_Vg_Composite_Method mask_mode;
         switch (mask->mMode)
           {
@@ -383,41 +294,22 @@ _construct_masks(Efl_Canvas_Vg_Container *mtarget, LOTMask *masks, unsigned int
           }
         efl_canvas_vg_node_comp_method_set(mtarget, msource, mask_mode);
         mtarget = msource;
+#endif
      }
    return mtarget;
 }
 
 static void
-_reset_vg_tree(Efl_VG *node)
-{
-   //Hide all nodes visibility
-   if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS))
-     {
-        Eina_List *list = (Eina_List*) efl_canvas_vg_container_children_direct_get(node);
-        Eina_List *list2;
-        Efl_VG* child;
-        EINA_LIST_FOREACH(list, list2, child)
-          _reset_vg_tree(child);
-     }
-   evas_vg_node_visible_set(node, EINA_FALSE);
-}
-
-static void
-_update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int depth EINA_UNUSED)
+_update_vg_tree(Tvg_Paint *root, const LOTLayerNode *layer, int depth EINA_UNUSED)
 {
    if (!layer->mVisible) return;
-
-   evas_vg_node_visible_set(root, EINA_TRUE);
-   evas_vg_node_color_set(root, layer->mAlpha, layer->mAlpha, layer->mAlpha, layer->mAlpha);
-
-   //Don't need to update it anymore since its layer is invisible.
    if (layer->mAlpha == 0) return;
 
-   Efl_Canvas_Vg_Container *ptree = NULL;
+   Tvg_Paint *ptree = NULL;
 
    //Note: We assume that if matte is valid, next layer must be a matte source.
-   int matte_mode = 0;
-   Efl_Canvas_Vg_Container *mtarget = NULL;
+   Tvg_Composite_Method matte_mode = TVG_COMPOSITE_METHOD_NONE;
+   Tvg_Paint *mtarget = NULL;
    LOTLayerNode *mlayer = NULL;
 
    //Is this layer a container layer?
@@ -425,63 +317,60 @@ _update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int de
      {
         LOTLayerNode *clayer = layer->mLayerList.ptr[i];
 
-        //Source Layer
-        char *key = _get_key_val(clayer);
-        Efl_Canvas_Vg_Container *ctree = efl_key_data_get(root, key);
-        if (!ctree)
-          {
-             ctree = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, root);
-             efl_key_data_set(root, key, ctree);
-             if (clayer->keypath) efl_key_data_set(ctree, "_lot_node_name", clayer->keypath);
-          }
 #if DEBUG
         for (int i = 0; i < depth; i++) printf("    ");
-        printf("%s (%p) matte:%d => %p %s\n", efl_class_name_get(efl_class_get(ctree)), ctree, matte_mode, ptree, clayer->keypath);
+        printf("[layer %03d] matte:%d\n", i, matte_mode);
 #endif
+
+        //Source Layer
+        Tvg_Paint *ctree = tvg_scene_new();
         _update_vg_tree(ctree, clayer, depth+1);
 
-        if (matte_mode != 0)
+        if (matte_mode == TVG_COMPOSITE_METHOD_NONE)
           {
-             efl_canvas_vg_node_comp_method_set(ptree, ctree, matte_mode);
-             mtarget = ctree;
+             tvg_scene_push(root, ctree);
           }
-        matte_mode = (int) clayer->mMatte;
-
-        if (clayer->mMaskList.size > 0)
+        else
           {
-             mlayer = clayer;
-             if (!mtarget) mtarget = ctree;
+             tvg_paint_set_composite_method(ptree, ctree, matte_mode);
+             mtarget = ctree;
           }
-        else
-           mtarget = NULL;
-
-        ptree = ctree;
 
         //Remap Matte Mode
-        switch (matte_mode)
+        switch (clayer->mMatte)
           {
            case MatteNone:
-              matte_mode = 0;
+              matte_mode = TVG_COMPOSITE_METHOD_NONE;
               break;
            case MatteAlpha:
-              matte_mode = EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA;
+              matte_mode = TVG_COMPOSITE_METHOD_ALPHA_MASK;
               break;
            case MatteAlphaInv:
-              matte_mode = EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA_INVERSE;
+              matte_mode = TVG_COMPOSITE_METHOD_INVERSE_ALPHA_MASK;
               break;
            case MatteLuma:
-              matte_mode = 0;
+              matte_mode = TVG_COMPOSITE_METHOD_NONE;
               ERR("TODO: MatteLuma");
               break;
            case MatteLumaInv:
-              matte_mode = 0;
+              matte_mode = TVG_COMPOSITE_METHOD_NONE;
               ERR("TODO: MatteLumaInv");
               break;
            default:
-              matte_mode = 0;
+              matte_mode = TVG_COMPOSITE_METHOD_NONE;
               break;
           }
 
+        ptree = ctree;
+
+        if (clayer->mMaskList.size > 0)
+          {
+             mlayer = clayer;
+             if (!mtarget) mtarget = ctree;
+          }
+        else
+           mtarget = NULL;
+
         //Construct node that have mask.
         if (mlayer && mtarget)
           ptree = _construct_masks(mtarget, mlayer->mMaskList.ptr, mlayer->mMaskList.size, depth + 1);
@@ -490,7 +379,6 @@ _update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int de
    //Construct drawable nodes.
    if (layer->mNodeList.size > 0)
      _construct_drawable_nodes(root, layer, depth);
-
 }
 #endif
 
@@ -606,13 +494,15 @@ vg_common_json_create_vg_node(Vg_File_Data *vfd)
         if (tree->keypath) efl_key_data_set(root, "_lot_node_name", tree->keypath);
         vfd->root = root;
      }
-   else _reset_vg_tree(root);
 
-#if DEBUG
-   printf("%s (%p)\n", efl_class_name_get(efl_class_get(vfd->root)), vfd->root);
-#endif
+   Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(root, EFL_CANVAS_VG_NODE_CLASS);
+   if (!nd || !nd->data) return EINA_FALSE;
+   Efl_Canvas_Vg_Container_Data *cd = nd->data;
+   if (!cd->scene) return EINA_FALSE;
+   cd->master_scene = EINA_TRUE;
 
-   _update_vg_tree(root, tree, 1);
+   tvg_scene_clear(cd->scene, EINA_TRUE);
+   _update_vg_tree(cd->scene, tree, 1);
 #else
    return EINA_FALSE;
 #endif