forked from enlightenment/efl
Evas filters: Final fix after the ector refactor
This implements a generic way of scaling buffers, using fake RGBA_Image wrapping ector buffer maps. The underlying algo is still the good old linear sw scaler. Now the filters *should* be back to their previous level of usability. Performance will probably be even worse than it was before, for GL, as more glReadPixels may be involved. Optimization now consists in actually implementing the filters with GL shaders.
This commit is contained in:
parent
13f66f8887
commit
c1b4728487
|
@ -778,6 +778,8 @@ CLEANFILES += \
|
|||
$(evas_gl_generic_eolian_c) \
|
||||
$(evas_gl_generic_eolian_h)
|
||||
|
||||
EXTRA_DIST += $(evas_gl_generic_eolian_files)
|
||||
|
||||
#evaseolianfilesdir = $(datadir)/eolian/include/evas-@VMAJ@
|
||||
#evaseolianfiles_DATA += $(evas_gl_generic_eolian_files)
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#define ENFN obj->layer->evas->engine.func
|
||||
#define ENDT obj->layer->evas->engine.data.output
|
||||
|
||||
#define FCOW_BEGIN(_pd) eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data))
|
||||
#define FCOW_END(_fcow, _pd) eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data), _fcow, EINA_TRUE)
|
||||
|
||||
typedef struct _Evas_Filter_Data Evas_Filter_Data;
|
||||
struct _Evas_Filter_Data
|
||||
{
|
||||
|
@ -21,9 +24,9 @@ static void
|
|||
_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
||||
{
|
||||
Eo *eo_obj = data;
|
||||
Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
|
||||
|
||||
// Destroy context as we won't reuse it.
|
||||
evas_filter_context_destroy(ctx);
|
||||
// FIXME: This needs to run in the main loop
|
||||
|
||||
// Redraw text with normal styles in case of failure
|
||||
if (!success)
|
||||
|
@ -39,6 +42,18 @@ _filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
|||
evas_object_coords_recalc(eo_obj, obj);
|
||||
evas_object_inform_call_resize(eo_obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
void *output = evas_filter_buffer_backing_steal(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->output = output;
|
||||
FCOW_END(fcow, pd);
|
||||
}
|
||||
|
||||
// Destroy context as we won't reuse it.
|
||||
evas_filter_context_destroy(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -76,9 +91,6 @@ _filter_source_hash_free_cb(void *data)
|
|||
free(pb);
|
||||
}
|
||||
|
||||
#define FCOW_BEGIN(_pd) eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data))
|
||||
#define FCOW_END(_fcow, _pd) eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(_pd->data), _fcow, EINA_TRUE)
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||
void *output, void *context, void *surface,
|
||||
|
@ -86,6 +98,10 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
{
|
||||
Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
|
||||
|
||||
// FIXME: Forcing sync render for all engines! (cb needs the main loop)
|
||||
if (do_async) WRN("Disarding async render flag!");
|
||||
do_async = EINA_FALSE;
|
||||
|
||||
if (!pd->data->invalid && (pd->data->chain || pd->data->code))
|
||||
{
|
||||
int X, Y, W, H, l = 0, r = 0, t = 0, b = 0;
|
||||
|
@ -94,7 +110,6 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
Eina_Bool ok;
|
||||
void *previous = pd->data->output;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
void *filter_output;
|
||||
|
||||
/* NOTE: Filter rendering is now done ENTIRELY on CPU.
|
||||
* So we rely on cache/cache2 to allocate a real image buffer,
|
||||
|
@ -236,8 +251,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
evas_filter_context_buffers_allocate_all(filter);
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||
|
||||
// Steal output and release previous
|
||||
filter_output = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||
// Release previous output
|
||||
evas_filter_buffer_backing_release(filter, previous);
|
||||
|
||||
// Request rendering from the object itself (child class)
|
||||
|
@ -252,7 +266,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
ok = evas_filter_run(filter);
|
||||
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->output = filter_output;
|
||||
fcow->output = NULL;
|
||||
fcow->changed = EINA_FALSE;
|
||||
fcow->async = do_async;
|
||||
if (!ok) fcow->invalid = EINA_TRUE;
|
||||
|
|
|
@ -209,6 +209,8 @@ _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data)
|
|||
flags = ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_CPU_WRITABLE;
|
||||
if (fb->id == EVAS_FILTER_BUFFER_INPUT_ID)
|
||||
flags |= ECTOR_BUFFER_FLAG_RENDERABLE;
|
||||
else if (fb->id == EVAS_FILTER_BUFFER_OUTPUT_ID)
|
||||
flags |= ECTOR_BUFFER_FLAG_DRAWABLE;
|
||||
|
||||
cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888;
|
||||
return fb->ENFN->ector_buffer_new(fb->ENDT, fb->ctx->evas->evas,
|
||||
|
|
|
@ -64,7 +64,7 @@ evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd)
|
|||
static Eina_Bool
|
||||
_mask_cpu_alpha_alpha_alpha(Evas_Filter_Command *cmd)
|
||||
{
|
||||
unsigned int src_len, src_stride, msk_len, msk_stride, dst_len, dst_stride;
|
||||
unsigned int src_len = 0, src_stride, msk_len = 0, msk_stride, dst_len = 0, dst_stride;
|
||||
Efl_Gfx_Render_Op render_op = cmd->draw.rop;
|
||||
Evas_Filter_Buffer *msk_fb;
|
||||
Alpha_Gfx_Func func;
|
||||
|
@ -225,7 +225,7 @@ _mask_cpu_alpha_rgba_rgba(Evas_Filter_Command *cmd)
|
|||
}
|
||||
else msk_fb = cmd->mask;
|
||||
|
||||
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ALPHA, &src_stride);
|
||||
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, 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);
|
||||
|
@ -316,8 +316,8 @@ _mask_cpu_alpha_alpha_rgba(Evas_Filter_Command *cmd)
|
|||
}
|
||||
else msk_fb = cmd->mask;
|
||||
|
||||
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);
|
||||
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ALPHA, &src_stride);
|
||||
msk_map = _buffer_map_all(msk_fb->buffer, &msk_len, E_READ, E_ALPHA, &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);
|
||||
|
||||
|
@ -400,7 +400,7 @@ _mask_cpu_rgba_rgba_rgba(Evas_Filter_Command *cmd)
|
|||
}
|
||||
else msk_fb = cmd->mask;
|
||||
|
||||
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_WRITE, E_ARGB, &src_stride);
|
||||
src_map = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, 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);
|
||||
|
|
|
@ -7,39 +7,65 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
|
|||
Evas_Filter_Buffer *src,
|
||||
unsigned w, unsigned h)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
RGBA_Image *dstim, *srcim;
|
||||
unsigned int src_len = 0, src_stride, dst_len = 0, dst_stride;
|
||||
uint8_t *src_map = NULL, *dst_map = NULL;
|
||||
Evas_Filter_Buffer *dst;
|
||||
RGBA_Image dstim, srcim;
|
||||
RGBA_Draw_Context dc;
|
||||
Eina_Bool ok;
|
||||
|
||||
// only for RGBA
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(!src->alpha_only, NULL);
|
||||
DBG("Scaling buffer from %dx%d to %dx%d, this is a slow operation!",
|
||||
src->w, src->h, w, h);
|
||||
DEBUG_TIME_BEGIN();
|
||||
|
||||
srcim = evas_filter_buffer_backing_get(ctx, src->id);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(srcim, NULL);
|
||||
// Get destination buffer
|
||||
dst = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, NULL);
|
||||
|
||||
fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
// Map input and output
|
||||
src_map = _buffer_map_all(src->buffer, &src_len, E_READ, E_ARGB, &src_stride);
|
||||
dst_map = _buffer_map_all(dst->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
|
||||
EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map, end);
|
||||
EINA_SAFETY_ON_FALSE_GOTO((src_stride == ((unsigned) src->w * 4)) &&
|
||||
(dst_stride == (w * 4)), end);
|
||||
|
||||
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);
|
||||
// Wrap as basic RGBA_Images
|
||||
memset(&dstim, 0, sizeof(dstim));
|
||||
dstim.cache_entry.w = w;
|
||||
dstim.cache_entry.h = h;
|
||||
dstim.cache_entry.flags.alpha = 1;
|
||||
dstim.cache_entry.flags.alpha_sparse = 0;
|
||||
dstim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
|
||||
dstim.image.data8 = dst_map;
|
||||
|
||||
memset(&srcim, 0, sizeof(srcim));
|
||||
srcim.cache_entry.w = src->w;
|
||||
srcim.cache_entry.h = src->h;
|
||||
srcim.cache_entry.flags.alpha = 1;
|
||||
srcim.cache_entry.flags.alpha_sparse = 0;
|
||||
srcim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
|
||||
srcim.image.data8 = src_map;
|
||||
|
||||
// Basic draw context
|
||||
memset(&dc, 0, sizeof(dc));
|
||||
dc.sli.h = 1;
|
||||
dc.render_op = EVAS_RENDER_COPY;
|
||||
|
||||
// Do the scale
|
||||
ok = evas_common_scale_rgba_in_to_out_clip_smooth
|
||||
(srcim, dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
|
||||
(&srcim, &dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
ERR("RGBA Image scaling failed.");
|
||||
return NULL;
|
||||
dst = NULL;
|
||||
}
|
||||
|
||||
return fb;
|
||||
end:
|
||||
if (src_map) eo_do(src->buffer, ector_buffer_unmap(src_map, src_len));
|
||||
if (dst_map) eo_do(dst->buffer, ector_buffer_unmap(dst_map, dst_len));
|
||||
DEBUG_TIME_END();
|
||||
return dst;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
|
|
|
@ -54,17 +54,6 @@ _pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_pixels_gry8_to_argb_convert(uint32_t *dst, const uint8_t *src, int len)
|
||||
{
|
||||
int k;
|
||||
for (k = 0; k < len; k++)
|
||||
{
|
||||
uint8_t s = *src++;
|
||||
*dst++ = ARGB_JOIN(s, s, s, s);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd,
|
||||
Evas *evas, void *image)
|
||||
|
@ -175,7 +164,7 @@ _evas_ector_gl_image_buffer_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Evas_E
|
|||
if (tofree)
|
||||
map->im = im;
|
||||
else
|
||||
map->im = ENFN->image_ref(ENDT, im);
|
||||
map->im = NULL;
|
||||
|
||||
len = w * h;
|
||||
if (cspace == EFL_GFX_COLORSPACE_GRY8)
|
||||
|
@ -218,7 +207,8 @@ _evas_ector_gl_image_buffer_ector_generic_buffer_unmap(Eo *obj EINA_UNUSED, Evas
|
|||
{
|
||||
CRI("Not implemented yet. Dropping pixel changes.");
|
||||
}
|
||||
ENFN->image_free(ENDT, map->im);
|
||||
if (map->im)
|
||||
ENFN->image_free(ENDT, map->im);
|
||||
if (map->allocated)
|
||||
free(map->ptr);
|
||||
return;
|
||||
|
|
|
@ -73,6 +73,12 @@ _evas_ector_gl_rgbaimage_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_
|
|||
goto end;
|
||||
|
||||
gc = re->window_gl_context_get(re->software.ob);
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cache2_image_cached(&pd->image->cache_entry))
|
||||
evas_cache2_image_ref(&pd->image->cache_entry);
|
||||
else
|
||||
#endif
|
||||
evas_cache_image_ref(&pd->image->cache_entry);
|
||||
pd->glim = evas_gl_common_image_new_from_rgbaimage(gc, pd->image, NULL, &err);
|
||||
if ((err != EVAS_LOAD_ERROR_NONE) || !pd->glim)
|
||||
{
|
||||
|
|
|
@ -2502,7 +2502,7 @@ eng_ector_buffer_new(void *data, Evas *evas, void *pixels,
|
|||
Ector_Buffer *buf = NULL;
|
||||
int iw = width + l + r;
|
||||
int ih = height + t + b;
|
||||
int pxs = (cspace = EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1;
|
||||
int pxs = (cspace == EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1;
|
||||
|
||||
if (stride && (stride != iw * pxs))
|
||||
WRN("stride support is not implemented for ector gl buffers at this point!");
|
||||
|
|
|
@ -3772,17 +3772,52 @@ eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image, Eina_
|
|||
}
|
||||
|
||||
static Ector_Buffer *
|
||||
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *pixels,
|
||||
eng_ector_buffer_new(void *data EINA_UNUSED, Evas *evas, 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;
|
||||
int pxs = (cspace == EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1;
|
||||
int iw = width + l + r;
|
||||
int ih = height + t + b;
|
||||
|
||||
buf = eo_add(ECTOR_SOFTWARE_BUFFER_CLASS, e,
|
||||
ector_buffer_pixels_set(pixels, width, height, stride, cspace,
|
||||
writeable, l, r, t, b));
|
||||
if ((flags & (ECTOR_BUFFER_FLAG_RENDERABLE | ECTOR_BUFFER_FLAG_DRAWABLE)) == 0)
|
||||
{
|
||||
buf = eo_add(ECTOR_SOFTWARE_BUFFER_CLASS, evas,
|
||||
ector_buffer_pixels_set(pixels, width, height, stride, cspace,
|
||||
writeable, l, r, t, b));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an RGBA Image as backing
|
||||
Image_Entry *ie;
|
||||
|
||||
if (pixels)
|
||||
{
|
||||
// no copy
|
||||
ie = evas_cache_image_data(evas_common_image_cache_get(), iw, ih,
|
||||
pixels, EINA_TRUE, (Evas_Colorspace) cspace);
|
||||
if (!ie) return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// alloc buffer
|
||||
ie = evas_cache_image_copied_data(evas_common_image_cache_get(), iw, ih,
|
||||
NULL, EINA_TRUE, (Evas_Colorspace) cspace);
|
||||
if (!ie) return NULL;
|
||||
pixels = ((RGBA_Image *) ie)->image.data;
|
||||
memset(pixels, 0, iw * ih * pxs);
|
||||
}
|
||||
ie->borders.l = l;
|
||||
ie->borders.r = r;
|
||||
ie->borders.t = t;
|
||||
ie->borders.b = b;
|
||||
|
||||
buf = eng_ector_buffer_wrap(data, evas, ie, EINA_TRUE);
|
||||
evas_cache_image_drop(ie);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue