evas vg: improve masking render logic. 32/198632/1
authorHermet Park <hermetpark@gmail.com>
Mon, 28 Jan 2019 07:53:42 +0000 (16:53 +0900)
committerHermet Park <hermetpark@gmail.com>
Mon, 28 Jan 2019 08:03:18 +0000 (17:03 +0900)
Previous masking image is generated on vg rendering time,
though context is changed to main vg rendering to masking,
This had a issue that ector context switching which is not allowed
in software backend because of asynchronou method.

Now, this improvment brings the masking rendering move to
vg render pre step with synchronous rendering method,
then use the masking surface in the main vg rendering.

Change-Id: I59b4c14899a9c3cd794273bf46e3c286c15561a3

src/lib/evas/canvas/efl_canvas_vg_container.c
src/lib/evas/canvas/efl_canvas_vg_gradient_linear.c
src/lib/evas/canvas/efl_canvas_vg_gradient_radial.c
src/lib/evas/canvas/efl_canvas_vg_object.c
src/lib/evas/canvas/efl_canvas_vg_shape.c
src/lib/evas/canvas/evas_vg_private.h

index f82f18a..f22ff1a 100644 (file)
@@ -22,9 +22,35 @@ _invalidate_cb(void *data EINA_UNUSED, const Efl_Event *event)
       efl_unref(child);
 }
 
+static void
+_draw_mask(Evas_Object_Protected_Data *obj, Efl_VG *node,
+           Ector_Surface *ector, void *engine, void *output,
+           void *context)
+{
+   if (!efl_gfx_entity_visible_get(node)) return;
+
+   if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS))
+     {
+        Efl_Canvas_Vg_Container_Data *cd =
+           efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS);
+
+        //Draw Mask Image.
+        Efl_VG *child;
+        Eina_List *l;
+        EINA_LIST_FOREACH(cd->children, l, child)
+          _draw_mask(obj, child, ector, engine, output, context);
+     }
+   else
+     {
+        Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(node, EFL_CANVAS_VG_NODE_CLASS);
+        ENFN->ector_renderer_draw(engine, output, context, nd->renderer, NULL, EINA_FALSE);
+     }
+}
+
 static Ector_Buffer *
 _prepare_mask(Evas_Object_Protected_Data *obj,     //vector object
               Efl_Canvas_Vg_Node* mask_obj,
+              void *engine, void *output, void *context,
               Ector_Surface *surface,
               Eina_Matrix3 *ptransform,
               Ector_Buffer *mask,
@@ -75,10 +101,17 @@ _prepare_mask(Evas_Object_Protected_Data *obj,     //vector object
 
    if (!pd->mask.buffer) ERR("Mask Buffer is invalid");
 
-   pd->mask.dirty = EINA_TRUE;
+   //3. Prepare Drawing shapes.
+   _evas_vg_render_pre(obj, mask_obj,
+                       engine, output, context,
+                       surface,
+                       ptransform, mask, mask_op);
 
-   //3. Prepare Drawing shapes...
-   _evas_vg_render_pre(obj, mask_obj, surface, ptransform, mask, mask_op);
+   //4. Generating Mask Image.
+   ector_buffer_pixels_set(surface, pd->mask.pixels, mbound.w, mbound.h, 0,
+                           EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE);
+   ector_surface_reference_point_set(surface, -mbound.x, -mbound.y);
+   _draw_mask(obj, mask_obj, surface, engine, output, context);
 
    return pd->mask.buffer;
 }
@@ -87,6 +120,7 @@ static void
 _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
                                     Efl_VG *obj EINA_UNUSED,
                                     Efl_Canvas_Vg_Node_Data *nd,
+                                    void *engine, void *output, void *context,
                                     Ector_Surface *surface,
                                     Eina_Matrix3 *ptransform,
                                     Ector_Buffer *mask,
@@ -108,8 +142,9 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
    //Container may have mask source.
    if (pd->mask_src)
      {
-        mask = _prepare_mask(vg_pd, pd->mask_src, surface, ptransform, mask,
-                             mask_op);
+        mask = _prepare_mask(vg_pd, pd->mask_src,
+                             engine, output, context, surface,
+                             ptransform, mask, mask_op);
         mask_op = pd->mask.option;
      }
 
@@ -133,7 +168,9 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
         if (flag & EFL_GFX_CHANGE_FLAG_MATRIX)
           child_nd->flags |= EFL_GFX_CHANGE_FLAG_MATRIX;
 
-        _evas_vg_render_pre(vg_pd, child, surface, ctransform, mask, mask_op);
+        _evas_vg_render_pre(vg_pd, child,
+                            engine, output, context, surface,
+                            ctransform, mask, mask_op);
      }
 }
 
index ad3118f..0b14352 100644 (file)
@@ -59,6 +59,9 @@ static void
 _efl_canvas_vg_gradient_linear_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED,
                                           Efl_VG *obj,
                                           Efl_Canvas_Vg_Node_Data *nd,
+                                          void *engine EINA_UNUSED,
+                                          void *output EINA_UNUSED,
+                                          void *context EINA_UNUSED,
                                           Ector_Surface *surface,
                                           Eina_Matrix3 *ptransform,
                                           Ector_Buffer *mask,
index 4146cdd..691dc5d 100644 (file)
@@ -75,6 +75,9 @@ static void
 _efl_canvas_vg_gradient_radial_render_pre(Evas_Object_Protected_Data *vg_pd EINA_UNUSED,
                                           Efl_VG *obj,
                                           Efl_Canvas_Vg_Node_Data *nd,
+                                          void *engine EINA_UNUSED,
+                                          void *output EINA_UNUSED,
+                                          void *context EINA_UNUSED,
                                           Ector_Surface *surface,
                                           Eina_Matrix3 *ptransform,
                                           Ector_Buffer *mask,
index f85e62e..0d1104b 100644 (file)
@@ -481,43 +481,6 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
         Efl_Canvas_Vg_Container_Data *cd =
            efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS);
 
-        //Update Mask Image
-        if (cd->mask_src)
-          {
-             Efl_Canvas_Vg_Container_Data *cd2 =
-                efl_data_scope_get(cd->mask_src, EFL_CANVAS_VG_CONTAINER_CLASS);
-
-             if (cd2->mask.buffer && cd2->mask.dirty)
-               {
-                  Ector_Surface *ector = evas_ector_get(obj->layer->evas);
-                  if (!ector) return;
-
-                  ENFN->ector_end(engine, output, context, ector, EINA_FALSE);
-
-                  //Need a better approach.
-                  ector_buffer_pixels_set(ector, cd2->mask.pixels, cd2->mask.bound.w, cd2->mask.bound.h, 0,
-                                          EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE);
-                  ector_surface_reference_point_set(ector, -cd2->mask.bound.x, -cd2->mask.bound.y);
-
-                  //Draw Mask Image.
-                  Efl_VG *child;
-                  Eina_List *l;
-                  EINA_LIST_FOREACH(cd2->children, l, child)
-                     _evas_vg_render(obj, pd, engine, output, context, child,
-                                     clips, EINA_FALSE);
-
-                  cd2->mask.dirty = EINA_FALSE;
-#if 0
-                  FILE *fp = fopen("./test.raw", "w+");
-                  fwrite(cd2->mask.pixels, cd2->mask.bound.w * cd2->mask.bound.h, sizeof(uint32_t), fp);
-                  fclose(fp);
-                  ERR("size = %d x %d", cd2->mask.bound.w, cd2->mask.bound.h);
-#endif
-                  //Restore previous ector context
-                  ENFN->ector_begin(engine, output, context, ector, 0, 0, EINA_FALSE, do_async);
-               }
-          }
-
         if (cd->mask.target) return;   //Don't draw mask itself.
 
         Efl_VG *child;
@@ -556,13 +519,17 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd
         buffer_created = EINA_TRUE;
      }
 
-   _evas_vg_render_pre(obj, root, ector, NULL, NULL, 0);
-
    //initialize buffer
    context = evas_common_draw_context_new();
    evas_common_draw_context_set_render_op(context, _EVAS_RENDER_COPY);
    evas_common_draw_context_set_color(context, 255, 255, 255, 255);
 
+   //ector begin - end for drawing mask images.
+   ENFN->ector_begin(engine, buffer, context, ector, 0, 0, EINA_FALSE, EINA_FALSE);
+   _evas_vg_render_pre(obj, root, engine, buffer, context, ector, NULL, NULL, 0);
+   ENFN->ector_end(engine, buffer, context, ector, EINA_FALSE);
+
+   //Actual content drawing
    ENFN->ector_begin(engine, buffer, context, ector, 0, 0, EINA_TRUE, do_async);
 
    //draw on buffer
@@ -823,9 +790,10 @@ _efl_canvas_vg_object_render_pre(Evas_Object *eo_obj,
      }
 
    // FIXME: handle damage only on changed renderer.
+   // FIXME: Move this render_pre to efl_canvas_vg_render()
    s = evas_ector_get(obj->layer->evas);
    if (pd->root && s)
-     _evas_vg_render_pre(obj, pd->root, s, NULL, NULL, 0);
+     _evas_vg_render_pre(obj, pd->root, NULL, NULL, NULL, s, NULL, NULL, 0);
 
    /* now figure what changed and add draw rects */
    /* if it just became visible or invisible */
index dc671f9..417641a 100644 (file)
@@ -75,6 +75,7 @@ static void
 _efl_canvas_vg_shape_render_pre(Evas_Object_Protected_Data *vg_pd,
                                 Efl_VG *obj,
                                 Efl_Canvas_Vg_Node_Data *nd,
+                                void *engine, void *output, void *context,
                                 Ector_Surface *surface,
                                 Eina_Matrix3 *ptransform,
                                 Ector_Buffer *mask,
@@ -90,9 +91,15 @@ _efl_canvas_vg_shape_render_pre(Evas_Object_Protected_Data *vg_pd,
 
    EFL_CANVAS_VG_COMPUTE_MATRIX(ctransform, ptransform, nd);
 
-   fill = _evas_vg_render_pre(vg_pd, pd->fill, surface, ctransform, mask, mask_op);
-   stroke_fill = _evas_vg_render_pre(vg_pd, pd->stroke.fill, surface, ctransform, mask, mask_op);
-   stroke_marker = _evas_vg_render_pre(vg_pd, pd->stroke.marker, surface, ctransform, mask, mask_op);
+   fill = _evas_vg_render_pre(vg_pd, pd->fill,
+                              engine, output, context,
+                              surface, ctransform, mask, mask_op);
+   stroke_fill = _evas_vg_render_pre(vg_pd, pd->stroke.fill,
+                                     engine, output, context,
+                                     surface, ctransform, mask, mask_op);
+   stroke_marker = _evas_vg_render_pre(vg_pd, pd->stroke.marker,
+                                       engine, output, context,
+                                       surface, ctransform, mask, mask_op);
 
    if (!nd->renderer)
      {
index dc5cdf6..5476a21 100644 (file)
@@ -69,7 +69,8 @@ struct _Efl_Canvas_Vg_Node_Data
    Efl_Canvas_Vg_Object_Data *vd;
 
    void (*render_pre)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node,
-         Efl_Canvas_Vg_Node_Data *nd, Ector_Surface *surface,
+         Efl_Canvas_Vg_Node_Data *nd,
+         void *engine, void *output, void *contenxt, Ector_Surface *surface,
          Eina_Matrix3 *ptransform, Ector_Buffer *mask, int mask_op, void *data);
    void *data;
 
@@ -89,7 +90,6 @@ typedef struct _Vg_Mask
    Eina_Rect bound;                    //Mask boundary
    Eina_List *target;                  //Mask target
    int option;                         //Mask option
-   Eina_Bool dirty : 1;                //Need to update mask image.
 } Vg_Mask;
 
 struct _Efl_Canvas_Vg_Container_Data
@@ -146,11 +146,17 @@ efl_canvas_vg_object_change(Efl_Canvas_Vg_Object_Data *vd)
 }
 
 static inline Efl_Canvas_Vg_Node_Data *
-_evas_vg_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *child, Ector_Surface *surface, Eina_Matrix3 *transform, Ector_Buffer *mask, int mask_op)
+_evas_vg_render_pre(Evas_Object_Protected_Data *vg_pd, Efl_VG *child,
+                    void *engine, void *output, void *context,
+                    Ector_Surface *surface,
+                    Eina_Matrix3 *transform,
+                    Ector_Buffer *mask, int mask_op)
 {
    if (!child) return NULL;
    Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS);
-   if (nd) nd->render_pre(vg_pd, child, nd, surface, transform, mask, mask_op, nd->data);
+   if (nd) nd->render_pre(vg_pd, child, nd,
+                          engine, output, context, surface,
+                          transform, mask, mask_op, nd->data);
    return nd;
 }