Evas filters: Use Ector.Buffer instead of RGBA_Image

This is a major refactoring of the evas filters submodule.

Use Ector.Buffer and the map/unmap methods instead of directly
accessing image buffers with RGBA_Image. RGBA_Image is still
used under the hood, for two reasons:
 - Required for the final output (blend onto Evas itself)
 - Required for the scaling routines

FIXME:
 - Breaks proxy support (ie. all kind of texturing).
 - This breaks filters support for the GL engine.
This commit is contained in:
Jean-Philippe Andre 2015-12-09 10:45:53 +09:00
parent e3af2783ff
commit 57902fffd3
17 changed files with 742 additions and 954 deletions

View File

@ -242,7 +242,8 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
// Request rendering from the object itself (child class) // Request rendering from the object itself (child class)
evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b); evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b);
eo_do(eo_obj, evas_filter_input_render(filter, drawctx, l, r, t, b, do_async)); eo_do(eo_obj, ok = evas_filter_input_render(filter, drawctx, l, r, t, b, do_async));
if (!ok) ERR("Filter input render failed.");
ENFN->context_free(ENDT, drawctx); ENFN->context_free(ENDT, drawctx);

View File

@ -21,25 +21,28 @@
#endif #endif
#include "evas_filter_private.h" #include "evas_filter_private.h"
#include <Ector.h>
#include <software/Ector_Software.h>
#include "evas_ector_buffer.eo.h"
#define _assert(a) if (!(a)) CRI("Failed on %s", #a); #define _assert(a) if (!(a)) CRI("Failed on %s", #a);
static void _buffer_free(Evas_Filter_Buffer *fb); static void _buffer_free(Evas_Filter_Buffer *fb);
static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd); static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
static RGBA_Image *_rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data); static Ector_Buffer* _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data);
#define DRAW_COLOR_SET(r, g, b, a) do { cmd->draw.R = r; cmd->draw.G = g; cmd->draw.B = b; cmd->draw.A = a; } while (0) #define DRAW_COLOR_SET(r, g, b, a) do { cmd->draw.R = r; cmd->draw.G = g; cmd->draw.B = b; cmd->draw.A = a; } while (0)
#define DRAW_CLIP_SET(_x, _y, _w, _h) do { cmd->draw.clip.x = _x; cmd->draw.clip.y = _y; cmd->draw.clip.w = _w; cmd->draw.clip.h = _h; } while (0) #define DRAW_CLIP_SET(_x, _y, _w, _h) do { cmd->draw.clip.x = _x; cmd->draw.clip.y = _y; cmd->draw.clip.w = _w; cmd->draw.clip.h = _h; } while (0)
#define DRAW_FILL_SET(fmode) do { cmd->draw.fillmode = fmode; } while (0) #define DRAW_FILL_SET(fmode) do { cmd->draw.fillmode = fmode; } while (0)
typedef struct _Evas_Filter_Thread_Command Evas_Filter_Thread_Command; static inline void *
struct _Evas_Filter_Thread_Command _evas_image_get(Ector_Buffer *buf)
{ {
Evas_Filter_Context *ctx; void *image = NULL;
RGBA_Image *src, *mask, *dst; if (!buf) return NULL;
Evas_Filter_Apply_Func func; eo_do(buf, evas_ector_buffer_engine_image_get(NULL, &image));
}; return image;
}
/* Main functions */ /* Main functions */
@ -67,6 +70,11 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async)
* better and implement filters direcly with shaders. * better and implement filters direcly with shaders.
*/ */
ctx->gl_engine = (evas->engine.func->gl_surface_read_pixels != NULL); ctx->gl_engine = (evas->engine.func->gl_surface_read_pixels != NULL);
if (ctx->gl_engine)
{
// FIXME!!!
CRI("gl support not implemented");
}
return ctx; return ctx;
} }
@ -92,45 +100,22 @@ evas_filter_context_clear(Evas_Filter_Context *ctx)
// Note: don't reset post_run, as it it set by the client // Note: don't reset post_run, as it it set by the client
} }
static void
_backing_free(Evas_Filter_Context *ctx, RGBA_Image *im)
{
if (!im) return;
if (!ctx->gl_engine)
{
if (!ctx->async)
ENFN->image_free(ENDT, im);
else
evas_unref_queue_image_put(ctx->evas, &im->cache_entry);
}
else
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&im->cache_entry);
else
#endif
evas_cache_image_drop(&im->cache_entry);
}
}
static void static void
_filter_buffer_backing_free(Evas_Filter_Buffer *fb) _filter_buffer_backing_free(Evas_Filter_Buffer *fb)
{ {
if (!fb) return; if (!fb || !fb->buffer) return;
eo_del(fb->buffer);
_backing_free(fb->ctx, fb->backing); fb->buffer = NULL;
if (fb->glimage)
fb->ENFN->image_free(fb->ENDT, fb->glimage);
fb->backing = NULL;
fb->glimage = NULL;
} }
/* GL engine stuff: read-back from texture */ /* GL engine stuff: read-back from texture */
static Eina_Bool static Eina_Bool
_filter_buffer_glimage_pixels_read(Evas_Filter_Buffer *fb, void *glimage) _filter_buffer_glimage_pixels_read(Evas_Filter_Buffer *fb EINA_UNUSED, void *glimage EINA_UNUSED)
{ {
CRI("not implemented");
return 0;
#if 0
Eina_Bool ok; Eina_Bool ok;
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
@ -143,8 +128,8 @@ _filter_buffer_glimage_pixels_read(Evas_Filter_Buffer *fb, void *glimage)
EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ENFN->gl_surface_read_pixels, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ENFN->gl_surface_read_pixels, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ENFN->gl_surface_unlock, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(fb->ENFN->gl_surface_unlock, EINA_FALSE);
fb->backing = _rgba_image_alloc(fb, NULL); fb->buffer = _ector_buffer_create(fb, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(fb->backing, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(fb->buffer, EINA_FALSE);
ok = fb->ENFN->gl_surface_lock(fb->ENDT, glimage); ok = fb->ENFN->gl_surface_lock(fb->ENDT, glimage);
if (!ok) if (!ok)
@ -163,13 +148,18 @@ _filter_buffer_glimage_pixels_read(Evas_Filter_Buffer *fb, void *glimage)
ok &= fb->ENFN->gl_surface_unlock(fb->ENDT, glimage); ok &= fb->ENFN->gl_surface_unlock(fb->ENDT, glimage);
return ok; return ok;
#endif
} }
/** @hidden private render proxy objects */ /** @hidden private render proxy objects */
void void
evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx EINA_UNUSED, Eo *eo_obj EINA_UNUSED,
Eina_Bool do_async) Eina_Bool do_async EINA_UNUSED)
{ {
CRI("not implemented");
return;
#if 0
Evas_Object_Protected_Data *source; Evas_Object_Protected_Data *source;
Evas_Object_Protected_Data *obj; Evas_Object_Protected_Data *obj;
Evas_Filter_Buffer *fb; Evas_Filter_Buffer *fb;
@ -208,6 +198,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
fb->alpha_only = EINA_FALSE; fb->alpha_only = EINA_FALSE;
XDBG("Source has dimensions %dx%d (buffer %d)", fb->w, fb->h, fb->id); XDBG("Source has dimensions %dx%d (buffer %d)", fb->w, fb->h, fb->id);
} }
#endif
} }
void void
@ -257,63 +248,43 @@ _buffer_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only)
return fb; return fb;
} }
static RGBA_Image * static Ector_Buffer *
_rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data) _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data)
{ {
Evas_Colorspace cspace; Evas_Colorspace cspace;
RGBA_Image *image; Image_Entry *ie;
size_t sz;
cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888; // FIXME: We still rely on evas image structs (scaling and target render)
if (!fb->ctx->gl_engine) // This should be fixed by implementing full support in ector
// Note: dropped support for cserve2, that was not needed anyway
cspace = fb->alpha_only ? E_ALPHA : E_ARGB;
#if 0
// ideal code
return fb->ENFN->ector_buffer_new(fb->ENDT, fb->ctx->evas->evas,
data, fb->w, fb->h, 0,
cspace, EINA_TRUE, 0, 0, 0, 0,
ECTOR_BUFFER_FLAG_CPU_READABLE |
ECTOR_BUFFER_FLAG_CPU_WRITABLE);
#endif
if (data)
{ {
if (!data) // no copy
{ ie = evas_cache_image_data(evas_common_image_cache_get(), fb->w, fb->h,
image = fb->ENFN->image_new_from_copied_data data, EINA_TRUE, cspace);
(fb->ENDT, fb->w, fb->h, NULL, EINA_TRUE, cspace); if (!ie) return NULL;
}
else
{
image = fb->ENFN->image_new_from_data
(fb->ENDT, fb->w, fb->h, data, EINA_TRUE, cspace);
}
} }
else else
{ {
// FIXME: Directly calling the alloc functions since we want to use sw surfaces. // alloc buffer
ie = evas_cache_image_copied_data(evas_common_image_cache_get(), fb->w, fb->h,
if (!data) NULL, EINA_TRUE, cspace);
{ if (!ie) return NULL;
#ifdef EVAS_CSERVE2 data = ((RGBA_Image *) ie)->image.data;
if (evas_cserve2_use_get()) memset(data, 0, fb->w * fb->h * (fb->alpha_only ? 1 : 4));
image = (RGBA_Image *) evas_cache2_image_copied_data
(evas_common_image_cache2_get(), fb->w, fb->h, NULL, EINA_TRUE, cspace);
else
#endif
image = (RGBA_Image *) evas_cache_image_copied_data
(evas_common_image_cache_get(), fb->w, fb->h, NULL, EINA_TRUE, cspace);
}
else
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
image = (RGBA_Image *) evas_cache2_image_data
(evas_common_image_cache2_get(), fb->w, fb->h, data, EINA_TRUE, cspace);
else
#endif
image = (RGBA_Image *) evas_cache_image_data
(evas_common_image_cache_get(), fb->w, fb->h, data, EINA_TRUE, cspace);
}
} }
if (!image) return NULL; return fb->ENFN->ector_buffer_wrap(fb->ENDT, fb->ctx->evas->evas, ie);
if (fb->alpha_only)
sz = image->cache_entry.w * image->cache_entry.h * sizeof(DATA8);
else
sz = image->cache_entry.w * image->cache_entry.h * sizeof(DATA32);
if (!data) memset(image->image.data, 0, sz);
return image;
} }
Eina_Bool Eina_Bool
@ -404,7 +375,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
EINA_LIST_FOREACH(ctx->buffers, li, fb) EINA_LIST_FOREACH(ctx->buffers, li, fb)
{ {
if (fb->backing || fb->source || fb->glimage) if (fb->buffer || fb->source || fb->glimage)
continue; continue;
if (!fb->w && !fb->h) if (!fb->w && !fb->h)
@ -413,10 +384,10 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
continue; continue;
} }
fb->backing = _rgba_image_alloc(fb, NULL); fb->buffer = _ector_buffer_create(fb, NULL);
XDBG("Allocating buffer #%d of size %ux%u %s", XDBG("Allocated buffer #%d of size %ux%u %s: %p",
fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba"); fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba", fb->buffer);
if (!fb->backing) goto alloc_fail; if (!fb->buffer) goto alloc_fail;
} }
return EINA_TRUE; return EINA_TRUE;
@ -457,35 +428,29 @@ _filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data,
if (w <= 0 || h <= 0) if (w <= 0 || h <= 0)
return EINA_FALSE; return EINA_FALSE;
EINA_SAFETY_ON_FALSE_RETURN_VAL(fb->backing == NULL, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(fb->buffer == NULL, EINA_FALSE);
// TODO: Check input parameters? // TODO: Check input parameters?
fb->alpha_only = alpha_only; fb->alpha_only = alpha_only;
fb->w = w; fb->w = w;
fb->h = h; fb->h = h;
fb->backing = _rgba_image_alloc(fb, data); fb->buffer = _ector_buffer_create(fb, data);
return (fb->backing != NULL); return (fb->buffer != NULL);
} }
int static int
evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image) _filter_buffer_new_from_evas_surface(Evas_Filter_Context *ctx, void *image)
{ {
Evas_Filter_Buffer *fb; Evas_Filter_Buffer *fb;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
image = ENFN->image_ref(ENDT, image);
EINA_SAFETY_ON_NULL_RETURN_VAL(image, -1);
fb = calloc(1, sizeof(Evas_Filter_Buffer)); fb = calloc(1, sizeof(Evas_Filter_Buffer));
if (!fb) return -1; if (!fb) return -1;
fb->id = ++(ctx->last_buffer_id); fb->id = ++(ctx->last_buffer_id);
fb->ctx = ctx; fb->ctx = ctx;
if (!ctx->gl_engine) fb->buffer = ENFN->ector_buffer_wrap(ENDT, ctx->evas->evas, image);
fb->backing = image;
else
fb->glimage = image;
ENFN->image_size_get(ENDT, image, &fb->w, &fb->h); ENFN->image_size_get(ENDT, image, &fb->w, &fb->h);
fb->alpha_only = (ENFN->image_colorspace_get(ENDT, image) fb->alpha_only = (ENFN->image_colorspace_get(ENDT, image)
== EVAS_COLORSPACE_GRY8); == EVAS_COLORSPACE_GRY8);
@ -544,12 +509,12 @@ _filter_buffer_get(Evas_Filter_Context *ctx, int bufid)
void * void *
evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid) evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid)
{ {
Evas_Filter_Buffer *buffer; Evas_Filter_Buffer *fb;
buffer = _filter_buffer_get(ctx, bufid); fb = _filter_buffer_get(ctx, bufid);
if (!buffer) return NULL; if (!fb) return NULL;
return buffer->backing; return _evas_image_get(fb->buffer);
} }
void * void *
@ -557,15 +522,10 @@ evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid)
{ {
Evas_Filter_Buffer *fb; Evas_Filter_Buffer *fb;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
fb = _filter_buffer_get(ctx, bufid); fb = _filter_buffer_get(ctx, bufid);
if (!fb) return NULL; if (!fb) return NULL;
if (ctx->gl_engine) return fb->ENFN->image_ref(fb->ENDT, _evas_image_get(fb->buffer));
return fb->ENFN->image_ref(fb->ENDT, fb->glimage);
else
return fb->ENFN->image_ref(fb->ENDT, fb->backing);
} }
Eina_Bool Eina_Bool
@ -577,11 +537,11 @@ evas_filter_buffer_backing_release(Evas_Filter_Context *ctx,
if (ctx->async) if (ctx->async)
evas_unref_queue_image_put(ctx->evas, stolen_buffer); evas_unref_queue_image_put(ctx->evas, stolen_buffer);
else if (ctx->gl_engine)
ctx->post_run.buffers_to_free =
eina_list_append(ctx->post_run.buffers_to_free, stolen_buffer);
else else
_backing_free(ctx, stolen_buffer); {
ctx->post_run.buffers_to_free =
eina_list_append(ctx->post_run.buffers_to_free, stolen_buffer);
}
return EINA_TRUE; return EINA_TRUE;
} }
@ -1345,12 +1305,6 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx,
return -1; return -1;
} }
if (in->alpha_only != out->alpha_only)
{
CRI("Incompatible buffer formats");
return -1;
}
cmd = _command_new(ctx, EVAS_FILTER_MODE_TRANSFORM, in, NULL, out); cmd = _command_new(ctx, EVAS_FILTER_MODE_TRANSFORM, in, NULL, out);
if (!cmd) return -1; if (!cmd) return -1;
@ -1372,7 +1326,7 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
ctx->target.bufid = evas_filter_buffer_image_new(ctx, surface); ctx->target.bufid = _filter_buffer_new_from_evas_surface(ctx, surface);
ctx->target.x = x; ctx->target.x = x;
ctx->target.y = y; ctx->target.y = y;
ctx->target.clip_use = ENFN->context_clip_get ctx->target.clip_use = ENFN->context_clip_get
@ -1391,6 +1345,7 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask); ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
ctx->target.mask = mask; ctx->target.mask = mask;
#if 0
if (ctx->gl_engine) if (ctx->gl_engine)
{ {
// Since GL has sync rendering, draw_context is safe to keep around // Since GL has sync rendering, draw_context is safe to keep around
@ -1410,6 +1365,7 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
XDBG("Set target as #%d (%p) and output #%d (%p, gl %p)", XDBG("Set target as #%d (%p) and output #%d (%p, gl %p)",
ctx->target.bufid, surface, fb->id, fb->backing, fb->glimage); ctx->target.bufid, surface, fb->id, fb->backing, fb->glimage);
} }
#endif
return EINA_TRUE; return EINA_TRUE;
} }
@ -1418,7 +1374,7 @@ static Eina_Bool
_filter_target_render(Evas_Filter_Context *ctx) _filter_target_render(Evas_Filter_Context *ctx)
{ {
Evas_Filter_Buffer *src, *dst; Evas_Filter_Buffer *src, *dst;
void *drawctx, *image, *surface; void *drawctx, *image = NULL, *surface = NULL;
int cx, cy, cw, ch; int cx, cy, cw, ch;
Eina_Bool use_clip = EINA_FALSE; Eina_Bool use_clip = EINA_FALSE;
@ -1429,13 +1385,8 @@ _filter_target_render(Evas_Filter_Context *ctx)
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
if (!ctx->gl_engine) #if 0
{ if (ctx->gl_engine)
drawctx = ENFN->context_new(ENDT);
surface = dst->backing;
image = src->backing;
}
else
{ {
drawctx = ctx->target.context; drawctx = ctx->target.context;
surface = dst->glimage; surface = dst->glimage;
@ -1456,9 +1407,18 @@ _filter_target_render(Evas_Filter_Context *ctx)
} }
image = src->glimage; image = src->glimage;
} }
else
#endif
{
drawctx = ENFN->context_new(ENDT);
image = _evas_image_get(src->buffer);
surface = _evas_image_get(dst->buffer);
}
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
// FIXME: Use ector buffer RENDERER here
if (ctx->target.clip_use) if (ctx->target.clip_use)
{ {
use_clip = ENFN->context_clip_get(ENDT, drawctx, &cx, &cy, &cw, &ch); use_clip = ENFN->context_clip_get(ENDT, drawctx, &cx, &cy, &cw, &ch);
@ -1511,12 +1471,10 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid,
{ {
Eina_Bool async_unref; Eina_Bool async_unref;
Evas_Filter_Buffer *fb; Evas_Filter_Buffer *fb;
void *surface; void *surface = NULL;
fb = _filter_buffer_get(ctx, bufid); fb = _filter_buffer_get(ctx, bufid);
if (!fb) return EINA_FALSE; surface = _evas_image_get(fb->buffer);
surface = fb->backing;
if (!surface) return EINA_FALSE; if (!surface) return EINA_FALSE;
if (!ctx->gl_engine) if (!ctx->gl_engine)
@ -1771,10 +1729,7 @@ end:
DEBUG_TIME_END(); DEBUG_TIME_END();
EINA_LIST_FREE(ctx->post_run.buffers_to_free, buffer) EINA_LIST_FREE(ctx->post_run.buffers_to_free, buffer)
{ ENFN->image_free(ENDT, buffer);
if (ctx->gl_engine)
ENFN->image_free(ENDT, buffer);
}
return ok; return ok;
} }

View File

@ -1,33 +1,37 @@
#include "evas_filter.h" #include "evas_filter.h"
#include "evas_filter_private.h" #include "evas_filter_private.h"
#include "evas_blend_private.h" #include "evas_blend_private.h"
#include "ector_buffer.h"
#include "draw.h" #include "draw.h"
// FIXME: This should all be based on ector renderer
// Use a better formula than R+G+B for rgba to alpha conversion (RGB to YCbCr) // Use a better formula than R+G+B for rgba to alpha conversion (RGB to YCbCr)
#define RGBA2ALPHA_WEIGHTED 1 #define RGBA2ALPHA_WEIGHTED 1
typedef Eina_Bool (*image_draw_func) (void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async); typedef Eina_Bool (*draw_func) (void *data, void *context, const void *src_map, unsigned int src_stride, void *dst_map, unsigned int dst_stride, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async);
static Eina_Bool _mapped_blend(void *data, void *drawctx, void *in, void *out, Evas_Filter_Fill_Mode fillmode, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, image_draw_func image_draw); static Eina_Bool _mapped_blend(void *data, void *drawctx, const void *src_map, unsigned int src_stride, void *dst_map, unsigned int dst_stride, Evas_Filter_Fill_Mode fillmode, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, draw_func image_draw);
struct Filter_Blend_Draw_Context struct Filter_Blend_Draw_Context
{ {
Efl_Gfx_Render_Op rop; Efl_Gfx_Render_Op rop;
DATA32 color; uint32_t color;
}; };
#define LINELEN(stride, ptr) (stride / (sizeof(*ptr)))
static Eina_Bool static Eina_Bool
_image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context, _image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context,
void *surface, void *image, const void *src_map, unsigned int src_stride,
void *dst_map, unsigned int dst_stride,
int src_x, int src_y, int src_w, int src_h, int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h, int dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED, int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED) Eina_Bool do_async EINA_UNUSED)
{ {
struct Filter_Blend_Draw_Context *dc = context; struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image; const uint8_t *srcdata = src_map;
RGBA_Image *dst = surface; uint8_t *dstdata = dst_map;
DATA8* srcdata = src->image.data8;
DATA8* dstdata = dst->image.data8;
Alpha_Gfx_Func func; Alpha_Gfx_Func func;
int y, sw, dw; int y, sw, dw;
@ -36,8 +40,8 @@ _image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context,
func = efl_draw_alpha_func_get(dc->rop, EINA_FALSE); func = efl_draw_alpha_func_get(dc->rop, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
sw = src->cache_entry.w; sw = LINELEN(src_stride, srcdata);
dw = dst->cache_entry.w; dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw; srcdata += src_y * sw;
dstdata += dst_y * dw; dstdata += dst_y * dw;
@ -53,28 +57,26 @@ _image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context,
static Eina_Bool static Eina_Bool
_image_draw_cpu_alpha2rgba(void *data EINA_UNUSED, void *context, _image_draw_cpu_alpha2rgba(void *data EINA_UNUSED, void *context,
void *surface, void *image, const void *src_map, unsigned int src_stride,
void *dst_map, unsigned int dst_stride,
int src_x, int src_y, int src_w, int src_h, int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h, int dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED, int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED) Eina_Bool do_async EINA_UNUSED)
{ {
struct Filter_Blend_Draw_Context *dc = context; struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image; uint8_t *srcdata = (uint8_t *) src_map;
RGBA_Image *dst = surface; uint32_t *dstdata = dst_map;
DATA8* srcdata = src->image.data8;
DATA32* dstdata = dst->image.data;
RGBA_Gfx_Func func; RGBA_Gfx_Func func;
int y, sw, dw; int y, sw, dw;
EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
func = evas_common_gfx_func_composite_mask_color_span_get func = evas_common_gfx_func_composite_mask_color_span_get(dc->color, 1, 1, _gfx_to_evas_render_op(dc->rop));
(dc->color, dst->cache_entry.flags.alpha, 1, dc->rop);
EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
sw = src->cache_entry.w; sw = LINELEN(src_stride, srcdata);
dw = dst->cache_entry.w; dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw; srcdata += src_y * sw;
dstdata += dst_y * dw; dstdata += dst_y * dw;
@ -88,122 +90,18 @@ _image_draw_cpu_alpha2rgba(void *data EINA_UNUSED, void *context,
return EINA_TRUE; return EINA_TRUE;
} }
static Eina_Bool
_filter_blend_cpu_generic_do(Evas_Filter_Command *cmd,
image_draw_func image_draw)
{
RGBA_Image *in, *out;
int sw, sh, dx, dy, dw, dh, sx, sy;
struct Filter_Blend_Draw_Context dc;
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
sx = 0;
sy = 0;
sw = in->cache_entry.w;
sh = in->cache_entry.h;
dx = cmd->draw.ox;
dy = cmd->draw.oy;
dw = out->cache_entry.w;
dh = out->cache_entry.h;
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return EINA_TRUE;
// Stretch if necessary.
/* NOTE: As of 2014/03/11, this will happen only with RGBA buffers, since
* only proxy sources may be scaled. So, we don't need an alpha scaling
* algorithm just now.
*/
if ((sw != dw || sh != dh) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
sw = dw;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
sh = dh;
BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, sw, sh);
BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
in = fb->backing;
}
dc.rop = cmd->draw.rop;
dc.color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
return _mapped_blend(cmd->ENDT, &dc, in, out, cmd->draw.fillmode,
sx, sy, sw, sh, dx, dy, dw, dh, image_draw);
}
static Eina_Bool
_image_draw_cpu_rgba2alpha(void *data EINA_UNUSED, void *context EINA_UNUSED,
void *surface, void *image,
int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
RGBA_Image *src = image;
RGBA_Image *dst = surface;
DATA32* srcdata = src->image.data;
DATA8* dstdata = dst->image.data8;
int x, y, sw, dw;
#if RGBA2ALPHA_WEIGHTED
const int WR = 299;
const int WG = 587;
const int WB = 114;
#else
const int WR = 1;
const int WG = 1;
const int WB = 1;
#endif
DEFINE_DIVIDER(WR + WG + WB);
EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
sw = src->cache_entry.w;
dw = dst->cache_entry.w;
srcdata += src_y * sw;
dstdata += dst_y * dw;
for (y = src_h; y; y--)
{
DATA32 *s = srcdata + src_x;
DATA8 *d = dstdata + dst_x;
for (x = src_w; x; x--, d++, s++)
*d = DIVIDE((R_VAL(s) * WR) + (G_VAL(s) * WG) + (B_VAL(s) * WB));
srcdata += sw;
dstdata += dw;
}
return EINA_TRUE;
}
static Eina_Bool static Eina_Bool
_image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context, _image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context,
void *surface, void *image, const void *src_map, unsigned int src_stride,
void *dst_map, unsigned int dst_stride,
int src_x, int src_y, int src_w, int src_h, int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h, int dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED, int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED) Eina_Bool do_async EINA_UNUSED)
{ {
struct Filter_Blend_Draw_Context *dc = context; struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image; uint32_t *srcdata = (uint32_t *) src_map;
RGBA_Image *dst = surface; uint32_t *dstdata = dst_map;
DATA32* srcdata = src->image.data;
DATA32* dstdata = dst->image.data;
RGBA_Gfx_Func func; RGBA_Gfx_Func func;
int y, sw, dw; int y, sw, dw;
@ -212,13 +110,13 @@ _image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context,
if (!dc->color) if (!dc->color)
return EINA_TRUE; return EINA_TRUE;
else if (dc->color == 0xFFFFFFFF) else if (dc->color == 0xFFFFFFFF)
func = evas_common_gfx_func_composite_pixel_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dst->cache_entry.flags.alpha, 1, dc->rop); func = evas_common_gfx_func_composite_pixel_span_get(1, 0, 1, 1, _gfx_to_evas_render_op(dc->rop));
else else
func = evas_common_gfx_func_composite_pixel_color_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dc->color, dst->cache_entry.flags.alpha, 1, dc->rop); func = evas_common_gfx_func_composite_pixel_color_span_get(1, 0, dc->color, 1, 1, _gfx_to_evas_render_op(dc->rop));
EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
sw = src->cache_entry.w; sw = LINELEN(src_stride, srcdata);
dw = dst->cache_entry.w; dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw; srcdata += src_y * sw;
dstdata += dst_y * dw; dstdata += dst_y * dw;
@ -232,6 +130,109 @@ _image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context,
return EINA_TRUE; return EINA_TRUE;
} }
static Eina_Bool
_image_draw_cpu_rgba2alpha(void *data EINA_UNUSED, void *context EINA_UNUSED,
const void *src_map, unsigned int src_stride,
void *dst_map, unsigned int dst_stride,
int src_x, int src_y, int src_w, int src_h,
int dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
uint32_t *srcdata = (uint32_t *) src_map;
uint8_t *dstdata = dst_map;
int x, y, sw, dw;
#if RGBA2ALPHA_WEIGHTED
const int WR = 299;
const int WG = 587;
const int WB = 114;
#else
const int WR = 1;
const int WG = 1;
const int WB = 1;
#endif
DEFINE_DIVIDER(WR + WG + WB);
EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
sw = LINELEN(src_stride, srcdata);
dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw;
dstdata += dst_y * dw;
for (y = src_h; y; y--)
{
uint32_t *s = srcdata + src_x;
uint8_t *d = dstdata + dst_x;
for (x = src_w; x; x--, d++, s++)
*d = DIVIDE((R_VAL(s) * WR) + (G_VAL(s) * WG) + (B_VAL(s) * WB));
srcdata += sw;
dstdata += dw;
}
return EINA_TRUE;
}
static Eina_Bool
_filter_blend_cpu_generic_do(Evas_Filter_Command *cmd, draw_func image_draw)
{
unsigned int src_len, src_stride, dst_len, dst_stride;
int sw, sh, dx, dy, dw, dh, sx, sy;
struct Filter_Blend_Draw_Context dc;
Eina_Bool ret = EINA_FALSE;
Evas_Filter_Buffer *src_fb;
void *src, *dst;
sx = 0;
sy = 0;
eo_do(cmd->input->buffer, ector_buffer_size_get(&sw, &sh));
dx = cmd->draw.ox;
dy = cmd->draw.oy;
eo_do(cmd->output->buffer, ector_buffer_size_get(&dw, &dh));
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return EINA_TRUE;
// Stretch if necessary.
/* NOTE: As of 2014/03/11, this will happen only with RGBA buffers, since
* only proxy sources may be scaled. So, we don't need an alpha scaling
* algorithm just now.
*/
if ((sw != dw || sh != dh) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
sw = dw;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
sh = dh;
BUFFERS_LOCK();
src_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->input, sw, sh);
BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_GOTO(src_fb, end);
src_fb->locked = EINA_FALSE;
}
else src_fb = cmd->input;
src = _buffer_map_all(src_fb->buffer, &src_len, E_READ, src_fb->alpha_only ? E_ALPHA : E_ARGB, &src_stride);
dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, cmd->output->alpha_only ? E_ALPHA : E_ARGB, &dst_stride);
dc.rop = cmd->draw.rop;
dc.color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
ret = _mapped_blend(cmd->ENDT, &dc, src, src_stride, dst, dst_stride, cmd->draw.fillmode,
sx, sy, sw, sh, dx, dy, dw, dh, image_draw);
end:
eo_do(src_fb->buffer, ector_buffer_unmap(src, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst, dst_len));
return ret;
}
static Eina_Bool static Eina_Bool
_filter_blend_cpu_alpha(Evas_Filter_Command *cmd) _filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
{ {
@ -239,7 +240,7 @@ _filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
} }
static Eina_Bool static Eina_Bool
_filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd) _filter_blend_cpu_alpha2rgba(Evas_Filter_Command *cmd)
{ {
return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha2rgba); return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha2rgba);
} }
@ -253,73 +254,19 @@ _filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
static Eina_Bool static Eina_Bool
_filter_blend_cpu_rgba(Evas_Filter_Command *cmd) _filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba2rgba);
RGBA_Draw_Context *drawctx;
int sw, sh, dx, dy, dw, dh, sx, sy;
Eina_Bool ret;
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
if (cmd->ctx->gl_engine)
return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba2rgba);
sx = 0;
sy = 0;
sw = in->cache_entry.w;
sh = in->cache_entry.h;
dx = cmd->draw.ox;
dy = cmd->draw.oy;
dw = out->cache_entry.w;
dh = out->cache_entry.h;
if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
return EINA_TRUE;
drawctx = cmd->ENFN->context_new(cmd->ENDT);
cmd->ENFN->context_color_set(cmd->ENDT, drawctx, 255, 255, 255, 255);
if ((cmd->draw.R != 255) || (cmd->draw.G != 255) || (cmd->draw.B != 255) || (cmd->draw.A != 255))
cmd->ENFN->context_multiplier_set(cmd->ENDT, drawctx, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A);
else
cmd->ENFN->context_multiplier_unset(cmd->ENDT, drawctx);
cmd->ENFN->context_render_op_set(cmd->ENDT, drawctx, _gfx_to_evas_render_op(cmd->draw.rop));
if (cmd->draw.clip_use)
{
cmd->ENFN->context_clip_set(cmd->ENDT, drawctx,
cmd->draw.clip.x, cmd->draw.clip.y,
cmd->draw.clip.w, cmd->draw.clip.h);
cmd->ENFN->context_clip_clip(cmd->ENDT, drawctx, 0, 0,
out->cache_entry.w, out->cache_entry.h);
}
else
{
cmd->ENFN->context_clip_set(cmd->ENDT, drawctx, 0, 0,
out->cache_entry.w, out->cache_entry.h);
}
ret = _mapped_blend(cmd->ENDT, drawctx, in, out, cmd->draw.fillmode,
sx, sy, sw, sh, dx, dy, dw, dh,
cmd->ENFN->image_draw);
cmd->ENFN->context_free(cmd->ENDT, drawctx);
return ret;
} }
static Eina_Bool static Eina_Bool
_mapped_blend(void *data, void *drawctx, _mapped_blend(void *data, void *drawctx,
void *in, void *out, const void *src_map, unsigned int src_stride,
void *dst_map, unsigned int dst_stride,
Evas_Filter_Fill_Mode fillmode, Evas_Filter_Fill_Mode fillmode,
int sx, int sy, int sx, int sy,
int sw, int sh, int sw, int sh,
int dx, int dy, int dx, int dy,
int dw, int dh, int dw, int dh,
image_draw_func image_draw) draw_func image_draw)
{ {
int right = 0, bottom = 0, left = 0, top = 0; int right = 0, bottom = 0, left = 0, top = 0;
int row, col, rows, cols; int row, col, rows, cols;
@ -336,7 +283,8 @@ _mapped_blend(void *data, void *drawctx,
XDBG("blend: %d,%d,%d,%d --> %d,%d,%d,%d (from %dx%d to %dx%d +%d,%d)", XDBG("blend: %d,%d,%d,%d --> %d,%d,%d,%d (from %dx%d to %dx%d +%d,%d)",
0, 0, sw, sh, dx, dy, cols, rows, sw, sh, dw, dh, dx, dy); 0, 0, sw, sh, dx, dy, cols, rows, sw, sh, dw, dh, dx, dy);
} }
image_draw(data, drawctx, out, in, image_draw(data, drawctx,
src_map, src_stride, dst_map, dst_stride,
sx, sy, cols, rows, // src sx, sy, cols, rows, // src
dx, dy, cols, rows, // dst dx, dy, cols, rows, // dst
EINA_TRUE, // smooth EINA_TRUE, // smooth
@ -477,7 +425,8 @@ _mapped_blend(void *data, void *drawctx,
dst_x, dst_y, dst_w, dst_h, dst_x, dst_y, dst_w, dst_h,
sw, sh, dw, dh); sw, sh, dw, dh);
} }
image_draw(data, drawctx, out, in, image_draw(data, drawctx,
src_map, src_stride, dst_map, dst_stride,
src_x, src_y, src_w, src_h, src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h, dst_x, dst_y, dst_w, dst_h,
EINA_TRUE, EINA_FALSE); EINA_TRUE, EINA_FALSE);
@ -493,27 +442,18 @@ evas_filter_blend_cpu_func_get(Evas_Filter_Command *cmd)
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
if (!cmd->ctx->gl_engine || !cmd->output->glimage || cmd->output->backing) if (cmd->input->alpha_only)
{ {
if (cmd->input->alpha_only) if (cmd->output->alpha_only)
{ return _filter_blend_cpu_alpha;
if (cmd->output->alpha_only)
return _filter_blend_cpu_alpha;
else
return _filter_blend_cpu_mask_rgba;
}
else else
{ return _filter_blend_cpu_alpha2rgba;
if (cmd->output->alpha_only)
return _filter_blend_cpu_rgba2alpha;
else
return _filter_blend_cpu_rgba;
}
} }
else else
{ {
CRI("Can't render to GL image for the moment!"); if (cmd->output->alpha_only)
//return _filter_blend_opengl_generic; return _filter_blend_cpu_rgba2alpha;
return NULL; else
return _filter_blend_cpu_rgba;
} }
} }

View File

@ -4,6 +4,8 @@
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
// FIXME: Add proper stride support
static int static int
_box_blur_auto_radius(int *radii, int r) _box_blur_auto_radius(int *radii, int r)
{ {
@ -45,7 +47,7 @@ _box_blur_auto_radius(int *radii, int r)
#endif #endif
static void static void
_box_blur_horiz_rgba(DATA32 *src, DATA32 *dst, int* radii, int w, int h) _box_blur_horiz_rgba(uint32_t *src, uint32_t *dst, int* radii, int w, int h)
{ {
DEBUG_TIME_BEGIN(); DEBUG_TIME_BEGIN();
@ -77,7 +79,7 @@ end:
} }
static void static void
_box_blur_vert_rgba(DATA32 *src, DATA32 *dst, int* radii, int w, int h) _box_blur_vert_rgba(uint32_t *src, uint32_t *dst, int* radii, int w, int h)
{ {
DEBUG_TIME_BEGIN(); DEBUG_TIME_BEGIN();
@ -108,64 +110,6 @@ end:
DEBUG_TIME_END(); DEBUG_TIME_END();
} }
static Eina_Bool
_box_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
int radii[7] = {0};
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dx);
in = cmd->input->backing;
out = cmd->output->backing;
if (cmd->blur.auto_count)
_box_blur_auto_radius(radii, r);
else for (int k = 0; k < cmd->blur.count; k++)
radii[k] = r;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
_box_blur_horiz_rgba(in->image.data, out->image.data, radii,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
}
static Eina_Bool
_box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
int radii[7] = {0};
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dy);
in = cmd->input->backing;
out = cmd->output->backing;
if (cmd->blur.auto_count)
_box_blur_auto_radius(radii, r);
else for (int k = 0; k < cmd->blur.count; k++)
radii[k] = r;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
_box_blur_vert_rgba(in->image.data, out->image.data, radii,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
}
#include "./blur/blur_box_alpha_.c" #include "./blur/blur_box_alpha_.c"
#ifdef BUILD_MMX #ifdef BUILD_MMX
#include "./blur/blur_box_alpha_i386.c" #include "./blur/blur_box_alpha_i386.c"
@ -178,7 +122,7 @@ _box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
#endif #endif
static void static void
_box_blur_horiz_alpha(DATA8 *src, DATA8 *dst, int* radii, int w, int h) _box_blur_horiz_alpha(const DATA8 *src, DATA8 *dst, int* radii, int w, int h)
{ {
DEBUG_TIME_BEGIN(); DEBUG_TIME_BEGIN();
@ -210,7 +154,7 @@ end:
} }
static void static void
_box_blur_vert_alpha(DATA8 *src, DATA8 *dst, int* radii, int w, int h) _box_blur_vert_alpha(const DATA8 *src, DATA8 *dst, int* radii, int w, int h)
{ {
DEBUG_TIME_BEGIN(); DEBUG_TIME_BEGIN();
@ -242,61 +186,70 @@ end:
} }
static Eina_Bool static Eina_Bool
_box_blur_horiz_apply_alpha(Evas_Filter_Command *cmd) _box_blur_apply(Evas_Filter_Command *cmd, Eina_Bool vert, Eina_Bool rgba)
{ {
RGBA_Image *in, *out; unsigned int src_len, src_stride, dst_len, dst_stride;
Eina_Bool ret = EINA_TRUE;
int radii[7] = {0}; int radii[7] = {0};
unsigned int r; unsigned int r;
void *src, *dst;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE); r = abs(vert ? cmd->blur.dy : cmd->blur.dx);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE); src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, rgba ? E_ARGB : E_ALPHA, &src_stride);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE); dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, rgba ? E_ARGB : E_ALPHA, &dst_stride);
r = abs(cmd->blur.dx);
in = cmd->input->backing;
out = cmd->output->backing;
if (cmd->blur.auto_count) if (cmd->blur.auto_count)
_box_blur_auto_radius(radii, r); _box_blur_auto_radius(radii, r);
else for (int k = 0; k < cmd->blur.count; k++) else for (int k = 0; k < cmd->blur.count; k++)
radii[k] = r; radii[k] = r;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE); if (src && dst)
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE); {
if (rgba)
{
if (!vert)
_box_blur_horiz_rgba(src, dst, radii, cmd->input->w, cmd->input->h);
else
_box_blur_vert_rgba(src, dst, radii, cmd->input->w, cmd->input->h);
}
else
{
if (!vert)
_box_blur_horiz_alpha(src, dst, radii, cmd->input->w, cmd->input->h);
else
_box_blur_vert_alpha(src, dst, radii, cmd->input->w, cmd->input->h);
}
}
else ret = EINA_FALSE;
_box_blur_horiz_alpha(in->image.data8, out->image.data8, radii, eo_do(cmd->input->buffer, ector_buffer_unmap(src, src_len));
in->cache_entry.w, in->cache_entry.h); eo_do(cmd->output->buffer, ector_buffer_unmap(dst, dst_len));
return EINA_TRUE; return ret;
}
static Eina_Bool
_box_blur_horiz_apply_alpha(Evas_Filter_Command *cmd)
{
return _box_blur_apply(cmd, 0, 0);
} }
static Eina_Bool static Eina_Bool
_box_blur_vert_apply_alpha(Evas_Filter_Command *cmd) _box_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _box_blur_apply(cmd, 1, 0);
int radii[7] = {0}; }
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE); static Eina_Bool
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE); _box_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE); {
return _box_blur_apply(cmd, 0, 1);
}
r = abs(cmd->blur.dy); static Eina_Bool
in = cmd->input->backing; _box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
out = cmd->output->backing; {
return _box_blur_apply(cmd, 1, 1);
if (cmd->blur.auto_count)
_box_blur_auto_radius(radii, r);
else for (int k = 0; k < cmd->blur.count; k++)
radii[k] = r;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
_box_blur_vert_alpha(in->image.data8, out->image.data8, radii,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
} }
/* Gaussian blur */ /* Gaussian blur */
@ -342,165 +295,86 @@ _sin_blur_weights_get(int *weights, int *pow2_divider, int radius)
#define STEP 1 #define STEP 1
#include "./blur/blur_gaussian_alpha_.c" #include "./blur/blur_gaussian_alpha_.c"
static void
_gaussian_blur_horiz_alpha(const DATA8 *src, DATA8 *dst, int radius, int w, int h)
{
int *weights;
int pow2_div = 0;
weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
_gaussian_blur_horiz_alpha_step(src, dst, radius, w, h, w, weights, pow2_div);
DEBUG_TIME_END();
}
// Step size is w (row by row), loops = w, so STEP = 'loops' // Step size is w (row by row), loops = w, so STEP = 'loops'
#define FUNCTION_NAME _gaussian_blur_vert_alpha_step #define FUNCTION_NAME _gaussian_blur_vert_alpha_step
#define STEP loops #define STEP loops
#include "./blur/blur_gaussian_alpha_.c" #include "./blur/blur_gaussian_alpha_.c"
static void
_gaussian_blur_vert_alpha(const DATA8 *src, DATA8 *dst, int radius, int w, int h)
{
int *weights;
int pow2_div = 0;
weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
_gaussian_blur_vert_alpha_step(src, dst, radius, h, w, 1, weights, pow2_div);
DEBUG_TIME_END();
}
#define FUNCTION_NAME _gaussian_blur_horiz_rgba_step #define FUNCTION_NAME _gaussian_blur_horiz_rgba_step
#define STEP 1 #define STEP 1
#include "./blur/blur_gaussian_rgba_.c" #include "./blur/blur_gaussian_rgba_.c"
static void
_gaussian_blur_horiz_rgba(DATA32 *src, DATA32 *dst, int radius, int w, int h)
{
int *weights;
int pow2_div = 0;
weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
_gaussian_blur_horiz_rgba_step(src, dst, radius, w, h, w, weights, pow2_div);
DEBUG_TIME_END();
}
#define FUNCTION_NAME _gaussian_blur_vert_rgba_step #define FUNCTION_NAME _gaussian_blur_vert_rgba_step
#define STEP loops #define STEP loops
#include "./blur/blur_gaussian_rgba_.c" #include "./blur/blur_gaussian_rgba_.c"
static void static Eina_Bool
_gaussian_blur_vert_rgba(DATA32 *src, DATA32 *dst, int radius, int w, int h) _gaussian_blur_apply(Evas_Filter_Command *cmd, Eina_Bool vert, Eina_Bool rgba)
{ {
unsigned int src_len, src_stride, dst_len, dst_stride, radius;
Eina_Bool ret = EINA_TRUE;
int pow2_div = 0, w, h;
void *src, *dst;
int *weights; int *weights;
int pow2_div = 0;
radius = abs(vert ? cmd->blur.dy : cmd->blur.dx);
src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, rgba ? E_ARGB : E_ALPHA, &src_stride);
dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, rgba ? E_ARGB : E_ALPHA, &dst_stride);
w = cmd->input->w;
h = cmd->input->h;
weights = alloca((2 * radius + 1) * sizeof(int)); weights = alloca((2 * radius + 1) * sizeof(int));
_sin_blur_weights_get(weights, &pow2_div, radius); _sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN(); if (src && dst)
_gaussian_blur_vert_rgba_step(src, dst, radius, h, w, 1, weights, pow2_div); {
DEBUG_TIME_END(); DEBUG_TIME_BEGIN();
if (rgba)
{
if (!vert)
_gaussian_blur_horiz_rgba_step(src, dst, radius, w, h, w, weights, pow2_div);
else
_gaussian_blur_vert_rgba_step(src, dst, radius, h, w, 1, weights, pow2_div);
}
else
{
if (!vert)
_gaussian_blur_horiz_alpha_step(src, dst, radius, w, h, w, weights, pow2_div);
else
_gaussian_blur_vert_alpha_step(src, dst, radius, h, w, 1, weights, pow2_div);
}
DEBUG_TIME_END();
}
else ret = EINA_FALSE;
eo_do(cmd->input->buffer, ector_buffer_unmap(src, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst, dst_len));
return ret;
} }
static Eina_Bool static Eina_Bool
_gaussian_blur_horiz_apply_alpha(Evas_Filter_Command *cmd) _gaussian_blur_horiz_apply_alpha(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _gaussian_blur_apply(cmd, 0, 0);
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dx);
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
_gaussian_blur_horiz_alpha(in->image.data8, out->image.data8, r,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
} }
static Eina_Bool static Eina_Bool
_gaussian_blur_vert_apply_alpha(Evas_Filter_Command *cmd) _gaussian_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _gaussian_blur_apply(cmd, 1, 0);
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dy);
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
_gaussian_blur_vert_alpha(in->image.data8, out->image.data8, r,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
} }
static Eina_Bool static Eina_Bool
_gaussian_blur_horiz_apply_rgba(Evas_Filter_Command *cmd) _gaussian_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _gaussian_blur_apply(cmd, 0, 1);
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dx);
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
_gaussian_blur_horiz_rgba(in->image.data, out->image.data, r,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
} }
static Eina_Bool static Eina_Bool
_gaussian_blur_vert_apply_rgba(Evas_Filter_Command *cmd) _gaussian_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; return _gaussian_blur_apply(cmd, 1, 1);
unsigned int r;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
r = abs(cmd->blur.dy);
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
_gaussian_blur_vert_rgba(in->image.data, out->image.data, r,
in->cache_entry.w, in->cache_entry.h);
return EINA_TRUE;
} }
/* Main entry point */ /* Main entry point */

View File

@ -50,7 +50,7 @@ evas_filter_bump_map_cpu_func_get(Evas_Filter_Command *cmd)
} }
static void static void
_phong_alpha_generate(DATA8 *phong, DATA8 dark, DATA8 color, DATA8 white, _phong_alpha_generate(uint8_t *phong, uint8_t dark, uint8_t color, uint8_t white,
float sf) float sf)
{ {
int x, y; int x, y;
@ -100,22 +100,23 @@ _phong_alpha_generate(DATA8 *phong, DATA8 dark, DATA8 color, DATA8 white,
static Eina_Bool static Eina_Bool
_bump_map_cpu_alpha_alpha(Evas_Filter_Command *cmd) _bump_map_cpu_alpha_alpha(Evas_Filter_Command *cmd)
{ {
DATA8 *src, *map, *dst, *map_y1, *map_y2; uint8_t *src_map, *map_map, *dst_map;
DATA8 dark, color, white; uint8_t *src, *map, *dst, *map_y1, *map_y2;
DATA8 *phong; uint8_t dark, color, white;
uint8_t *phong = NULL;
Eina_Bool ret = EINA_FALSE;
int x, y, w, h, lx, ly; int x, y, w, h, lx, ly;
unsigned int ss, ms, ds, slen, dlen, mlen;
float xyangle, zangle, sf, lxy; float xyangle, zangle, sf, lxy;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 2 && h > 2, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 2 && h > 2, EINA_FALSE);
src = ((RGBA_Image *) cmd->input->backing)->image.data8; src_map = src = _buffer_map_all(cmd->input->buffer, &slen, E_READ, E_ALPHA, &ss);
map = ((RGBA_Image *) cmd->mask->backing)->image.data8; map_map = map = _buffer_map_all(cmd->mask->buffer, &mlen, E_READ, E_ALPHA, &ms);
dst = ((RGBA_Image *) cmd->output->backing)->image.data8; dst_map = dst = _buffer_map_all(cmd->output->buffer, &dlen, E_WRITE, E_ALPHA, &ds);
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); EINA_SAFETY_ON_FALSE_GOTO(src && dst && map, end);
EINA_SAFETY_ON_NULL_RETURN_VAL(map, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
xyangle = cmd->bump.xyangle; xyangle = cmd->bump.xyangle;
zangle = cmd->bump.zangle; zangle = cmd->bump.zangle;
@ -150,7 +151,7 @@ _bump_map_cpu_alpha_alpha(Evas_Filter_Command *cmd)
// Generate light table // Generate light table
phong = malloc(256 * 256 * sizeof(*phong)); phong = malloc(256 * 256 * sizeof(*phong));
EINA_SAFETY_ON_NULL_RETURN_VAL(phong, EINA_FALSE); EINA_SAFETY_ON_NULL_GOTO(phong, end);
_phong_alpha_generate(phong, dark, color, white, sf); _phong_alpha_generate(phong, dark, color, white, sf);
for (y = 0; y < h; y++) for (y = 0; y < h; y++)
@ -228,31 +229,36 @@ _bump_map_cpu_alpha_alpha(Evas_Filter_Command *cmd)
src++; src++;
} }
ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, slen));
eo_do(cmd->mask->buffer, ector_buffer_unmap(map_map, mlen));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dlen));
free(phong); free(phong);
return EINA_TRUE; return ret;
} }
static Eina_Bool static Eina_Bool
_bump_map_cpu_alpha_rgba(Evas_Filter_Command *cmd) _bump_map_cpu_alpha_rgba(Evas_Filter_Command *cmd)
{ {
DATA8 *src, *map, *map_y1, *map_y2; uint8_t *src_map, *map_map;
DATA32 *dst; uint8_t *src, *map, *map_y1, *map_y2;
DATA32 dark, color, white, col; uint32_t *dst, *dst_map;
//DATA32 *phong; uint32_t dark, color, white, col;
Eina_Bool compensate; Eina_Bool compensate, ret = EINA_FALSE;
int x, y, w, h, lx, ly, lz, gz, NL, diffusion, gzlz, gz2; int x, y, w, h, lx, ly, lz, gz, NL, diffusion, gzlz, gz2;
unsigned int ss, ms, ds, slen, dlen, mlen;
double xyangle, zangle, sf, lxy, elevation; double xyangle, zangle, sf, lxy, elevation;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 2 && h > 2, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 2 && h > 2, EINA_FALSE);
src = ((RGBA_Image *) cmd->input->backing)->image.data8; src_map = src = _buffer_map_all(cmd->input->buffer, &slen, E_READ, E_ALPHA, &ss);
map = ((RGBA_Image *) cmd->mask->backing)->image.data8; map_map = map = _buffer_map_all(cmd->mask->buffer, &mlen, E_READ, E_ALPHA, &ms);
dst = ((RGBA_Image *) cmd->output->backing)->image.data; dst_map = dst = (uint32_t *) _buffer_map_all(cmd->output->buffer, &dlen, E_WRITE, E_ARGB, &ds);
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); EINA_SAFETY_ON_FALSE_GOTO(src && dst && map, end);
EINA_SAFETY_ON_NULL_RETURN_VAL(map, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
xyangle = cmd->bump.xyangle; xyangle = cmd->bump.xyangle;
zangle = cmd->bump.zangle; zangle = cmd->bump.zangle;
@ -403,7 +409,13 @@ _bump_map_cpu_alpha_rgba(Evas_Filter_Command *cmd)
} }
} }
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, slen));
eo_do(cmd->mask->buffer, ector_buffer_unmap(map_map, mlen));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dlen));
return ret;
} }
static Eina_Bool static Eina_Bool

View File

@ -5,23 +5,23 @@
static Eina_Bool static Eina_Bool
_filter_curve_cpu_rgba(Evas_Filter_Command *cmd) _filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; unsigned int src_len, src_stride, dst_len, dst_stride;
DATA32 *src, *dst, *d, *s; void *src_map = NULL, *dst_map;
DATA8 *curve; Eina_Bool ret = EINA_FALSE;
uint32_t *src, *dst, *d, *s;
uint8_t *curve;
int k, offset = -1, len; int k, offset = -1, len;
#define C_VAL(p) (((DATA8 *)(p))[offset]) #define C_VAL(p) (((uint8_t *)(p))[offset])
// FIXME: support src_stride != dst_stride
// Note: potentially mapping the same region twice (read then write)
src_map = src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ARGB, &src_stride);
dst_map = dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
EINA_SAFETY_ON_FALSE_GOTO(src && dst && (src_len == dst_len), end);
in = cmd->input->backing;
out = cmd->output->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
src = in->image.data;
dst = out->image.data;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
curve = cmd->curve.data; curve = cmd->curve.data;
len = in->cache_entry.w * in->cache_entry.h; len = dst_len / sizeof(uint32_t);
switch (cmd->curve.channel) switch (cmd->curve.channel)
{ {
@ -38,11 +38,11 @@ _filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
case EVAS_FILTER_CHANNEL_RGB: break; case EVAS_FILTER_CHANNEL_RGB: break;
default: default:
ERR("Invalid color channel %d", (int) cmd->curve.channel); ERR("Invalid color channel %d", (int) cmd->curve.channel);
return EINA_FALSE; goto end;
} }
if (src != dst) if (src != dst)
memcpy(dst, src, len * sizeof(DATA32)); memcpy(dst, src, dst_len);
evas_data_argb_unpremul(dst, len); evas_data_argb_unpremul(dst, len);
// One channel (R, G or B) // One channel (R, G or B)
@ -82,31 +82,39 @@ _filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
premul: premul:
evas_data_argb_premul(dst, len); evas_data_argb_premul(dst, len);
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }
static Eina_Bool static Eina_Bool
_filter_curve_cpu_alpha(Evas_Filter_Command *cmd) _filter_curve_cpu_alpha(Evas_Filter_Command *cmd)
{ {
RGBA_Image *in, *out; unsigned int src_len, src_stride, dst_len, dst_stride;
DATA8 *src, *dst; uint8_t *src, *dst, *curve;
DATA8 *curve; void *src_map, *dst_map;
Eina_Bool ret = EINA_FALSE;
int k; int k;
in = cmd->input->backing; // FIXME: support src_stride != dst_stride
out = cmd->output->backing; // Note: potentially mapping the same region twice (read then write)
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE); src_map = src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ALPHA, &src_stride);
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE); dst_map = dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ALPHA, &dst_stride);
src = in->image.data8; EINA_SAFETY_ON_FALSE_GOTO(src && dst && (src_len == dst_len), end);
dst = out->image.data8;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
curve = cmd->curve.data; curve = cmd->curve.data;
for (k = in->cache_entry.w * in->cache_entry.h; k; k--) for (k = src_len; k; k--)
*dst++ = curve[*src++]; *dst++ = curve[*src++];
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }
Evas_Filter_Apply_Func Evas_Filter_Apply_Func
@ -124,6 +132,8 @@ evas_filter_curve_cpu_func_get(Evas_Filter_Command *cmd)
if (cmd->input->alpha_only && cmd->output->alpha_only) if (cmd->input->alpha_only && cmd->output->alpha_only)
return _filter_curve_cpu_alpha; return _filter_curve_cpu_alpha;
CRI("Incompatible image formats"); // Rely on ector buffer's implicit conversion. not great but the command
return NULL; // doesn't make much sense (curve requires same channel count).
WRN("Incompatible image formats");
return _filter_curve_cpu_rgba;
} }

View File

@ -3,22 +3,24 @@
static void static void
_filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity, _filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity,
DATA8 *src, DATA8 *dst, DATA32 *map_start, uint8_t *src, uint8_t *dst, uint32_t *map_start,
Eina_Bool stretch, Eina_Bool smooth, Eina_Bool stretch, Eina_Bool smooth,
Eina_Bool blend) Eina_Bool blend)
{ {
int x, y, map_x, map_y; int x, y, map_x, map_y;
const int dx = RED; const int dx = RED;
const int dy = GREEN; const int dy = GREEN;
DATA8 *map; uint8_t *map;
// FIXME: Add stride support
for (y = 0, map_y = 0; y < h; y++, map_y++) for (y = 0, map_y = 0; y < h; y++, map_y++)
{ {
if (map_y >= map_h) map_y = 0; if (map_y >= map_h) map_y = 0;
map = (DATA8 *) (map_start + map_y * map_w); map = (uint8_t *) (map_start + map_y * map_w);
for (x = 0, map_x = 0; x < w; for (x = 0, map_x = 0; x < w;
x++, dst++, src++, map_x++, map += sizeof(DATA32)) x++, dst++, src++, map_x++, map += sizeof(uint32_t))
{ {
int offx = 0, offy = 0, offx_dec = 0, offy_dec = 0, val = 0; int offx = 0, offy = 0, offx_dec = 0, offy_dec = 0, val = 0;
Eina_Bool out = 0; Eina_Bool out = 0;
@ -27,7 +29,7 @@ _filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity,
if (map_x >= map_w) if (map_x >= map_w)
{ {
map_x = 0; map_x = 0;
map = (DATA8 *) (map_start + map_y * map_w); map = (uint8_t *) (map_start + map_y * map_w);
} }
// x // x
@ -76,7 +78,7 @@ _filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity,
static void static void
_filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity, _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity,
DATA32 *src, DATA32 *dst, DATA32 *map_start, uint32_t *src, uint32_t *dst, uint32_t *map_start,
Eina_Bool stretch, Eina_Bool smooth, Eina_Bool stretch, Eina_Bool smooth,
Eina_Bool blend) Eina_Bool blend)
{ {
@ -84,25 +86,25 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity,
const int dx = RED; const int dx = RED;
const int dy = GREEN; const int dy = GREEN;
Eina_Bool unpremul = EINA_FALSE; Eina_Bool unpremul = EINA_FALSE;
DATA8 *map; uint8_t *map;
for (y = 0, map_y = 0; y < h; y++, map_y++) for (y = 0, map_y = 0; y < h; y++, map_y++)
{ {
if (map_y >= map_h) map_y = 0; if (map_y >= map_h) map_y = 0;
map = (DATA8 *) (map_start + map_y * map_w); map = (uint8_t *) (map_start + map_y * map_w);
for (x = 0, map_x = 0; x < w; for (x = 0, map_x = 0; x < w;
x++, dst++, src++, map_x++, map += sizeof(DATA32)) x++, dst++, src++, map_x++, map += sizeof(uint32_t))
{ {
int offx = 0, offy = 0, offx_dec = 0, offy_dec = 0, val = 0; int offx = 0, offy = 0, offx_dec = 0, offy_dec = 0, val = 0;
DATA32 col = 0; uint32_t col = 0;
Eina_Bool out = 0; Eina_Bool out = 0;
// wrap (x) // wrap (x)
if (map_x >= map_w) if (map_x >= map_w)
{ {
map_x = 0; map_x = 0;
map = (DATA8 *) (map_start + map_y * map_w); map = (uint8_t *) (map_start + map_y * map_w);
} }
if (!map[ALPHA]) continue; if (!map[ALPHA]) continue;
@ -134,7 +136,7 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity,
else else
{ {
int R, G, B, A; int R, G, B, A;
DATA32 s00, s01, s10, s11; // indexes represent x,y uint32_t s00, s01, s10, s11; // indexes represent x,y
int mul00, mul01, mul10, mul11; int mul00, mul01, mul10, mul11;
mul00 = (128 - offx_dec) * (128 - offy_dec); mul00 = (128 - offx_dec) * (128 - offy_dec);
@ -172,7 +174,7 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity,
if (blend) if (blend)
{ {
DATA32 a = 256 - ALPHA_OF(col); uint32_t a = 256 - ALPHA_OF(col);
*dst = col + MUL_256(a, *dst); *dst = col + MUL_256(a, *dst);
} }
else else
@ -193,26 +195,21 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity,
static Eina_Bool static Eina_Bool
_filter_displace_cpu_alpha(Evas_Filter_Command *cmd) _filter_displace_cpu_alpha(Evas_Filter_Command *cmd)
{ {
unsigned int src_len, src_stride, map_len, map_stride, dst_len, dst_stride;
int w, h, map_w, map_h, intensity; int w, h, map_w, map_h, intensity;
DATA8 *dst, *src; uint8_t *dst, *src;
DATA32 *map_start; uint32_t *map_start;
Eina_Bool stretch, smooth, blend; Eina_Bool stretch, smooth, blend;
Evas_Filter_Buffer *map_fb;
Eina_Bool ret = EINA_FALSE;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
src = ((RGBA_Image *) cmd->input->backing)->image.data8;
map_start = ((RGBA_Image *) cmd->mask->backing)->image.data;
dst = ((RGBA_Image *) cmd->output->backing)->image.data8;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(map_start, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ALPHA, &src_stride);
dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_READ, E_ALPHA, &dst_stride);
stretch = cmd->displacement.flags & EVAS_FILTER_DISPLACE_STRETCH; stretch = cmd->displacement.flags & EVAS_FILTER_DISPLACE_STRETCH;
smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR; smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR;
map_w = cmd->mask->w; map_w = cmd->mask->w;
@ -223,26 +220,32 @@ _filter_displace_cpu_alpha(Evas_Filter_Command *cmd)
// Stretch if necessary. // Stretch if necessary.
if ((map_w != w || map_h != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((map_w != w || map_h != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
map_w = w; map_w = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
map_h = h; map_h = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, map_w, map_h); map_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, map_w, map_h);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(map_fb, EINA_FALSE);
fb->locked = EINA_FALSE; map_fb->locked = EINA_FALSE;
map_start = ((RGBA_Image *) fb->backing)->image.data;
} }
else map_fb = cmd->mask;
map_start = (uint32_t *) _buffer_map_all(map_fb->buffer, &map_len, E_READ, E_ARGB, &map_stride);
EINA_SAFETY_ON_FALSE_GOTO(src && dst && map_start, end);
_filter_displace_cpu_alpha_do(w, h, map_w, map_h, intensity, _filter_displace_cpu_alpha_do(w, h, map_w, map_h, intensity,
src, dst, map_start, stretch, smooth, blend); src, dst, map_start, stretch, smooth, blend);
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst, dst_len));
eo_do(map_fb->buffer, ector_buffer_unmap(map_start, map_len));
return ret;
} }
/** /**
@ -254,25 +257,20 @@ _filter_displace_cpu_alpha(Evas_Filter_Command *cmd)
static Eina_Bool static Eina_Bool
_filter_displace_cpu_rgba(Evas_Filter_Command *cmd) _filter_displace_cpu_rgba(Evas_Filter_Command *cmd)
{ {
unsigned int src_len, src_stride, map_len, map_stride, dst_len, dst_stride;
int w, h, map_w, map_h, intensity; int w, h, map_w, map_h, intensity;
DATA32 *dst, *src, *map_start; uint32_t *dst, *src, *map_start;
Eina_Bool stretch, smooth, blend; Eina_Bool stretch, smooth, blend;
Evas_Filter_Buffer *map_fb;
Eina_Bool ret = EINA_FALSE;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE); EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
src = ((RGBA_Image *) cmd->input->backing)->image.data;
map_start = ((RGBA_Image *) cmd->mask->backing)->image.data;
dst = ((RGBA_Image *) cmd->output->backing)->image.data;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(map_start, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ARGB, &src_stride);
dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_READ, E_ARGB, &dst_stride);
stretch = cmd->displacement.flags & EVAS_FILTER_DISPLACE_STRETCH; stretch = cmd->displacement.flags & EVAS_FILTER_DISPLACE_STRETCH;
smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR; smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR;
map_w = cmd->mask->w; map_w = cmd->mask->w;
@ -283,26 +281,32 @@ _filter_displace_cpu_rgba(Evas_Filter_Command *cmd)
// Stretch if necessary. // Stretch if necessary.
if ((map_w != w || map_h != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((map_w != w || map_h != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
map_w = w; map_w = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
map_h = h; map_h = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, map_w, map_h); map_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, map_w, map_h);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(map_fb, EINA_FALSE);
fb->locked = EINA_FALSE; map_fb->locked = EINA_FALSE;
map_start = ((RGBA_Image *) fb->backing)->image.data;
} }
else map_fb = cmd->mask;
map_start = (uint32_t *) _buffer_map_all(map_fb->buffer, &map_len, E_READ, E_ARGB, &map_stride);
EINA_SAFETY_ON_FALSE_GOTO(src && dst && map_start, end);
_filter_displace_cpu_rgba_do(w, h, map_w, map_h, intensity, _filter_displace_cpu_rgba_do(w, h, map_w, map_h, intensity,
src, dst, map_start, stretch, smooth, blend); src, dst, map_start, stretch, smooth, blend);
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src, src_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst, dst_len));
eo_do(map_fb->buffer, ector_buffer_unmap(map_start, map_len));
return ret;
} }
Evas_Filter_Apply_Func Evas_Filter_Apply_Func

View File

@ -1,14 +1,17 @@
#include "evas_filter_private.h" #include "evas_filter_private.h"
#include "draw.h"
static Eina_Bool static Eina_Bool
_fill_cpu(Evas_Filter_Command *cmd) _fill_cpu(Evas_Filter_Command *cmd)
{ {
Evas_Filter_Buffer *fb = cmd->output; Evas_Filter_Buffer *fb = cmd->output;
int step = fb->alpha_only ? sizeof(DATA8) : sizeof(DATA32); int step = fb->alpha_only ? sizeof(uint8_t) : sizeof(uint32_t);
int x = MAX(0, cmd->draw.clip.x); int x = MAX(0, cmd->draw.clip.x);
int y = MAX(0, cmd->draw.clip.y); int y = MAX(0, cmd->draw.clip.y);
DATA8 *ptr = ((RGBA_Image *) fb->backing)->image.data8; uint32_t color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
int w, h, k, j; unsigned int stride, len;
int w, h, k;
uint8_t *ptr;
if (!cmd->draw.clip_mode_lrtb) if (!cmd->draw.clip_mode_lrtb)
{ {
@ -29,30 +32,28 @@ _fill_cpu(Evas_Filter_Command *cmd)
h = CLAMP(0, fb->h - y - cmd->draw.clip.b, fb->h - y); h = CLAMP(0, fb->h - y - cmd->draw.clip.b, fb->h - y);
} }
ptr += y * step * fb->w; ptr = _buffer_map_all(fb->buffer, &len, E_WRITE, fb->alpha_only ? E_ALPHA : E_ARGB, &stride);
if ((fb->alpha_only) if (!ptr) return EINA_FALSE;
|| (!cmd->draw.R && !cmd->draw.G && !cmd->draw.B && !cmd->draw.A)
|| ((cmd->draw.R == 0xff) && (cmd->draw.G == 0xff) ptr += y * stride;
&& (cmd->draw.B == 0xff) && (cmd->draw.A == 0xff))) if (fb->alpha_only)
{ {
for (k = 0; k < h; k++) for (k = 0; k < h; k++)
{ {
memset(ptr + (x * step), cmd->draw.A, step * w); memset(ptr + (x * step), cmd->draw.A, step * w);
ptr += step * fb->w; ptr += stride;
} }
} }
else else
{ {
DATA32 *dst = ((DATA32 *) ptr) + x;
DATA32 color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
for (k = 0; k < h; k++) for (k = 0; k < h; k++)
{ {
for (j = 0; j < w; j++) uint32_t *dst = ((uint32_t *) (ptr + (y + k) * stride)) + x;
*dst++ = color; draw_memset32(dst, color, w);
dst += fb->w - w;
} }
} }
eo_do(fb->buffer, ector_buffer_unmap(ptr, len));
return EINA_TRUE; return EINA_TRUE;
} }

View File

@ -18,11 +18,11 @@ evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd)
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->buffer, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->buffer, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->buffer, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->backing, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->input->w > 0) && (cmd->input->h > 0), NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->mask->w > 0) && (cmd->mask->h > 0), NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->w == cmd->output->w, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->w == cmd->output->w, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->h == cmd->output->h, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->h == cmd->output->h, NULL);
@ -53,12 +53,14 @@ evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd)
static Eina_Bool static Eina_Bool
_mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd) _mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
{ {
Alpha_Gfx_Func func; unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
RGBA_Image *in, *out, *mask;
DATA8 *src, *dst, *msk;
Efl_Gfx_Render_Op render_op = cmd->draw.rop; Efl_Gfx_Render_Op render_op = cmd->draw.rop;
Evas_Filter_Buffer *msk_fb;
Alpha_Gfx_Func func;
uint8_t *src_map = NULL, *dst, *dst_map = NULL, *msk, *msk_map = NULL;
int w, h, mw, mh, x, y, my; int w, h, mw, mh, x, y, my;
int stepsize, stepcount, step; int stepsize, stepcount, step;
Eina_Bool ret = EINA_FALSE;
/* Mechanism: /* Mechanism:
* 1. Stretch mask as requested in fillmode * 1. Stretch mask as requested in fillmode
@ -68,56 +70,57 @@ _mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
* FIXME: Could probably be optimized into a single op :) * FIXME: Could probably be optimized into a single op :)
*/ */
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
mw = cmd->mask->w; mw = cmd->mask->w;
mh = cmd->mask->h; mh = cmd->mask->h;
src = in->image.data8;
dst = out->image.data8;
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
stepsize = MIN(mw, w); stepsize = MIN(mw, w);
stepcount = w / stepsize; stepcount = w / stepsize;
// Stretch if necessary. // Stretch if necessary.
if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
mw = w; mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h; mh = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh); msk_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
fb->locked = EINA_FALSE; msk_fb->locked = EINA_FALSE;
mask = fb->backing;
} }
else msk_fb = cmd->mask;
msk = mask->image.data8; msk_map = msk = _buffer_map_all(msk_fb->buffer, &msk_len, E_READ, E_ALPHA, &msk_stride);
dst_map = dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ALPHA, &dst_stride);
EINA_SAFETY_ON_FALSE_GOTO(dst_map && msk_map, end);
// First pass: copy to dest // First pass: copy to dest
if (src != dst) if (cmd->input->buffer != cmd->output->buffer)
memcpy(dst, src, w * h * sizeof(DATA8)); {
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ALPHA, &src_stride);
EINA_SAFETY_ON_FALSE_GOTO(src_map, end);
if (dst_stride == src_stride)
memcpy(dst_map, src_map, dst_stride * h * sizeof(uint8_t));
else
{
for (y = 0; y < h; y++)
memcpy(dst_map + (y * dst_stride), src_map + (y * src_stride),
MIN(dst_stride, src_stride) * h * sizeof(uint8_t));
}
}
// Second pass: apply render op // Second pass: apply render op
func = efl_draw_alpha_func_get(render_op, EINA_FALSE); func = efl_draw_alpha_func_get(render_op, EINA_FALSE);
for (y = 0, my = 0; y < h; y++, my++, msk += mw) for (y = 0, my = 0; y < h; y++, my++)
{ {
if (my >= mh) if (my >= mh) my = 0;
{
my = 0; msk = msk_map + (my * msk_stride);
msk = mask->image.data8; dst = dst_map + (y * dst_stride);
}
for (step = 0; step < stepcount; step++, dst += stepsize) for (step = 0; step < stepcount; step++, dst += stepsize)
func(msk, dst, stepsize); func(msk, dst, stepsize);
@ -126,11 +129,16 @@ _mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
if (x < w) if (x < w)
{ {
func(msk, dst, w - x); func(msk, dst, w - x);
dst += w - x;
} }
} }
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(msk_fb->buffer, ector_buffer_unmap(msk_map, msk_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }
static Eina_Bool static Eina_Bool
@ -161,14 +169,16 @@ _mask_cpu_rgba_alpha_rgba(Evas_Filter_Command *cmd)
static Eina_Bool static Eina_Bool
_mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd) _mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
{ {
RGBA_Gfx_Func func1, func2; unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
RGBA_Image *in, *out, *mask;
DATA8 *src;
DATA32 *dst, *msk, *span;
Efl_Gfx_Render_Op op = cmd->draw.rop; Efl_Gfx_Render_Op op = cmd->draw.rop;
int w, h, mw, mh, y, my, r; Evas_Filter_Buffer *msk_fb;
RGBA_Gfx_Func func1, func2;
uint8_t *src, *src_map = NULL, *msk_map = NULL, *dst_map = NULL;
uint32_t *dst, *msk, *span;
int w, h, mw, mh, x, y, my;
int stepsize, stepcount, step; int stepsize, stepcount, step;
DATA32 color2; Eina_Bool ret = EINA_FALSE;
uint32_t color;
/* Mechanism: /* Mechanism:
* 1. Stretch mask as requested in fillmode * 1. Stretch mask as requested in fillmode
@ -178,94 +188,88 @@ _mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
* FIXME: Could probably be optimized into a single op :) * FIXME: Could probably be optimized into a single op :)
*/ */
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
mw = cmd->mask->w; mw = cmd->mask->w;
mh = cmd->mask->h; mh = cmd->mask->h;
src = in->image.data8; color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
dst = out->image.data; stepsize = MIN(mw, w);
stepcount = w / stepsize;
span = alloca(stepsize * sizeof(uint32_t));
// Stretch if necessary. // Stretch if necessary.
if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
mw = w; mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h; mh = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh); msk_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
fb->locked = EINA_FALSE; msk_fb->locked = EINA_FALSE;
mask = fb->backing;
} }
else msk_fb = cmd->mask;
color2 = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B); src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ALPHA, &src_stride);
msk = mask->image.data; msk_map = _buffer_map_all(msk_fb->buffer, &msk_len, E_READ, E_ARGB, &msk_stride);
dst_map = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map && msk_map, end);
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); func1 = evas_common_gfx_func_composite_pixel_mask_span_get(1, 0, 1, 1, EVAS_RENDER_COPY);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE); func2 = evas_common_gfx_func_composite_pixel_color_span_get(1, 0, color, 1, 1, _gfx_to_evas_render_op(op));
EINA_SAFETY_ON_NULL_RETURN_VAL(msk, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
stepsize = MIN(mw, w);
stepcount = w / stepsize;
span = malloc(stepsize * sizeof(DATA32));
func1 = evas_common_gfx_func_composite_pixel_mask_span_get(mask->cache_entry.flags.alpha, mask->cache_entry.flags.alpha_sparse, out->cache_entry.flags.alpha, 1, EVAS_RENDER_COPY);
func2 = evas_common_gfx_func_composite_pixel_color_span_get(mask->cache_entry.flags.alpha, mask->cache_entry.flags.alpha_sparse, color2, out->cache_entry.flags.alpha, 1, _gfx_to_evas_render_op(op));
// Apply mask using Gfx functions // Apply mask using Gfx functions
for (y = 0, my = 0; y < h; y++, my++, msk += mw) for (y = 0, my = 0; y < h; y++, my++)
{ {
if (my >= mh) if (my >= mh) my = 0;
{
my = 0; src = src_map + (y * src_stride);
msk = mask->image.data; msk = (uint32_t *) (msk_map + (my * msk_stride));
} dst = (uint32_t *) (dst_map + (y * dst_stride));
for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize) for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize)
{ {
memset(span, 0, stepsize * sizeof(DATA32)); memset(span, 0, stepsize * sizeof(uint32_t));
func1(msk, src, 0, span, stepsize); func1(msk, src, 0, span, stepsize);
func2(span, NULL, color2, dst, stepsize); func2(span, NULL, color, dst, stepsize);
} }
r = w - (stepsize * stepcount); x = stepsize * stepcount;
if (r > 0) if (x < w)
{ {
memset(span, 0, r * sizeof(DATA32)); memset(span, 0, (w - x) * sizeof(uint32_t));
func1(msk, src, 0, span, r); func1(msk, src, 0, span, w - x);
func2(span, NULL, color2, dst, r); func2(span, NULL, color, dst, w - x);
dst += r;
src += r;
} }
} }
free(span); ret = EINA_TRUE;
return EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(msk_fb->buffer, ector_buffer_unmap(msk_map, msk_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }
static Eina_Bool static Eina_Bool
_mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd) _mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd)
{ {
unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
uint8_t *src, *msk, *span, *src_map = NULL, *msk_map = NULL, *dst_map = NULL;
Evas_Filter_Buffer *msk_fb;
RGBA_Gfx_Func func; RGBA_Gfx_Func func;
Alpha_Gfx_Func span_func; Alpha_Gfx_Func span_func;
RGBA_Image *in, *out, *mask; uint32_t *dst;
DATA8 *src, *msk, *span; uint32_t color;
DATA32 *dst;
DATA32 color;
Efl_Gfx_Render_Op op = cmd->draw.rop; Efl_Gfx_Render_Op op = cmd->draw.rop;
int w, h, mw, mh, y, my, r; int w, h, mw, mh, x, y, my;
int stepsize, stepcount, step; int stepsize, stepcount, step;
Eina_Bool ret = EINA_FALSE;
/* Mechanism: /* Mechanism:
* 1. Copy mask to span buffer (1 line) * 1. Copy mask to span buffer (1 line)
@ -275,155 +279,147 @@ _mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd)
* FIXME: Could probably be optimized into a single op :) * FIXME: Could probably be optimized into a single op :)
*/ */
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
mw = cmd->mask->w; mw = cmd->mask->w;
mh = cmd->mask->h; mh = cmd->mask->h;
src = in->image.data8;
dst = out->image.data;
color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B); color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
stepsize = MIN(mw, w);
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE); stepcount = w / stepsize;
span = alloca(stepsize * sizeof(uint32_t));
// Stretch if necessary. // Stretch if necessary.
if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
mw = w; mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h; mh = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh); msk_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
fb->locked = EINA_FALSE; msk_fb->locked = EINA_FALSE;
mask = fb->backing;
} }
else msk_fb = cmd->mask;
msk = mask->image.data8; src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ALPHA, &src_stride);
stepsize = MIN(mw, w); msk_map = _buffer_map_all(msk_fb->buffer, &msk_len, E_READ, E_ARGB, &msk_stride);
stepcount = w / stepsize; dst_map = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
span = malloc(stepsize * sizeof(DATA8)); EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map && msk_map, end);
func = evas_common_gfx_func_composite_mask_color_span_get(color, out->cache_entry.flags.alpha, 1, _gfx_to_evas_render_op(op)); func = evas_common_gfx_func_composite_mask_color_span_get(color, 1, 1, _gfx_to_evas_render_op(op));
span_func = efl_draw_alpha_func_get(cmd->draw.rop, EINA_TRUE); span_func = efl_draw_alpha_func_get(cmd->draw.rop, EINA_TRUE);
for (y = 0, my = 0; y < h; y++, my++, msk += mw) for (y = 0, my = 0; y < h; y++, my++, msk += mw)
{ {
if (my >= mh) if (my >= mh) my = 0;
{
my = 0; src = src_map + (y * src_stride);
msk = mask->image.data8; msk = msk_map + (my * msk_stride);
} dst = (uint32_t *) (dst_map + (y * dst_stride));
for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize) for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize)
{ {
memcpy(span, msk, stepsize * sizeof(DATA8)); memcpy(span, msk, stepsize * sizeof(uint8_t));
span_func(src, span, stepsize); span_func(src, span, stepsize);
func(NULL, span, color, dst, stepsize); func(NULL, span, color, dst, stepsize);
} }
r = w - (stepsize * stepcount); x = stepsize * stepcount;
if (r > 0) if (x < w)
{ {
memcpy(span, msk, r * sizeof(DATA8)); memcpy(span, msk, (w - x) * sizeof(uint8_t));
span_func(src, span, r); span_func(src, span, w - x);
func(NULL, span, color, dst, r); func(NULL, span, color, dst, w -x);
dst += r;
src += r;
} }
} }
free(span); ret = EINA_TRUE;
return EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(msk_fb->buffer, ector_buffer_unmap(msk_map, msk_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }
static Eina_Bool static Eina_Bool
_mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd) _mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd)
{ {
unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
uint8_t *src_map = NULL, *msk_map = NULL, *dst_map = NULL;
Draw_Func_ARGB_Mix3 func; Draw_Func_ARGB_Mix3 func;
RGBA_Image *in, *out, *mask; Evas_Filter_Buffer *msk_fb;
DATA32 *dst, *msk, *src; uint32_t *dst, *msk, *src;
int w, h, mw, mh, y, my, r; int w, h, mw, mh, x, y, my;
int stepsize, stepcount, step; int stepsize, stepcount, step;
DATA32 color; Eina_Bool ret = EINA_FALSE;
uint32_t color;
/* Mechanism: /* Mechanism:
* 1. Stretch mask as requested in fillmode * 1. Stretch mask as requested in fillmode
* 2. Mix 3 colors * 2. Mix 3 colors
*/ */
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
mw = cmd->mask->w; mw = cmd->mask->w;
mh = cmd->mask->h; mh = cmd->mask->h;
src = in->image.data; color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
dst = out->image.data; stepsize = MIN(mw, w);
stepcount = w / stepsize;
// Stretch if necessary. // Stretch if necessary.
if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY)) if ((mw != w || mh != h) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
{ {
Evas_Filter_Buffer *fb;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
mw = w; mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h; mh = h;
BUFFERS_LOCK(); BUFFERS_LOCK();
fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh); msk_fb = evas_filter_buffer_scaled_get(cmd->ctx, cmd->mask, mw, mh);
BUFFERS_UNLOCK(); BUFFERS_UNLOCK();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
fb->locked = EINA_FALSE; msk_fb->locked = EINA_FALSE;
mask = fb->backing;
} }
else msk_fb = cmd->mask;
color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B); src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ARGB, &src_stride);
msk = mask->image.data; msk_map = _buffer_map_all(msk_fb->buffer, &msk_len, E_READ, E_ARGB, &msk_stride);
dst_map = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map && msk_map, end);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(msk, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
stepsize = MIN(mw, w);
stepcount = w / stepsize;
func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color); func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color);
// Apply mask using Gfx functions // Apply mask using Gfx functions
for (y = 0, my = 0; y < h; y++, my++, msk += mw) for (y = 0, my = 0; y < h; y++, my++)
{ {
if (my >= mh) if (my >= mh) my = 0;
{
my = 0; src = (uint32_t *) (src_map + (y * src_stride));
msk = mask->image.data; msk = (uint32_t *) (msk_map + (my * msk_stride));
} dst = (uint32_t *) (dst_map + (y * dst_stride));
for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize) for (step = 0; step < stepcount; step++, dst += stepsize, src += stepsize)
func(dst, src, msk, stepsize, color); func(dst, src, msk, stepsize, color);
r = w - (stepsize * stepcount); x = stepsize * stepcount;
if (r > 0) if (x < w)
{ {
func(dst, src, msk, r, color); func(dst, src, msk, w - x, color);
dst += r;
src += r;
} }
} }
return EINA_TRUE; ret = EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(src_map, src_len));
eo_do(msk_fb->buffer, ector_buffer_unmap(msk_map, msk_len));
eo_do(cmd->output->buffer, ector_buffer_unmap(dst_map, dst_len));
return ret;
} }

View File

@ -230,7 +230,7 @@ struct _Evas_Filter_Buffer
Evas_Object *source; Evas_Object *source;
Eina_Stringshare *source_name; Eina_Stringshare *source_name;
RGBA_Image *backing; Ector_Generic_Buffer *buffer;
void *glimage; void *glimage;
int w, h; int w, h;
@ -275,4 +275,20 @@ int evas_filter_smallest_pow2_larger_than(int val);
void evas_filter_parser_shutdown(void); void evas_filter_parser_shutdown(void);
#define E_READ ECTOR_BUFFER_ACCESS_FLAG_READ
#define E_WRITE ECTOR_BUFFER_ACCESS_FLAG_WRITE
#define E_ALPHA EFL_GFX_COLORSPACE_GRY8
#define E_ARGB EFL_GFX_COLORSPACE_ARGB8888
static inline void *
_buffer_map_all(Ector_Buffer *buf, unsigned int *len, Ector_Buffer_Access_Flag mode, Efl_Gfx_Colorspace cspace, unsigned int *stride)
{
void *ret = NULL;
int w, h;
if (!buf) return NULL;
eo_do(buf, ector_buffer_size_get(&w, &h);
ret = ector_buffer_map(len, mode, 0, 0, w, h, cspace, stride));
return ret;
}
#endif // EVAS_FILTER_PRIVATE_H #endif // EVAS_FILTER_PRIVATE_H

View File

@ -10,27 +10,22 @@
static Eina_Bool static Eina_Bool
_vflip_cpu(Evas_Filter_Command *cmd) _vflip_cpu(Evas_Filter_Command *cmd)
{ {
size_t datasize, stride; unsigned int src_len, src_stride, dst_len, dst_stride;
DATA8 *in, *out, *span = NULL; uint8_t *in, *out = NULL, *span = NULL;
int w, h, sy, dy, oy, center, t, b, objh; int w, h, sy, dy, oy, center, t, b, objh;
int s0, s1, d0, d1; int s0, s1, d0, d1;
Eina_Bool ret = 0;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
w = cmd->input->w; w = cmd->input->w;
h = cmd->input->h; h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->w == w, EINA_FALSE); in = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, cmd->output->alpha_only ? E_ALPHA : E_ARGB, &src_stride);
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->h == h, EINA_FALSE); if (cmd->input->buffer != cmd->output->buffer)
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->alpha_only == cmd->input->alpha_only, EINA_FALSE); out = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, cmd->output->alpha_only ? E_ALPHA : E_ARGB, &dst_stride);
in = ((RGBA_Image *) cmd->input->backing)->image.data8; EINA_SAFETY_ON_FALSE_GOTO(cmd->output->w == w, end);
out = ((RGBA_Image *) cmd->output->backing)->image.data8; EINA_SAFETY_ON_FALSE_GOTO(cmd->output->h == h, end);
datasize = cmd->input->alpha_only ? sizeof(DATA8) : sizeof(DATA32); EINA_SAFETY_ON_FALSE_GOTO(src_stride <= dst_stride, end);
stride = w * datasize; EINA_SAFETY_ON_FALSE_GOTO(cmd->output->alpha_only == cmd->input->alpha_only, end);
oy = cmd->draw.oy; oy = cmd->draw.oy;
t = cmd->ctx->padt; t = cmd->ctx->padt;
@ -53,28 +48,32 @@ _vflip_cpu(Evas_Filter_Command *cmd)
if (in == out) if (in == out)
{ {
span = malloc(stride); span = alloca(src_stride);
if (!span) return EINA_FALSE; if (!span) goto end;
} }
for (sy = s0, dy = d0; (dy >= d1) && (sy <= s1); sy++, dy--) for (sy = s0, dy = d0; (dy >= d1) && (sy <= s1); sy++, dy--)
{ {
DATA8* src = in + stride * sy; uint8_t* src = in + src_stride * sy;
DATA8* dst = out + stride * dy; uint8_t* dst = out + dst_stride * dy;
if (in == out) if (in == out)
{ {
if (src == dst) break; if (src == dst) break;
memcpy(span, dst, stride); memcpy(span, dst, src_stride);
memcpy(dst, src, stride); memcpy(dst, src, src_stride);
memcpy(src, span, stride); memcpy(src, span, src_stride);
if (sy >= center) break; if (sy >= center) break;
} }
else else
memcpy(dst, src, stride); memcpy(dst, src, src_stride);
} }
free(span); ret = EINA_TRUE;
return EINA_TRUE;
end:
eo_do(cmd->input->buffer, ector_buffer_unmap(in, src_len));
if (in != out) eo_do(cmd->output->buffer, ector_buffer_unmap(out, dst_len));
return ret;
} }
Evas_Filter_Apply_Func Evas_Filter_Apply_Func

View File

@ -8,76 +8,35 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
unsigned w, unsigned h) unsigned w, unsigned h)
{ {
Evas_Filter_Buffer *fb; Evas_Filter_Buffer *fb;
Image_Entry *dstdata = NULL; RGBA_Image *dstim, *srcim;
Image_Entry *srcdata; RGBA_Draw_Context dc;
void *drawctx; Eina_Bool ok;
srcdata = evas_filter_buffer_backing_get(ctx, src->id); // only for RGBA
EINA_SAFETY_ON_NULL_RETURN_VAL(srcdata, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(!src->alpha_only, NULL);
if (src->alpha_only) srcim = evas_filter_buffer_backing_get(ctx, src->id);
{ EINA_SAFETY_ON_NULL_RETURN_VAL(srcim, NULL);
// There is no supporting function in Evas for alpha scaling...
// but guess what? There is also no use case in the filters :)
CRI("Alpha buffer scaling is not supported");
return NULL;
}
fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only); fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
if (!fb) return NULL; EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
dstdata = evas_filter_buffer_backing_get(ctx, fb->id); dstim = evas_filter_buffer_backing_get(ctx, fb->id);
if (!dstdata) EINA_SAFETY_ON_NULL_RETURN_VAL(dstim, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL((dstim->cache_entry.w == w) &&
(dstim->cache_entry.h == h), NULL);
memset(&dc, 0, sizeof(dc));
dc.sli.h = 1;
dc.render_op = EVAS_RENDER_COPY;
ok = evas_common_scale_rgba_in_to_out_clip_smooth
(srcim, dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
if (!ok)
{ {
CRI("No backing found for buffer %d", fb->id); ERR("RGBA Image scaling failed.");
return NULL; return NULL;
}
if ((dstdata->w != w) || (dstdata->h != h))
{
CRI("Buffer size mismatch: got %dx%d requested %dx%d",
dstdata->w, dstdata->h, w, h);
return NULL;
}
if (ctx->gl_engine)
{
RGBA_Image *s = (RGBA_Image *) srcdata;
RGBA_Image *d = (RGBA_Image *) dstdata;
EINA_SAFETY_ON_NULL_RETURN_VAL(s->image.data, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(d->image.data, NULL);
if (src->w == (int) w && src->h == (int) h)
memcpy(d->image.data, s->image.data, w * h * 4);
else
{
Eina_Bool ok;
RGBA_Draw_Context dc;
memset(&dc, 0, sizeof(dc));
dc.sli.h = 1;
dc.render_op = EVAS_RENDER_COPY;
ok = evas_common_scale_rgba_in_to_out_clip_smooth
(s, d, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
if (!ok)
{
ERR("RGBA Image scaling failed.");
return NULL;
}
}
}
else
{
drawctx = ENFN->context_new(ENDT);
ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY);
ENFN->image_draw(ENDT, drawctx, dstdata, srcdata,
0, 0, src->w, src->h, // src
0, 0, w, h, // dst
EINA_TRUE, // smooth
EINA_FALSE); // Not async
ENFN->context_free(ENDT, drawctx);
} }
return fb; return fb;

View File

@ -143,7 +143,6 @@ void evas_filter_context_post_run_callback_set(Evas_Filter_C
Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx); Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only); int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only);
int evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image);
void *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid); void *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid);
void *evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid); void *evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid);
Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer); Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer);

View File

@ -1450,7 +1450,8 @@ struct _Evas_Func
Ector_Surface *(*ector_create) (void *data); Ector_Surface *(*ector_create) (void *data);
void (*ector_destroy) (void *data, Ector_Surface *surface); void (*ector_destroy) (void *data, Ector_Surface *surface);
Ector_Buffer *(*ector_buffer_new) (void *data, Evas *e, void *engine_image); // free it with eo_del Ector_Buffer *(*ector_buffer_wrap) (void *data, Evas *e, void *engine_image);
Ector_Buffer *(*ector_buffer_new) (void *data, Evas *e, void *pixels, int width, int height, int stride, Efl_Gfx_Colorspace cspace, Eina_Bool writeable, int l, int r, int t, int b, Ector_Buffer_Flag flags);
void (*ector_begin) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, int x, int y, Eina_Bool do_async); void (*ector_begin) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, int x, int y, Eina_Bool do_async);
void (*ector_renderer_draw) (void *data, void *context, void *surface, void *engine_data, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async); void (*ector_renderer_draw) (void *data, void *context, void *surface, void *engine_data, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async);
void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, Eina_Bool do_async); void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, Eina_Bool do_async);

View File

@ -2465,17 +2465,20 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector)
} }
static Ector_Buffer * static Ector_Buffer *
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *engine_image) eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image)
{ {
Evas_GL_Image *im = engine_image;
Ector_Buffer *buf = NULL;
if (!im) return NULL;
#warning FIXME: implement me #warning FIXME: implement me
(void) e; return NULL;
}
return buf; static Ector_Buffer *
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *pixels,
int width, int height, int stride,
Efl_Gfx_Colorspace cspace, Eina_Bool writeable,
int l, int r, int t, int b, Ector_Buffer_Flag flags)
{
#warning FIXME: implement me
return NULL;
} }
static Efl_Gfx_Render_Op static Efl_Gfx_Render_Op
@ -2836,6 +2839,7 @@ module_open(Evas_Module *em)
ORD(ector_create); ORD(ector_create);
ORD(ector_destroy); ORD(ector_destroy);
ORD(ector_buffer_wrap);
ORD(ector_buffer_new); ORD(ector_buffer_new);
ORD(ector_begin); ORD(ector_begin);
ORD(ector_renderer_draw); ORD(ector_renderer_draw);

View File

@ -49,7 +49,7 @@ _evas_ector_software_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect
eo_do(obj, ector_buffer_pixels_set(im->image.data, eo_do(obj, ector_buffer_pixels_set(im->image.data,
im->cache_entry.w, im->cache_entry.h, 0, im->cache_entry.w, im->cache_entry.h, 0,
_evas_to_gfx_render_op(im->cache_entry.space), im->cache_entry.space,
EINA_TRUE, 0, 0, 0, 0)); EINA_TRUE, 0, 0, 0, 0));
} }

View File

@ -3758,7 +3758,7 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector)
} }
static Ector_Buffer * static Ector_Buffer *
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *engine_image) eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image)
{ {
Image_Entry *ie = engine_image; Image_Entry *ie = engine_image;
Ector_Buffer *buf = NULL; Ector_Buffer *buf = NULL;
@ -3771,6 +3771,22 @@ eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *engine_image)
return buf; return buf;
} }
static Ector_Buffer *
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *pixels,
int width, int height, int stride,
Efl_Gfx_Colorspace cspace, Eina_Bool writeable,
int l, int r, int t, int b,
Ector_Buffer_Flag flags EINA_UNUSED)
{
Ector_Buffer *buf = NULL;
buf = eo_add(ECTOR_SOFTWARE_BUFFER_CLASS, e,
ector_buffer_pixels_set(pixels, width, height, stride, cspace,
writeable, l, r, t, b));
return buf;
}
static Efl_Gfx_Render_Op static Efl_Gfx_Render_Op
_evas_render_op_to_ector_rop(Evas_Render_Op op) _evas_render_op_to_ector_rop(Evas_Render_Op op)
{ {
@ -4182,6 +4198,7 @@ static Evas_Func func =
NULL, // eng_texture_image_get NULL, // eng_texture_image_get
eng_ector_create, eng_ector_create,
eng_ector_destroy, eng_ector_destroy,
eng_ector_buffer_wrap,
eng_ector_buffer_new, eng_ector_buffer_new,
eng_ector_begin, eng_ector_begin,
eng_ector_renderer_draw, eng_ector_renderer_draw,