forked from enlightenment/efl
Evas filters: Alloc/Dealloc buffers from the main loop only
This is a problem I didn't spot immediately... but with tons of nasty consequences.
This commit is contained in:
parent
bf46a1d26c
commit
eea049f988
|
@ -2133,6 +2133,7 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
void *filter_ctx;
|
||||
Eina_Bool ok;
|
||||
int ox = 0, oy = 0;
|
||||
Image_Entry *previous = o->cur.filter.output;
|
||||
|
||||
/* NOTE: Font effect rendering is now done ENTIRELY on CPU.
|
||||
* So we rely on cache/cache2 to allocate a real image buffer,
|
||||
|
@ -2146,7 +2147,7 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
X = obj->cur->geometry.x;
|
||||
Y = obj->cur->geometry.y;
|
||||
|
||||
if (o->cur.filter.output)
|
||||
if (previous)
|
||||
{
|
||||
Eina_Bool redraw = o->cur.filter.changed;
|
||||
|
||||
|
@ -2170,16 +2171,11 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
eina_iterator_free(it);
|
||||
}
|
||||
|
||||
if (redraw)
|
||||
{
|
||||
ENFN->image_free(ENDT, o->cur.filter.output);
|
||||
o->cur.filter.output = NULL;
|
||||
}
|
||||
else
|
||||
if (!redraw)
|
||||
{
|
||||
// Render this image only
|
||||
ENFN->image_draw(ENDT, context,
|
||||
surface, o->cur.filter.output,
|
||||
surface, previous,
|
||||
0, 0, W, H, // src
|
||||
X + x, Y + y, W, H, // dst
|
||||
EINA_FALSE, // smooth
|
||||
|
@ -2205,10 +2201,15 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
|
||||
|
||||
// Allocate main buffers now
|
||||
evas_filter_buffer_data_set(filter, inbuf, NULL, W, H, EINA_TRUE);
|
||||
evas_filter_buffer_data_set(filter, outbuf, NULL, W, H, EINA_FALSE);
|
||||
evas_filter_context_buffers_allocate_all(filter, W, H);
|
||||
//evas_filter_buffer_data_set(filter, inbuf, NULL, W, H, EINA_TRUE);
|
||||
//evas_filter_buffer_data_set(filter, outbuf, NULL, W, H, EINA_FALSE);
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||
|
||||
// Steal output and release previous
|
||||
o->cur.filter.output = evas_filter_buffer_backing_steal(filter, outbuf);
|
||||
if (o->cur.filter.output != previous)
|
||||
evas_filter_buffer_backing_release(filter, previous);
|
||||
|
||||
// Render text to input buffer
|
||||
EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
|
||||
|
|
|
@ -80,29 +80,40 @@ 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, Image_Entry *ie)
|
||||
{
|
||||
if (!ie) return;
|
||||
|
||||
if (!ctx->gl_engine)
|
||||
ENFN->image_free(ENDT, ie);
|
||||
else
|
||||
{
|
||||
if (!evas_cserve2_use_get())
|
||||
evas_cache_image_drop(ie);
|
||||
else
|
||||
evas_cache2_image_close(ie);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_filter_buffer_backing_free(Evas_Filter_Buffer *fb)
|
||||
{
|
||||
void *backing;
|
||||
if (!fb) return;
|
||||
|
||||
if (fb->stolen)
|
||||
{
|
||||
fb->delete_me = EINA_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
INF("Free backing of buffer %d fb @ %p backing @ %p alloc %d", fb->id, fb, fb->backing, fb->allocated);
|
||||
backing = fb->backing;
|
||||
fb->backing = NULL;
|
||||
|
||||
if (!fb->allocated) return;
|
||||
fb->allocated = EINA_FALSE;
|
||||
|
||||
if (!backing) return;
|
||||
|
||||
if (!fb->ctx->gl_engine)
|
||||
fb->ENFN->image_free(fb->ENDT, backing);
|
||||
else
|
||||
{
|
||||
if (!evas_cserve2_use_get())
|
||||
evas_cache_image_drop(backing);
|
||||
else
|
||||
evas_cache2_image_close(backing);
|
||||
}
|
||||
_backing_free(fb->ctx, backing);
|
||||
}
|
||||
|
||||
/** @hidden private bind proxy to context */
|
||||
|
@ -362,42 +373,111 @@ _rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data)
|
|||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
Eina_Bool
|
||||
evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h)
|
||||
{
|
||||
if (!fb) return EINA_FALSE;
|
||||
INF("Allocate buffer %d: backing %p", fb->id, fb->backing);
|
||||
if (fb->backing)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
int W, H;
|
||||
|
||||
if (fb->ctx->gl_engine)
|
||||
return EINA_TRUE;
|
||||
|
||||
fb->ENFN->image_size_get(fb->ENDT, fb->backing, &W, &H);
|
||||
if ((W == w) && (H == h))
|
||||
return EINA_TRUE;
|
||||
|
||||
if (!fb->transient)
|
||||
{
|
||||
ERR("Buffer dimensions mismatch with external image!");
|
||||
//return EINA_FALSE;
|
||||
// This needs to be counter-checked.
|
||||
INF("Nope, gl engine is used");
|
||||
return EINA_TRUE;
|
||||
}
|
||||
_filter_buffer_backing_free(fb);
|
||||
|
||||
im = fb->backing;
|
||||
if (!im->image.data)
|
||||
{
|
||||
if (fb->allocated)
|
||||
fb->ENFN->image_free(fb->ENDT, im);
|
||||
fb->allocated = EINA_FALSE;
|
||||
fb->backing = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fb->ENFN->image_size_get(fb->ENDT, fb->backing, &W, &H);
|
||||
if ((W == w) && (H == h))
|
||||
{
|
||||
INF("Nope, already fine");
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (!fb->transient)
|
||||
ERR("Buffer dimensions mismatch with external image!");
|
||||
_filter_buffer_backing_free(fb);
|
||||
}
|
||||
}
|
||||
if ((fb->w && (fb->w != w)) || (fb->h && (fb->h != h)))
|
||||
{
|
||||
ERR("Buffer dimensions mismatch!");
|
||||
//return EINA_FALSE;
|
||||
}
|
||||
if (fb->allocated) return EINA_TRUE;
|
||||
if (fb->allocated && fb->backing)
|
||||
{
|
||||
RGBA_Image *a = fb->backing;
|
||||
INF("Already allocated. Is that true? backing %p and data %p", a, a?a->image.data:NULL);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
fb->w = w;
|
||||
fb->h = h;
|
||||
|
||||
fb->backing = _rgba_image_alloc(fb, NULL);
|
||||
fb->allocated = (fb->backing != NULL);
|
||||
RGBA_Image *a = fb->backing;
|
||||
INF("Allocated buf %d with backing %p data %p", fb->id, fb->backing, a?a->image.data:0);
|
||||
return fb->allocated;
|
||||
}
|
||||
*/
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx, unsigned w, unsigned h)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
Image_Entry *ie;
|
||||
Eina_List *li;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
EINA_LIST_FOREACH(ctx->buffers, li, fb)
|
||||
{
|
||||
if (fb->source) continue;
|
||||
|
||||
ie = fb->backing;
|
||||
if (ie)
|
||||
{
|
||||
if ((ie->w != w) || (ie->h != h))
|
||||
{
|
||||
CRI("Inconsistent buffer size!");
|
||||
continue;
|
||||
}
|
||||
ie->references++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fb->w && !fb->h)
|
||||
{
|
||||
fb->w = w;
|
||||
fb->h = h;
|
||||
}
|
||||
ie = (Image_Entry *) _rgba_image_alloc(fb, NULL);
|
||||
if (!ie)
|
||||
{
|
||||
ERR("Buffer %d allocation failed!", fb->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
fb->backing = ie;
|
||||
}
|
||||
|
||||
// To unref: evas_unref_queue_image_put
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only)
|
||||
|
@ -462,6 +542,7 @@ evas_filter_buffer_image_new(Evas_Filter_Context *ctx, RGBA_Image *image)
|
|||
return fb->id;
|
||||
}
|
||||
|
||||
/*
|
||||
int
|
||||
evas_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h,
|
||||
Eina_Bool alpha_only)
|
||||
|
@ -487,6 +568,7 @@ evas_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h,
|
|||
|
||||
return fb->id;
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
_buffer_free(Evas_Filter_Buffer *fb)
|
||||
|
@ -525,16 +607,45 @@ evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid)
|
|||
{
|
||||
Evas_Filter_Buffer *buffer;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
|
||||
|
||||
buffer = _filter_buffer_get(ctx, bufid);
|
||||
if (!buffer) return NULL;
|
||||
|
||||
if (!buffer->glimage)
|
||||
{
|
||||
buffer->allocated = EINA_FALSE;
|
||||
return buffer->backing;
|
||||
}
|
||||
else
|
||||
buffer->stolen = EINA_TRUE;
|
||||
if (buffer->glimage)
|
||||
return buffer->glimage;
|
||||
else
|
||||
return buffer->backing;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer)
|
||||
{
|
||||
Image_Entry *ie = stolen_buffer;
|
||||
Evas_Filter_Buffer *fb;
|
||||
Eina_List *li;
|
||||
|
||||
if (!stolen_buffer) return EINA_FALSE;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
|
||||
EINA_LIST_FOREACH(ctx->buffers, li, fb)
|
||||
{
|
||||
if (fb->backing == ie)
|
||||
{
|
||||
fb->stolen = EINA_FALSE;
|
||||
if (fb->delete_me)
|
||||
{
|
||||
ctx->buffers = eina_list_remove_list(ctx->buffers, li);
|
||||
_buffer_free(fb);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
_backing_free(ctx, ie);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Evas_Filter_Command *
|
||||
|
@ -1418,29 +1529,12 @@ _filter_command_run(Evas_Filter_Command *cmd)
|
|||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (!cmd->output->w && !cmd->output->h)
|
||||
{
|
||||
if (!cmd->output->backing)
|
||||
{
|
||||
cmd->output->w = cmd->ctx->w;
|
||||
cmd->output->h = cmd->ctx->h;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd->output->w <= 0) || (cmd->output->h <= 0))
|
||||
{
|
||||
ERR("Output size invalid: %dx%d", cmd->output->w, cmd->output->h);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
ok = evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h);
|
||||
if (!ok)
|
||||
{
|
||||
ERR("Failed to allocate output buffer of size %dx%d",
|
||||
cmd->output->w, cmd->output->h);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
//func = cmd->ENFN->filter_command_func_get(cmd);
|
||||
// FIXME: Must call engine function, not CPU directly.
|
||||
|
||||
|
|
|
@ -51,9 +51,6 @@ _filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
|
|||
if (!func)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h))
|
||||
return EINA_FALSE;
|
||||
|
||||
in = cmd->input->backing;
|
||||
out = cmd->output->backing;
|
||||
sw = in->cache_entry.w;
|
||||
|
@ -96,13 +93,12 @@ _filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
|
|||
RGBA_Draw_Context *drawctx;
|
||||
int sw, sh, dx, dy, dw, dh, sx, sy;
|
||||
|
||||
if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h))
|
||||
return EINA_FALSE;
|
||||
|
||||
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);
|
||||
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
|
@ -324,9 +320,6 @@ _filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd)
|
|||
DATA8 *maskdata;
|
||||
int sw, sh, dw, dh, ox, oy, sx = 0, sy = 0, dx = 0, dy = 0, rows, cols, y;
|
||||
|
||||
if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h))
|
||||
return EINA_FALSE;
|
||||
|
||||
// TODO: Call _mapped_blend_cpu to implement repeat fill mode.
|
||||
if (cmd->draw.fillmode != EVAS_FILTER_FILL_MODE_NONE)
|
||||
ERR("Fill modes are not implemented for Alpha --> RGBA");
|
||||
|
@ -343,6 +336,19 @@ _filter_blend_cpu_mask_rgba(Evas_Filter_Command *cmd)
|
|||
maskdata = in->mask.data;
|
||||
col = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
|
||||
|
||||
// TODO: Fix this crash. Change proxy image and OUTPUT data is NULL. Why?
|
||||
|
||||
if (!dstdata)
|
||||
{
|
||||
ERR("Empty destination from buffer #%d %dx%d %p", cmd->output->id, dw, dh, out);
|
||||
//abort();
|
||||
return EINA_FALSE;
|
||||
}
|
||||
if (!maskdata)
|
||||
abort();
|
||||
//EINA_SAFETY_ON_NULL_RETURN_VAL(dstdata, EINA_FALSE);
|
||||
//EINA_SAFETY_ON_NULL_RETURN_VAL(maskdata, EINA_FALSE);
|
||||
|
||||
func = evas_common_gfx_func_composite_mask_color_span_get
|
||||
(col, out, 1, cmd->draw.render_op);
|
||||
|
||||
|
@ -417,9 +423,6 @@ _filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
|
|||
RGBA_Image *in, *out;
|
||||
int sw, sh, dx, dy, dw, dh, sx, sy;
|
||||
|
||||
if (!evas_filter_buffer_alloc(cmd->output, cmd->output->w, cmd->output->h))
|
||||
return EINA_FALSE;
|
||||
|
||||
in = cmd->input->backing;
|
||||
out = cmd->output->backing;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
|
||||
|
@ -439,6 +442,7 @@ _filter_blend_cpu_rgba2alpha(Evas_Filter_Command *cmd)
|
|||
return EINA_TRUE;
|
||||
|
||||
// Stretch if necessary.
|
||||
#warning FIXME Must be in the main loop because of buffer allocation
|
||||
if ((sw != dw || sh != dh) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
|
|
|
@ -154,6 +154,8 @@ struct _Evas_Filter_Buffer
|
|||
Eina_Bool allocated : 1; // allocated on demand, belongs to this context
|
||||
Eina_Bool transient : 1; // temporary buffer (automatic allocation)
|
||||
Eina_Bool locked : 1; // internal flag
|
||||
Eina_Bool stolen : 1; // stolen by the client
|
||||
Eina_Bool delete_me : 1; // request delete asap (after released by client)
|
||||
};
|
||||
|
||||
enum _Evas_Filter_Interpolation_Mode
|
||||
|
|
|
@ -10,8 +10,8 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
|
|||
int w, int h)
|
||||
{
|
||||
Evas_Filter_Buffer *fb;
|
||||
void *dstdata = NULL;
|
||||
void *srcdata;
|
||||
Image_Entry *dstdata = NULL;
|
||||
Image_Entry *srcdata;
|
||||
void *drawctx;
|
||||
|
||||
srcdata = evas_filter_buffer_backing_get(ctx, src->id);
|
||||
|
@ -20,11 +20,17 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
|
|||
fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
|
||||
if (!fb) return NULL;
|
||||
|
||||
if (evas_filter_buffer_alloc(fb, w, h))
|
||||
dstdata = evas_filter_buffer_backing_get(ctx, fb->id);
|
||||
dstdata = evas_filter_buffer_backing_get(ctx, fb->id);
|
||||
if (!dstdata)
|
||||
{
|
||||
ERR("Buffer allocation failed for size %dx%d", w, h);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,14 +101,18 @@ Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas);
|
|||
void evas_filter_context_destroy(Evas_Filter_Context *ctx);
|
||||
void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
|
||||
#define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx)
|
||||
Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx, unsigned w, unsigned h);
|
||||
|
||||
int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only);
|
||||
int evas_filter_buffer_image_new(Evas_Filter_Context *ctx, RGBA_Image *image);
|
||||
int evas_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h, Eina_Bool alpha_only);
|
||||
//int evas_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h, Eina_Bool alpha_only);
|
||||
#define evas_filter_buffer_alloc_new(ctx, w, h, a) evas_filter_buffer_data_new(ctx, NULL, w, h, a)
|
||||
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_data_set(Evas_Filter_Context *ctx, int bufid, void *data, int w, int h, Eina_Bool alpha_only);
|
||||
Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer);
|
||||
|
||||
// Do not use
|
||||
EINA_DEPRECATED Eina_Bool evas_filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data, int w, int h, Eina_Bool alpha_only);
|
||||
|
||||
Eina_Bool evas_filter_run(Evas_Filter_Context *ctx, Eina_Bool do_async);
|
||||
|
||||
|
|
Loading…
Reference in New Issue