forked from enlightenment/efl
ector: Fix precomp layer rendering issue when it has alpha value
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
This commit is contained in:
parent
c27c469204
commit
c7b1a40b5e
|
@ -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]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -236,6 +236,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);
|
||||
|
|
|
@ -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, do_async);
|
||||
_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);
|
||||
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -94,6 +94,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
|
||||
|
|
Loading…
Reference in New Issue