From d8301fae6e650e179cd3046874faabe6909f6531 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 9 Dec 2013 14:46:12 +0900 Subject: [PATCH] Evas: Add support for Alpha buffers Evas is an RGBA only engine, BUT we also use some alpha masks, especially in the font rendering pipeline. This commit adds basic support for alpha buffer operations (blend and copy). RGBA_Image can then point to either alpha-only data, if its colorspace is grey. --- src/Makefile_Evas.am | 1 + src/lib/evas/common/evas_alpha_main.c | 90 ++++++++++++++++++++++ src/lib/evas/common/evas_blend_private.h | 3 + src/lib/evas/common/evas_image_data.c | 24 +++++- src/lib/evas/include/evas_common_private.h | 21 +++-- 5 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 src/lib/evas/common/evas_alpha_main.c diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index c94e54ea01..f74a737439 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -127,6 +127,7 @@ lib/evas/common/evas_op_add_main_.c \ lib/evas/common/evas_op_sub_main_.c \ lib/evas/common/evas_op_mask_main_.c \ lib/evas/common/evas_op_mul_main_.c \ +lib/evas/common/evas_alpha_main.c \ lib/evas/common/evas_blend_main.c \ lib/evas/common/evas_blit_main.c \ lib/evas/common/evas_convert_color.c \ diff --git a/src/lib/evas/common/evas_alpha_main.c b/src/lib/evas/common/evas_alpha_main.c new file mode 100644 index 0000000000..6bd654cec1 --- /dev/null +++ b/src/lib/evas/common/evas_alpha_main.c @@ -0,0 +1,90 @@ +#include "evas_common_private.h" +#include "evas_blend_private.h" + +/** default op: d = d*(1-sa) + s */ +static void +_alpha_func_blend(DATA8 *src, DATA8 *dst, int len) +{ + int k; + + EINA_SAFETY_ON_NULL_RETURN(src); + EINA_SAFETY_ON_NULL_RETURN(dst); + + for (k = len; k; k--) + { + int val = (*dst * (255 - *src)) / 255 + *src; + *dst++ = val; + src++; + } +} + +/** d = s */ +static void +_alpha_func_copy(DATA8 *src, DATA8 *dst, int len) +{ + EINA_SAFETY_ON_NULL_RETURN(src); + EINA_SAFETY_ON_NULL_RETURN(dst); + + memcpy(dst, src, len); +} + +/** d = d*s */ +static void +_alpha_func_mul(DATA8 *src, DATA8 *dst, int len) +{ + int k; + + EINA_SAFETY_ON_NULL_RETURN(src); + EINA_SAFETY_ON_NULL_RETURN(dst); + + for (k = len; k; k--) + { + int val = (*dst * *src) / 255; + *dst++ = val; + src++; + } +} + + +#if 0 +// Reference ops. In case of alpha, s == sa. +EVAS_RENDER_BLEND = 0, /**< default op: d = d*(1-sa) + s */ +EVAS_RENDER_BLEND_REL = 1, /**< d = d*(1 - sa) + s*da */ +EVAS_RENDER_COPY = 2, /**< d = s */ +EVAS_RENDER_COPY_REL = 3, /**< d = s*da */ +EVAS_RENDER_ADD = 4, /* d = d + s */ +EVAS_RENDER_ADD_REL = 5, /**< d = d + s*da */ +EVAS_RENDER_SUB = 6, /**< d = d - s */ +EVAS_RENDER_SUB_REL = 7, /* d = d - s*da */ +EVAS_RENDER_TINT = 8, /**< d = d*s + d*(1 - sa) + s*(1 - da) */ +EVAS_RENDER_TINT_REL = 9, /**< d = d*(1 - sa + s) */ +EVAS_RENDER_MASK = 10, /**< d = d*sa */ +EVAS_RENDER_MUL = 11, /**< d = d*s */ +#endif + +Alpha_Gfx_Func +evas_common_alpha_func_get(int op) +{ + INF("Requesting alpha function with OP %d", op); + switch (op) + { + case EVAS_RENDER_BLEND: + return _alpha_func_blend; +// case EVAS_RENDER_BLEND_REL: + case EVAS_RENDER_COPY: + return _alpha_func_copy; +// case EVAS_RENDER_COPY_REL: +// case EVAS_RENDER_ADD: +// case EVAS_RENDER_ADD_REL: +// case EVAS_RENDER_SUB: +// case EVAS_RENDER_SUB_REL: +// case EVAS_RENDER_TINT: +// case EVAS_RENDER_TINT_REL: + case EVAS_RENDER_MASK: + case EVAS_RENDER_MUL: + return _alpha_func_mul; + default: + ERR("Not implemented yet."); + return NULL; + } +} diff --git a/src/lib/evas/common/evas_blend_private.h b/src/lib/evas/common/evas_blend_private.h index 1d14951da1..00291981bf 100644 --- a/src/lib/evas/common/evas_blend_private.h +++ b/src/lib/evas/common/evas_blend_private.h @@ -27,5 +27,8 @@ RGBA_Gfx_Pt_Func evas_common_gfx_func_composite_pixel_color_pt_get (Image_ RGBA_Gfx_Pt_Func evas_common_gfx_func_composite_mask_color_pt_get (DATA32 col, RGBA_Image *dst, int op); RGBA_Gfx_Pt_Func evas_common_gfx_func_composite_pixel_mask_pt_get (Image_Entry_Flags src_flags, RGBA_Image *dst, int op); +/* Alpha/mask functions */ +Alpha_Gfx_Func evas_common_alpha_func_get (int op); + #endif /* _EVAS_BLEND_PRIVATE_H */ diff --git a/src/lib/evas/common/evas_image_data.c b/src/lib/evas/common/evas_image_data.c index fe808323e6..8971867c25 100644 --- a/src/lib/evas/common/evas_image_data.c +++ b/src/lib/evas/common/evas_image_data.c @@ -33,6 +33,13 @@ evas_common_rgba_image_from_data(Image_Entry* ie_dst, int w, int h, DATA32 *imag dst->cs.data = image_data; dst->cs.no_free = 1; break; + case EVAS_COLORSPACE_GRY8: + dst->cache_entry.w = w; + dst->cache_entry.h = h; + dst->mask.data = (DATA8 *) image_data; + dst->mask.no_free = 1; + dst->cache_entry.flags.alpha = 1; + break; default: abort(); break; @@ -65,6 +72,11 @@ evas_common_rgba_image_from_copied_data(Image_Entry* ie_dst, int w, int h, DATA3 if (image_data && (dst->cs.data)) memcpy(dst->cs.data, image_data, dst->cache_entry.h * sizeof(unsigned char*) * 2); break; + case EVAS_COLORSPACE_GRY8: + dst->cache_entry.flags.alpha = 1; + if (image_data) + memcpy(dst->mask.data, image_data, w * h * sizeof(DATA8)); + break; default: abort(); break; @@ -104,17 +116,25 @@ int evas_common_rgba_image_colorspace_set(Image_Entry* ie_dst, int cspace) { RGBA_Image *dst = (RGBA_Image *) ie_dst; + Eina_Bool change = (dst->cache_entry.space != cspace); switch (cspace) { case EVAS_COLORSPACE_ARGB8888: + case EVAS_COLORSPACE_GRY8: if (dst->cs.data) { if (!dst->cs.no_free) free(dst->cs.data); dst->cs.data = NULL; dst->cs.no_free = 0; } - break; + if (change && dst->image.data) + { + if (!dst->image.no_free) free(dst->image.data); + dst->image.data = NULL; + dst->image.no_free = 0; + } + break; case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: @@ -136,7 +156,7 @@ evas_common_rgba_image_colorspace_set(Image_Entry* ie_dst, int cspace) } dst->cs.data = calloc(1, dst->cache_entry.h * sizeof(unsigned char *) * 2); dst->cs.no_free = 0; - break; + break; default: abort(); break; diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index e75cd93290..83c027208f 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -424,7 +424,7 @@ typedef void (*RGBA_Gfx_Pt_Func) (DATA32 src, DATA8 mask, DATA32 col, DATA32 *ds typedef void (*Gfx_Func_Copy) (DATA32 *src, DATA32 *dst, int len); typedef void (*Gfx_Func_Convert) (DATA32 *src, DATA8 *dst, int src_jump, int dst_jump, int w, int h, int dith_x, int dith_y, DATA8 *pal); - +typedef void (*Alpha_Gfx_Func) (DATA8 *src, DATA8 *dst, int len); typedef void (*Evas_Render_Done_Cb)(void *); @@ -801,11 +801,20 @@ struct _RGBA_Image Eina_Bool dirty : 1; } cs; - /* RGBA stuff */ - struct { - DATA32 *data; - Eina_Bool no_free : 1; - } image; + union + { + /* RGBA stuff */ + struct { + DATA32 *data; + Eina_Bool no_free : 1; + } image; + + /* Alpha Mask stuff */ + struct { + DATA8 *data; + Eina_Bool no_free : 1; + } mask; + }; struct { SLK(lock);