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.
This commit is contained in:
Jean-Philippe Andre 2013-12-09 14:46:12 +09:00
parent 71c7d0e9ad
commit d8301fae6e
5 changed files with 131 additions and 8 deletions

View File

@ -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 \

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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);