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

View File

@ -21,25 +21,28 @@
#endif
#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);
static void _buffer_free(Evas_Filter_Buffer *fb);
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_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)
typedef struct _Evas_Filter_Thread_Command Evas_Filter_Thread_Command;
struct _Evas_Filter_Thread_Command
static inline void *
_evas_image_get(Ector_Buffer *buf)
{
Evas_Filter_Context *ctx;
RGBA_Image *src, *mask, *dst;
Evas_Filter_Apply_Func func;
};
void *image = NULL;
if (!buf) return NULL;
eo_do(buf, evas_ector_buffer_engine_image_get(NULL, &image));
return image;
}
/* Main functions */
@ -67,6 +70,11 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async)
* better and implement filters direcly with shaders.
*/
ctx->gl_engine = (evas->engine.func->gl_surface_read_pixels != NULL);
if (ctx->gl_engine)
{
// FIXME!!!
CRI("gl support not implemented");
}
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
}
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
_filter_buffer_backing_free(Evas_Filter_Buffer *fb)
{
if (!fb) return;
_backing_free(fb->ctx, fb->backing);
if (fb->glimage)
fb->ENFN->image_free(fb->ENDT, fb->glimage);
fb->backing = NULL;
fb->glimage = NULL;
if (!fb || !fb->buffer) return;
eo_del(fb->buffer);
fb->buffer = NULL;
}
/* GL engine stuff: read-back from texture */
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_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_unlock, EINA_FALSE);
fb->backing = _rgba_image_alloc(fb, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(fb->backing, EINA_FALSE);
fb->buffer = _ector_buffer_create(fb, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(fb->buffer, EINA_FALSE);
ok = fb->ENFN->gl_surface_lock(fb->ENDT, glimage);
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);
return ok;
#endif
}
/** @hidden private render proxy objects */
void
evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
Eina_Bool do_async)
evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx EINA_UNUSED, Eo *eo_obj EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
CRI("not implemented");
return;
#if 0
Evas_Object_Protected_Data *source;
Evas_Object_Protected_Data *obj;
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;
XDBG("Source has dimensions %dx%d (buffer %d)", fb->w, fb->h, fb->id);
}
#endif
}
void
@ -257,63 +248,43 @@ _buffer_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only)
return fb;
}
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)
{
Evas_Colorspace cspace;
RGBA_Image *image;
size_t sz;
Image_Entry *ie;
cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888;
if (!fb->ctx->gl_engine)
// FIXME: We still rely on evas image structs (scaling and target render)
// 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)
{
image = fb->ENFN->image_new_from_copied_data
(fb->ENDT, fb->w, fb->h, NULL, EINA_TRUE, cspace);
}
else
{
image = fb->ENFN->image_new_from_data
(fb->ENDT, fb->w, fb->h, data, EINA_TRUE, cspace);
}
// no copy
ie = evas_cache_image_data(evas_common_image_cache_get(), fb->w, fb->h,
data, EINA_TRUE, cspace);
if (!ie) return NULL;
}
else
{
// FIXME: Directly calling the alloc functions since we want to use sw surfaces.
if (!data)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
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);
}
// alloc buffer
ie = evas_cache_image_copied_data(evas_common_image_cache_get(), fb->w, fb->h,
NULL, EINA_TRUE, cspace);
if (!ie) return NULL;
data = ((RGBA_Image *) ie)->image.data;
memset(data, 0, fb->w * fb->h * (fb->alpha_only ? 1 : 4));
}
if (!image) return NULL;
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;
return fb->ENFN->ector_buffer_wrap(fb->ENDT, fb->ctx->evas->evas, ie);
}
Eina_Bool
@ -404,7 +375,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
EINA_LIST_FOREACH(ctx->buffers, li, fb)
{
if (fb->backing || fb->source || fb->glimage)
if (fb->buffer || fb->source || fb->glimage)
continue;
if (!fb->w && !fb->h)
@ -413,10 +384,10 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx)
continue;
}
fb->backing = _rgba_image_alloc(fb, NULL);
XDBG("Allocating buffer #%d of size %ux%u %s",
fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba");
if (!fb->backing) goto alloc_fail;
fb->buffer = _ector_buffer_create(fb, NULL);
XDBG("Allocated buffer #%d of size %ux%u %s: %p",
fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba", fb->buffer);
if (!fb->buffer) goto alloc_fail;
}
return EINA_TRUE;
@ -457,35 +428,29 @@ _filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data,
if (w <= 0 || h <= 0)
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?
fb->alpha_only = alpha_only;
fb->w = w;
fb->h = h;
fb->backing = _rgba_image_alloc(fb, data);
return (fb->backing != NULL);
fb->buffer = _ector_buffer_create(fb, data);
return (fb->buffer != NULL);
}
int
evas_filter_buffer_image_new(Evas_Filter_Context *ctx, void *image)
static int
_filter_buffer_new_from_evas_surface(Evas_Filter_Context *ctx, void *image)
{
Evas_Filter_Buffer *fb;
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));
if (!fb) return -1;
fb->id = ++(ctx->last_buffer_id);
fb->ctx = ctx;
if (!ctx->gl_engine)
fb->backing = image;
else
fb->glimage = image;
fb->buffer = ENFN->ector_buffer_wrap(ENDT, ctx->evas->evas, image);
ENFN->image_size_get(ENDT, image, &fb->w, &fb->h);
fb->alpha_only = (ENFN->image_colorspace_get(ENDT, image)
== EVAS_COLORSPACE_GRY8);
@ -544,12 +509,12 @@ _filter_buffer_get(Evas_Filter_Context *ctx, int bufid)
void *
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);
if (!buffer) return NULL;
fb = _filter_buffer_get(ctx, bufid);
if (!fb) return NULL;
return buffer->backing;
return _evas_image_get(fb->buffer);
}
void *
@ -557,15 +522,10 @@ evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid)
{
Evas_Filter_Buffer *fb;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
fb = _filter_buffer_get(ctx, bufid);
if (!fb) return NULL;
if (ctx->gl_engine)
return fb->ENFN->image_ref(fb->ENDT, fb->glimage);
else
return fb->ENFN->image_ref(fb->ENDT, fb->backing);
return fb->ENFN->image_ref(fb->ENDT, _evas_image_get(fb->buffer));
}
Eina_Bool
@ -577,11 +537,11 @@ evas_filter_buffer_backing_release(Evas_Filter_Context *ctx,
if (ctx->async)
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
_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;
}
@ -1345,12 +1305,6 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx,
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);
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);
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.y = y;
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->target.mask = mask;
#if 0
if (ctx->gl_engine)
{
// 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)",
ctx->target.bufid, surface, fb->id, fb->backing, fb->glimage);
}
#endif
return EINA_TRUE;
}
@ -1418,7 +1374,7 @@ static Eina_Bool
_filter_target_render(Evas_Filter_Context *ctx)
{
Evas_Filter_Buffer *src, *dst;
void *drawctx, *image, *surface;
void *drawctx, *image = NULL, *surface = NULL;
int cx, cy, cw, ch;
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(dst, EINA_FALSE);
if (!ctx->gl_engine)
{
drawctx = ENFN->context_new(ENDT);
surface = dst->backing;
image = src->backing;
}
else
#if 0
if (ctx->gl_engine)
{
drawctx = ctx->target.context;
surface = dst->glimage;
@ -1456,9 +1407,18 @@ _filter_target_render(Evas_Filter_Context *ctx)
}
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(surface, EINA_FALSE);
// FIXME: Use ector buffer RENDERER here
if (ctx->target.clip_use)
{
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;
Evas_Filter_Buffer *fb;
void *surface;
void *surface = NULL;
fb = _filter_buffer_get(ctx, bufid);
if (!fb) return EINA_FALSE;
surface = fb->backing;
surface = _evas_image_get(fb->buffer);
if (!surface) return EINA_FALSE;
if (!ctx->gl_engine)
@ -1771,10 +1729,7 @@ end:
DEBUG_TIME_END();
EINA_LIST_FREE(ctx->post_run.buffers_to_free, buffer)
{
if (ctx->gl_engine)
ENFN->image_free(ENDT, buffer);
}
ENFN->image_free(ENDT, buffer);
return ok;
}

View File

@ -1,33 +1,37 @@
#include "evas_filter.h"
#include "evas_filter_private.h"
#include "evas_blend_private.h"
#include "ector_buffer.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)
#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);
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);
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, 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
{
Efl_Gfx_Render_Op rop;
DATA32 color;
uint32_t color;
};
#define LINELEN(stride, ptr) (stride / (sizeof(*ptr)))
static Eina_Bool
_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 dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image;
RGBA_Image *dst = surface;
DATA8* srcdata = src->image.data8;
DATA8* dstdata = dst->image.data8;
const uint8_t *srcdata = src_map;
uint8_t *dstdata = dst_map;
Alpha_Gfx_Func func;
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);
EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
sw = src->cache_entry.w;
dw = dst->cache_entry.w;
sw = LINELEN(src_stride, srcdata);
dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw;
dstdata += dst_y * dw;
@ -53,28 +57,26 @@ _image_draw_cpu_alpha2alpha(void *data EINA_UNUSED, void *context,
static Eina_Bool
_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 dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image;
RGBA_Image *dst = surface;
DATA8* srcdata = src->image.data8;
DATA32* dstdata = dst->image.data;
uint8_t *srcdata = (uint8_t *) src_map;
uint32_t *dstdata = dst_map;
RGBA_Gfx_Func func;
int y, sw, dw;
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
(dc->color, dst->cache_entry.flags.alpha, 1, dc->rop);
func = evas_common_gfx_func_composite_mask_color_span_get(dc->color, 1, 1, _gfx_to_evas_render_op(dc->rop));
EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
sw = src->cache_entry.w;
dw = dst->cache_entry.w;
sw = LINELEN(src_stride, srcdata);
dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw;
dstdata += dst_y * dw;
@ -88,122 +90,18 @@ _image_draw_cpu_alpha2rgba(void *data EINA_UNUSED, void *context,
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
_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 dst_x, int dst_y, int dst_w, int dst_h,
int smooth EINA_UNUSED,
Eina_Bool do_async EINA_UNUSED)
{
struct Filter_Blend_Draw_Context *dc = context;
RGBA_Image *src = image;
RGBA_Image *dst = surface;
DATA32* srcdata = src->image.data;
DATA32* dstdata = dst->image.data;
uint32_t *srcdata = (uint32_t *) src_map;
uint32_t *dstdata = dst_map;
RGBA_Gfx_Func func;
int y, sw, dw;
@ -212,13 +110,13 @@ _image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context,
if (!dc->color)
return EINA_TRUE;
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
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);
sw = src->cache_entry.w;
dw = dst->cache_entry.w;
sw = LINELEN(src_stride, srcdata);
dw = LINELEN(dst_stride, dstdata);
srcdata += src_y * sw;
dstdata += dst_y * dw;
@ -232,6 +130,109 @@ _image_draw_cpu_rgba2rgba(void *data EINA_UNUSED, void *context,
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
_filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
{
@ -239,7 +240,7 @@ _filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
}
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);
}
@ -253,73 +254,19 @@ _filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
static Eina_Bool
_filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
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;
return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba2rgba);
}
static Eina_Bool
_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,
int sx, int sy,
int sw, int sh,
int dx, int dy,
int dw, int dh,
image_draw_func image_draw)
draw_func image_draw)
{
int right = 0, bottom = 0, left = 0, top = 0;
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)",
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
dx, dy, cols, rows, // dst
EINA_TRUE, // smooth
@ -477,7 +425,8 @@ _mapped_blend(void *data, void *drawctx,
dst_x, dst_y, dst_w, dst_h,
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,
dst_x, dst_y, dst_w, dst_h,
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->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;
else
return _filter_blend_cpu_mask_rgba;
}
if (cmd->output->alpha_only)
return _filter_blend_cpu_alpha;
else
{
if (cmd->output->alpha_only)
return _filter_blend_cpu_rgba2alpha;
else
return _filter_blend_cpu_rgba;
}
return _filter_blend_cpu_alpha2rgba;
}
else
{
CRI("Can't render to GL image for the moment!");
//return _filter_blend_opengl_generic;
return NULL;
if (cmd->output->alpha_only)
return _filter_blend_cpu_rgba2alpha;
else
return _filter_blend_cpu_rgba;
}
}

View File

@ -4,6 +4,8 @@
#include <math.h>
#include <time.h>
// FIXME: Add proper stride support
static int
_box_blur_auto_radius(int *radii, int r)
{
@ -45,7 +47,7 @@ _box_blur_auto_radius(int *radii, int r)
#endif
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();
@ -77,7 +79,7 @@ end:
}
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();
@ -108,64 +110,6 @@ 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"
#ifdef BUILD_MMX
#include "./blur/blur_box_alpha_i386.c"
@ -178,7 +122,7 @@ _box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
#endif
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();
@ -210,7 +154,7 @@ end:
}
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();
@ -242,61 +186,70 @@ end:
}
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};
unsigned int r;
void *src, *dst;
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;
r = 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);
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);
if (src && dst)
{
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,
in->cache_entry.w, in->cache_entry.h);
eo_do(cmd->input->buffer, ector_buffer_unmap(src, src_len));
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
_box_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
int radii[7] = {0};
unsigned int r;
return _box_blur_apply(cmd, 1, 0);
}
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);
static Eina_Bool
_box_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
{
return _box_blur_apply(cmd, 0, 1);
}
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.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;
static Eina_Bool
_box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
{
return _box_blur_apply(cmd, 1, 1);
}
/* Gaussian blur */
@ -342,165 +295,86 @@ _sin_blur_weights_get(int *weights, int *pow2_divider, int radius)
#define STEP 1
#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'
#define FUNCTION_NAME _gaussian_blur_vert_alpha_step
#define STEP loops
#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 STEP 1
#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 STEP loops
#include "./blur/blur_gaussian_rgba_.c"
static void
_gaussian_blur_vert_rgba(DATA32 *src, DATA32 *dst, int radius, int w, int h)
static Eina_Bool
_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 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));
_sin_blur_weights_get(weights, &pow2_div, radius);
DEBUG_TIME_BEGIN();
_gaussian_blur_vert_rgba_step(src, dst, radius, h, w, 1, weights, pow2_div);
DEBUG_TIME_END();
if (src && dst)
{
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
_gaussian_blur_horiz_apply_alpha(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
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;
return _gaussian_blur_apply(cmd, 0, 0);
}
static Eina_Bool
_gaussian_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
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;
return _gaussian_blur_apply(cmd, 1, 0);
}
static Eina_Bool
_gaussian_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
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;
return _gaussian_blur_apply(cmd, 0, 1);
}
static Eina_Bool
_gaussian_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
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;
return _gaussian_blur_apply(cmd, 1, 1);
}
/* Main entry point */

View File

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

View File

@ -5,23 +5,23 @@
static Eina_Bool
_filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
DATA32 *src, *dst, *d, *s;
DATA8 *curve;
unsigned int src_len, src_stride, dst_len, dst_stride;
void *src_map = NULL, *dst_map;
Eina_Bool ret = EINA_FALSE;
uint32_t *src, *dst, *d, *s;
uint8_t *curve;
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;
len = in->cache_entry.w * in->cache_entry.h;
len = dst_len / sizeof(uint32_t);
switch (cmd->curve.channel)
{
@ -38,11 +38,11 @@ _filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
case EVAS_FILTER_CHANNEL_RGB: break;
default:
ERR("Invalid color channel %d", (int) cmd->curve.channel);
return EINA_FALSE;
goto end;
}
if (src != dst)
memcpy(dst, src, len * sizeof(DATA32));
memcpy(dst, src, dst_len);
evas_data_argb_unpremul(dst, len);
// One channel (R, G or B)
@ -82,31 +82,39 @@ _filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
premul:
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
_filter_curve_cpu_alpha(Evas_Filter_Command *cmd)
{
RGBA_Image *in, *out;
DATA8 *src, *dst;
DATA8 *curve;
unsigned int src_len, src_stride, dst_len, dst_stride;
uint8_t *src, *dst, *curve;
void *src_map, *dst_map;
Eina_Bool ret = EINA_FALSE;
int k;
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.data8;
dst = out->image.data8;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
// 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_ALPHA, &src_stride);
dst_map = dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ALPHA, &dst_stride);
EINA_SAFETY_ON_FALSE_GOTO(src && dst && (src_len == dst_len), end);
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++];
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
@ -124,6 +132,8 @@ evas_filter_curve_cpu_func_get(Evas_Filter_Command *cmd)
if (cmd->input->alpha_only && cmd->output->alpha_only)
return _filter_curve_cpu_alpha;
CRI("Incompatible image formats");
return NULL;
// Rely on ector buffer's implicit conversion. not great but the command
// 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
_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 blend)
{
int x, y, map_x, map_y;
const int dx = RED;
const int dy = GREEN;
DATA8 *map;
uint8_t *map;
// FIXME: Add stride support
for (y = 0, map_y = 0; y < h; y++, map_y++)
{
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;
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;
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)
{
map_x = 0;
map = (DATA8 *) (map_start + map_y * map_w);
map = (uint8_t *) (map_start + map_y * map_w);
}
// x
@ -76,7 +78,7 @@ _filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity,
static void
_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 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 dy = GREEN;
Eina_Bool unpremul = EINA_FALSE;
DATA8 *map;
uint8_t *map;
for (y = 0, map_y = 0; y < h; y++, map_y++)
{
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;
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;
DATA32 col = 0;
uint32_t col = 0;
Eina_Bool out = 0;
// wrap (x)
if (map_x >= map_w)
{
map_x = 0;
map = (DATA8 *) (map_start + map_y * map_w);
map = (uint8_t *) (map_start + map_y * map_w);
}
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
{
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;
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)
{
DATA32 a = 256 - ALPHA_OF(col);
uint32_t a = 256 - ALPHA_OF(col);
*dst = col + MUL_256(a, *dst);
}
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
_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;
DATA8 *dst, *src;
DATA32 *map_start;
uint8_t *dst, *src;
uint32_t *map_start;
Eina_Bool stretch, smooth, blend;
Evas_Filter_Buffer *map_fb;
Eina_Bool ret = EINA_FALSE;
w = cmd->input->w;
h = cmd->input->h;
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_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;
smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR;
map_w = cmd->mask->w;
@ -223,26 +220,32 @@ _filter_displace_cpu_alpha(Evas_Filter_Command *cmd)
// Stretch if necessary.
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)
map_w = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
map_h = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
map_start = ((RGBA_Image *) fb->backing)->image.data;
EINA_SAFETY_ON_NULL_RETURN_VAL(map_fb, EINA_FALSE);
map_fb->locked = EINA_FALSE;
}
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,
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
_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;
DATA32 *dst, *src, *map_start;
uint32_t *dst, *src, *map_start;
Eina_Bool stretch, smooth, blend;
Evas_Filter_Buffer *map_fb;
Eina_Bool ret = EINA_FALSE;
w = cmd->input->w;
h = cmd->input->h;
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_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;
smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR;
map_w = cmd->mask->w;
@ -283,26 +281,32 @@ _filter_displace_cpu_rgba(Evas_Filter_Command *cmd)
// Stretch if necessary.
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)
map_w = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
map_h = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
map_start = ((RGBA_Image *) fb->backing)->image.data;
EINA_SAFETY_ON_NULL_RETURN_VAL(map_fb, EINA_FALSE);
map_fb->locked = EINA_FALSE;
}
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,
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

View File

@ -1,14 +1,17 @@
#include "evas_filter_private.h"
#include "draw.h"
static Eina_Bool
_fill_cpu(Evas_Filter_Command *cmd)
{
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 y = MAX(0, cmd->draw.clip.y);
DATA8 *ptr = ((RGBA_Image *) fb->backing)->image.data8;
int w, h, k, j;
uint32_t color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
unsigned int stride, len;
int w, h, k;
uint8_t *ptr;
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);
}
ptr += y * step * fb->w;
if ((fb->alpha_only)
|| (!cmd->draw.R && !cmd->draw.G && !cmd->draw.B && !cmd->draw.A)
|| ((cmd->draw.R == 0xff) && (cmd->draw.G == 0xff)
&& (cmd->draw.B == 0xff) && (cmd->draw.A == 0xff)))
ptr = _buffer_map_all(fb->buffer, &len, E_WRITE, fb->alpha_only ? E_ALPHA : E_ARGB, &stride);
if (!ptr) return EINA_FALSE;
ptr += y * stride;
if (fb->alpha_only)
{
for (k = 0; k < h; k++)
{
memset(ptr + (x * step), cmd->draw.A, step * w);
ptr += step * fb->w;
ptr += stride;
}
}
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 (j = 0; j < w; j++)
*dst++ = color;
dst += fb->w - w;
uint32_t *dst = ((uint32_t *) (ptr + (y + k) * stride)) + x;
draw_memset32(dst, color, w);
}
}
eo_do(fb->buffer, ector_buffer_unmap(ptr, len));
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->output, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->backing, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->buffer, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->buffer, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->buffer, 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->h == cmd->output->h, NULL);
@ -53,12 +53,14 @@ evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd)
static Eina_Bool
_mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
{
Alpha_Gfx_Func func;
RGBA_Image *in, *out, *mask;
DATA8 *src, *dst, *msk;
unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
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 stepsize, stepcount, step;
Eina_Bool ret = EINA_FALSE;
/* Mechanism:
* 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 :)
*/
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w;
h = cmd->input->h;
mw = cmd->mask->w;
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);
stepcount = w / stepsize;
// Stretch if necessary.
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)
mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
mask = fb->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
msk_fb->locked = EINA_FALSE;
}
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
if (src != dst)
memcpy(dst, src, w * h * sizeof(DATA8));
if (cmd->input->buffer != cmd->output->buffer)
{
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
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)
{
my = 0;
msk = mask->image.data8;
}
if (my >= mh) my = 0;
msk = msk_map + (my * msk_stride);
dst = dst_map + (y * dst_stride);
for (step = 0; step < stepcount; step++, dst += stepsize)
func(msk, dst, stepsize);
@ -126,11 +129,16 @@ _mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
if (x < w)
{
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
@ -161,14 +169,16 @@ _mask_cpu_rgba_alpha_rgba(Evas_Filter_Command *cmd)
static Eina_Bool
_mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
{
RGBA_Gfx_Func func1, func2;
RGBA_Image *in, *out, *mask;
DATA8 *src;
DATA32 *dst, *msk, *span;
unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
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;
DATA32 color2;
Eina_Bool ret = EINA_FALSE;
uint32_t color;
/* Mechanism:
* 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 :)
*/
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w;
h = cmd->input->h;
mw = cmd->mask->w;
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);
stepsize = MIN(mw, w);
stepcount = w / stepsize;
span = alloca(stepsize * sizeof(uint32_t));
// Stretch if necessary.
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)
mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
mask = fb->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
msk_fb->locked = EINA_FALSE;
}
else msk_fb = cmd->mask;
color2 = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
msk = mask->image.data;
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ALPHA, &src_stride);
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);
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;
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));
func1 = evas_common_gfx_func_composite_pixel_mask_span_get(1, 0, 1, 1, EVAS_RENDER_COPY);
func2 = evas_common_gfx_func_composite_pixel_color_span_get(1, 0, color, 1, 1, _gfx_to_evas_render_op(op));
// 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)
{
my = 0;
msk = mask->image.data;
}
if (my >= mh) my = 0;
src = src_map + (y * src_stride);
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)
{
memset(span, 0, stepsize * sizeof(DATA32));
memset(span, 0, stepsize * sizeof(uint32_t));
func1(msk, src, 0, span, stepsize);
func2(span, NULL, color2, dst, stepsize);
func2(span, NULL, color, dst, stepsize);
}
r = w - (stepsize * stepcount);
if (r > 0)
x = stepsize * stepcount;
if (x < w)
{
memset(span, 0, r * sizeof(DATA32));
func1(msk, src, 0, span, r);
func2(span, NULL, color2, dst, r);
dst += r;
src += r;
memset(span, 0, (w - x) * sizeof(uint32_t));
func1(msk, src, 0, span, w - x);
func2(span, NULL, color, dst, w - x);
}
}
free(span);
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
_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;
Alpha_Gfx_Func span_func;
RGBA_Image *in, *out, *mask;
DATA8 *src, *msk, *span;
DATA32 *dst;
DATA32 color;
uint32_t *dst;
uint32_t color;
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;
Eina_Bool ret = EINA_FALSE;
/* Mechanism:
* 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 :)
*/
in = (RGBA_Image *) cmd->input->backing;
out = (RGBA_Image *) cmd->output->backing;
mask = (RGBA_Image *) cmd->mask->backing;
w = cmd->input->w;
h = cmd->input->h;
mw = cmd->mask->w;
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);
EINA_SAFETY_ON_FALSE_RETURN_VAL((w > 0) && (mw > 0), EINA_FALSE);
stepsize = MIN(mw, w);
stepcount = w / stepsize;
span = alloca(stepsize * sizeof(uint32_t));
// Stretch if necessary.
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)
mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
mask = fb->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
msk_fb->locked = EINA_FALSE;
}
else msk_fb = cmd->mask;
msk = mask->image.data8;
stepsize = MIN(mw, w);
stepcount = w / stepsize;
span = malloc(stepsize * sizeof(DATA8));
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ALPHA, &src_stride);
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);
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);
for (y = 0, my = 0; y < h; y++, my++, msk += mw)
{
if (my >= mh)
{
my = 0;
msk = mask->image.data8;
}
if (my >= mh) my = 0;
src = src_map + (y * src_stride);
msk = msk_map + (my * msk_stride);
dst = (uint32_t *) (dst_map + (y * dst_stride));
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);
func(NULL, span, color, dst, stepsize);
}
r = w - (stepsize * stepcount);
if (r > 0)
x = stepsize * stepcount;
if (x < w)
{
memcpy(span, msk, r * sizeof(DATA8));
span_func(src, span, r);
func(NULL, span, color, dst, r);
dst += r;
src += r;
memcpy(span, msk, (w - x) * sizeof(uint8_t));
span_func(src, span, w - x);
func(NULL, span, color, dst, w -x);
}
}
free(span);
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
_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;
RGBA_Image *in, *out, *mask;
DATA32 *dst, *msk, *src;
int w, h, mw, mh, y, my, r;
Evas_Filter_Buffer *msk_fb;
uint32_t *dst, *msk, *src;
int w, h, mw, mh, x, y, my;
int stepsize, stepcount, step;
DATA32 color;
Eina_Bool ret = EINA_FALSE;
uint32_t color;
/* Mechanism:
* 1. Stretch mask as requested in fillmode
* 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;
h = cmd->input->h;
mw = cmd->mask->w;
mh = cmd->mask->h;
src = in->image.data;
dst = out->image.data;
color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
stepsize = MIN(mw, w);
stepcount = w / stepsize;
// Stretch if necessary.
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)
mw = w;
if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
mh = h;
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();
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
fb->locked = EINA_FALSE;
mask = fb->backing;
EINA_SAFETY_ON_NULL_RETURN_VAL(msk_fb, EINA_FALSE);
msk_fb->locked = EINA_FALSE;
}
else msk_fb = cmd->mask;
color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
msk = mask->image.data;
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
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;
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ARGB, &src_stride);
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);
func = efl_draw_func_argb_mix3_get(cmd->draw.rop, color);
// 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)
{
my = 0;
msk = mask->image.data;
}
if (my >= mh) my = 0;
src = (uint32_t *) (src_map + (y * src_stride));
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)
func(dst, src, msk, stepsize, color);
r = w - (stepsize * stepcount);
if (r > 0)
x = stepsize * stepcount;
if (x < w)
{
func(dst, src, msk, r, color);
dst += r;
src += r;
func(dst, src, msk, w - x, color);
}
}
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;
Eina_Stringshare *source_name;
RGBA_Image *backing;
Ector_Generic_Buffer *buffer;
void *glimage;
int w, h;
@ -275,4 +275,20 @@ int evas_filter_smallest_pow2_larger_than(int val);
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

View File

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

View File

@ -8,76 +8,35 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
unsigned w, unsigned h)
{
Evas_Filter_Buffer *fb;
Image_Entry *dstdata = NULL;
Image_Entry *srcdata;
void *drawctx;
RGBA_Image *dstim, *srcim;
RGBA_Draw_Context dc;
Eina_Bool ok;
srcdata = evas_filter_buffer_backing_get(ctx, src->id);
EINA_SAFETY_ON_NULL_RETURN_VAL(srcdata, NULL);
// only for RGBA
EINA_SAFETY_ON_FALSE_RETURN_VAL(!src->alpha_only, NULL);
if (src->alpha_only)
{
// 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;
}
srcim = evas_filter_buffer_backing_get(ctx, src->id);
EINA_SAFETY_ON_NULL_RETURN_VAL(srcim, NULL);
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);
if (!dstdata)
dstim = evas_filter_buffer_backing_get(ctx, fb->id);
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);
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);
ERR("RGBA Image scaling failed.");
return NULL;
}
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);
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_steal(Evas_Filter_Context *ctx, int bufid);
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);
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_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);

View File

@ -2465,17 +2465,20 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector)
}
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
(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
@ -2836,6 +2839,7 @@ module_open(Evas_Module *em)
ORD(ector_create);
ORD(ector_destroy);
ORD(ector_buffer_wrap);
ORD(ector_buffer_new);
ORD(ector_begin);
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,
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));
}

View File

@ -3758,7 +3758,7 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector)
}
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;
Ector_Buffer *buf = NULL;
@ -3771,6 +3771,22 @@ eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *engine_image)
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
_evas_render_op_to_ector_rop(Evas_Render_Op op)
{
@ -4182,6 +4198,7 @@ static Evas_Func func =
NULL, // eng_texture_image_get
eng_ector_create,
eng_ector_destroy,
eng_ector_buffer_wrap,
eng_ector_buffer_new,
eng_ector_begin,
eng_ector_renderer_draw,