ector: Fix precomp layer rendering issue when it has alpha value 62/208262/1
authorJunsuChoi <jsuya.choi@samsung.com>
Thu, 20 Jun 2019 07:07:05 +0000 (16:07 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 21 Jun 2019 00:50:31 +0000 (09:50 +0900)
Summary:
When the precomp layer(parent layer) has alpha transparency and has more than 1 child layer
and they overlap each other if vg object just propagate the alpha to child layer
it will be applied twice in overlapped area.
Even if the child layer does not have alpha transparency, parent alpha is applied to each child.

Test Plan: N/A

Reviewers: Hermet, smohanty

Reviewed By: Hermet

Subscribers: cedric, #reviewers, kimcinoo, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D9072

Change-Id: I67e1fd3781050fc4427011865f8801998b530e52

src/lib/ector/ector_surface.eo
src/lib/ector/software/ector_software_private.h
src/lib/ector/software/ector_software_surface.c
src/lib/ector/software/ector_software_surface.eo
src/lib/evas/canvas/efl_canvas_vg_container.c
src/lib/evas/canvas/efl_canvas_vg_object.c
src/lib/evas/canvas/evas_vg_private.h

index 0dcfff2..67a4813 100644 (file)
@@ -21,5 +21,15 @@ mixin @beta Ector.Surface extends Ector.Buffer
             @in type: const(Efl.Class); [[Efl class]] /* FIXME: Should probably be a more restricted type */
          }
       }
+      draw_image @pure_virtual {
+         [[ Draw image's buffer to surface buffer. ]]
+         params {
+            @in image: Ector.Buffer; [[Image buffer]]
+            @in x: int; [[Buffer position x]]
+            @in y: int; [[Buffer position y]]
+            @in alpha: int; [[Buffer alpha value]]
+         }
+         return: bool; [[True if drawing was successful]]
+      }
    }
 }
index 34ea003..62d1c3f 100644 (file)
@@ -5,6 +5,7 @@
 #include "sw_ft_raster.h"
 #include "sw_ft_stroker.h"
 #include "../ector_private.h"
+#include "draw.h"
 
 typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data;
 typedef struct _Ector_Software_Thread Ector_Software_Thread;
index 10cf996..08a2786 100644 (file)
@@ -245,5 +245,31 @@ _ector_software_surface_ector_surface_reference_point_set(Eo *obj EINA_UNUSED,
    pd->y = y;
 }
 
+static Eina_Bool
+_ector_software_surface_ector_surface_draw_image(Eo *obj EINA_UNUSED,
+                                                 Ector_Software_Surface_Data *pd,
+                                                 Ector_Buffer *buffer, int x, int y, int alpha)
+{
+   if (!buffer || !pd->rasterizer || !pd->rasterizer->fill_data.raster_buffer->pixels.u32)
+     return EINA_FALSE;
+
+   Ector_Software_Buffer_Base_Data *bd = efl_data_scope_get(buffer, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN);
+   const int pix_stride = pd->rasterizer->fill_data.raster_buffer->stride / 4;
+
+   uint32_t *src = bd->pixels.u32;
+   for (unsigned int local_y = 0; local_y <  bd->generic->h; local_y++)
+     {
+        uint32_t *dst = pd->rasterizer->fill_data.raster_buffer->pixels.u32 + (x + ((local_y + y) * pix_stride));
+        for (unsigned int local_x = 0; local_x <  bd->generic->w; local_x++)
+          {
+             *src = draw_mul_256(alpha, *src);
+             int inv_alpha = 255 - ((*src) >> 24);
+             *dst = *src + draw_mul_256(inv_alpha, *dst);
+             dst++;
+             src++;
+          }
+     }
+   return EINA_TRUE;
+}
 #include "ector_software_surface.eo.c"
 #include "ector_renderer_software.eo.c"
index 77d6db2..6212640 100644 (file)
@@ -6,6 +6,7 @@ class @beta Ector.Software.Surface extends Ector.Software.Buffer implements Ecto
    implements {
       Ector.Surface.renderer_factory_new;
       Ector.Surface.reference_point { set; }
+      Ector.Surface.draw_image;
       Efl.Object.destructor;
       Efl.Object.constructor;
    }
index 5f92e62..4d11e0b 100644 (file)
@@ -240,6 +240,9 @@ static void
 _efl_canvas_vg_container_efl_object_destructor(Eo *obj,
                                                Efl_Canvas_Vg_Container_Data *pd)
 {
+   if (pd->blend_pixels) free(pd->blend_pixels);
+   if (pd->blend_buffer) efl_unref(pd->blend_buffer);
+
    //Destroy mask surface
    if (pd->mask.buffer) efl_unref(pd->mask.buffer);
    if (pd->mask.pixels) free(pd->mask.pixels);
index 245685f..e8c1524 100644 (file)
@@ -386,22 +386,66 @@ _efl_canvas_vg_object_efl_object_finalize(Eo *obj, Efl_Canvas_Vg_Object_Data *pd
 static void
 _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
                 void *engine, void *output, void *context, Efl_VG *node,
-                Eina_Array *clips, Eina_Bool do_async)
+                Eina_Array *clips, int w, int h, Ector_Surface *ector, Eina_Bool do_async)
 {
    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);
+        Efl_VG *child;
+        Eina_List *l;
+        Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS);
 
         if (cd->mask.target) return;   //Don't draw mask itself.
 
-        Efl_VG *child;
-        Eina_List *l;
+        int alpha = 255;
+        efl_gfx_color_get(node, NULL, NULL, NULL, &alpha);
+
+        if (alpha < 255)
+          {
+             // Reuse buffer
+             if (!cd->blend_pixels)
+               cd->blend_pixels = calloc(w * h, sizeof(uint32_t*));
+             else
+               memset(cd->blend_pixels, 0, sizeof(uint32_t) * (w * h));
+
+             if (!cd->blend_buffer)
+               {
+                  cd->blend_buffer = ENFN->ector_buffer_new(ENC, obj->layer->evas->evas,
+                                                                    w, h,
+                                                                    EFL_GFX_COLORSPACE_ARGB8888,
+                                                                    ECTOR_BUFFER_FLAG_DRAWABLE |
+                                                                    ECTOR_BUFFER_FLAG_CPU_READABLE |
+                                                                    ECTOR_BUFFER_FLAG_CPU_WRITABLE);
+                  ector_buffer_pixels_set(cd->blend_buffer, cd->blend_pixels,
+                                          w, h, 0,
+                                          EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE);
+               }
+
+             // Buffer change
+             ector_buffer_pixels_set(ector, cd->blend_pixels,
+                                     w, h, 0,
+                                     EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE);
+             ector_surface_reference_point_set(ector, 0,0);
+
+             // Draw child node to changed buffer
+             EINA_LIST_FOREACH(cd->children, l, child)
+                _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+
+             // Re-set original surface
+             ENFN->ector_begin(engine, output, context, ector, 0, 0, EINA_FALSE, do_async);
+
+             // Draw buffer to original surface.(Ector_Surface)
+             ector_surface_draw_image(ector, cd->blend_buffer, 0, 0, alpha);
 
-        EINA_LIST_FOREACH(cd->children, l, child)
-          _evas_vg_render(obj, pd, engine, output, context, child, clips, do_async);
+          }
+        else
+          {
+             if (cd->blend_pixels) free(cd->blend_pixels);
+             if (cd->blend_buffer) efl_unref(cd->blend_buffer);
+             EINA_LIST_FOREACH(cd->children, l, child)
+                _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+          }
      }
    else
      {
@@ -451,6 +495,7 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd
                    engine, buffer,
                    context, root,
                    NULL,
+                   w, h, ector,
                    do_async);
 
    ENFN->image_dirty_region(engine, buffer, 0, 0, w, h);
index e241392..e9fba36 100644 (file)
@@ -97,6 +97,10 @@ struct _Efl_Canvas_Vg_Container_Data
    //Masking feature.
    Efl_Canvas_Vg_Node *mask_src;         //Mask Source
    Vg_Mask mask;                         //Mask source data
+
+   //Layer transparency feature. This buffer is only valid when the layer has transparency.
+   Ector_Buffer *blend_buffer;
+   void *blend_pixels;
 };
 
 struct _Efl_Canvas_Vg_Gradient_Data