forked from enlightenment/efl
Evas filters: OpenGL support part 2.
This patch implements the final draw from RGBA_Image to the OpenGL surface. We can even steal the output buffer and redraw it quickly, without having to re-render everything (same as in SW).
This commit is contained in:
parent
f007cd5665
commit
8062df320c
|
@ -2128,12 +2128,9 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
{
|
||||
int X, Y, W, H;
|
||||
Evas_Filter_Context *filter;
|
||||
int inbuf = 1;
|
||||
int outbuf = 2;
|
||||
int targetbuf;
|
||||
RGBA_Image *input, *outputimg = NULL; // FIXME: This is engine dependent
|
||||
const int inbuf = 1;
|
||||
const int outbuf = 2;
|
||||
void *filter_ctx;
|
||||
static int gl_engine = -1;
|
||||
Eina_Bool ok;
|
||||
int ox = 0, oy = 0;
|
||||
|
||||
|
@ -2144,10 +2141,6 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
* image to GL.
|
||||
*/
|
||||
|
||||
// FIXME. Disabled redraw for OpenGL.
|
||||
if (gl_engine == -1)
|
||||
gl_engine = !!strstr(obj->layer->evas->engine.module->definition->name, "gl");
|
||||
|
||||
W = obj->cur->geometry.w;
|
||||
H = obj->cur->geometry.h;
|
||||
X = obj->cur->geometry.x;
|
||||
|
@ -2185,7 +2178,6 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
else
|
||||
{
|
||||
// Render this image only
|
||||
outputimg = o->cur.filter.output;
|
||||
ENFN->image_draw(ENDT, context,
|
||||
surface, o->cur.filter.output,
|
||||
0, 0, W, H, // src
|
||||
|
@ -2208,21 +2200,15 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
// Proxies
|
||||
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
||||
|
||||
// Output
|
||||
targetbuf = evas_filter_buffer_image_new(filter, surface);
|
||||
|
||||
// Context: FIXME it should be a sw context only
|
||||
filter_ctx = ENFN->context_new(ENDT);
|
||||
ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
|
||||
|
||||
// Alloc input now so we can draw text asap
|
||||
// Allocate main buffers now
|
||||
evas_filter_buffer_data_set(filter, inbuf, NULL, W, H, EINA_TRUE);
|
||||
|
||||
// Allocate and steal output so we can keep it around
|
||||
evas_filter_buffer_data_set(filter, outbuf, NULL, W, H, EINA_FALSE);
|
||||
if (!gl_engine)
|
||||
outputimg = evas_filter_buffer_backing_steal(filter, outbuf);
|
||||
o->cur.filter.output = outputimg;
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||
o->cur.filter.output = evas_filter_buffer_backing_steal(filter, outbuf);
|
||||
|
||||
// Render text to input buffer
|
||||
EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
|
||||
|
@ -2235,10 +2221,6 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
do_async);
|
||||
}
|
||||
|
||||
// FIXME: This final blend is not necessary. Needs to be removed.
|
||||
evas_filter_command_blend_add(filter, context, outbuf, targetbuf,
|
||||
X + x, Y + y, EVAS_FILTER_FILL_MODE_NONE);
|
||||
|
||||
ENFN->context_free(ENDT, filter_ctx);
|
||||
|
||||
// Add post-run callback and run filter
|
||||
|
|
|
@ -330,7 +330,6 @@ _rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data)
|
|||
}
|
||||
else
|
||||
{
|
||||
WRN("EXPERIMENTAL OpenGL support. VERY HACKISH!");
|
||||
// FIXME: Directly calling the alloc functions since we want to use sw surfaces.
|
||||
|
||||
if (!data)
|
||||
|
@ -371,6 +370,9 @@ evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h)
|
|||
{
|
||||
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;
|
||||
|
@ -526,8 +528,13 @@ evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid)
|
|||
buffer = _filter_buffer_get(ctx, bufid);
|
||||
if (!buffer) return NULL;
|
||||
|
||||
buffer->allocated = EINA_FALSE;
|
||||
return buffer->backing;
|
||||
if (!buffer->glimage)
|
||||
{
|
||||
buffer->allocated = EINA_FALSE;
|
||||
return buffer->backing;
|
||||
}
|
||||
else
|
||||
return buffer->glimage;
|
||||
}
|
||||
|
||||
static Evas_Filter_Command *
|
||||
|
@ -1211,6 +1218,78 @@ evas_filter_fill_cpu_func_get(Evas_Filter_Command *cmd)
|
|||
}
|
||||
|
||||
|
||||
/* Final target */
|
||||
Eina_Bool
|
||||
evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
|
||||
void *surface, int x, int y)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
|
||||
|
||||
ctx->target.bufid = evas_filter_buffer_image_new(ctx, surface);
|
||||
if (!ctx->gl_engine)
|
||||
{
|
||||
/* FIXME: This extraneous blend could be avoided if all filters
|
||||
* drawing to output (buffer #2) support proper colors and offsets.
|
||||
*/
|
||||
evas_filter_command_blend_add(ctx, draw_context, 2, ctx->target.bufid,
|
||||
x, y, EVAS_FILTER_FILL_MODE_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Since GL has sync rendering, draw_context is safe to keep around
|
||||
Evas_Filter_Buffer *target, *image;
|
||||
RGBA_Image *im;
|
||||
|
||||
ctx->target.context = draw_context;
|
||||
ctx->target.x = x;
|
||||
ctx->target.y = y;
|
||||
|
||||
target = _filter_buffer_get(ctx, ctx->target.bufid);
|
||||
target->glimage = target->backing;
|
||||
target->backing = NULL;
|
||||
|
||||
image = _filter_buffer_get(ctx, 2);
|
||||
im = image->backing;
|
||||
image->glimage = ENFN->image_new_from_data
|
||||
(ENDT, image->w, image->h, im->image.data, EINA_TRUE, im->cache_entry.space);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_filter_target_render(Evas_Filter_Context *ctx)
|
||||
{
|
||||
Evas_Filter_Buffer *src, *dst;
|
||||
Eina_Bool ok;
|
||||
|
||||
/* FIXME: This is some hackish hook to send the final buffer on the screen
|
||||
* Only used for OpenGL now, since evas_filter_target_set() adds a blend
|
||||
* command in case of pure software rendering.
|
||||
*/
|
||||
|
||||
if (!ctx->gl_engine) return EINA_FALSE;
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(ctx->target.bufid, EINA_FALSE);
|
||||
|
||||
src = _filter_buffer_get(ctx, 2);
|
||||
if (!src) return EINA_FALSE;
|
||||
|
||||
dst = _filter_buffer_get(ctx, ctx->target.bufid);
|
||||
if (!dst) return EINA_FALSE;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(src->glimage, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dst->glimage, EINA_FALSE);
|
||||
|
||||
ok = ENFN->image_draw(ENDT, ctx->target.context,
|
||||
dst->glimage, src->glimage,
|
||||
0, 0, src->w, src->h,
|
||||
ctx->target.x, ctx->target.y, src->w, src->h,
|
||||
EINA_TRUE, EINA_FALSE);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/* Font drawing stuff */
|
||||
Eina_Bool
|
||||
evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid,
|
||||
|
@ -1367,9 +1446,6 @@ _filter_command_run(Evas_Filter_Command *cmd)
|
|||
//func = cmd->ENFN->filter_command_func_get(cmd);
|
||||
// FIXME: Must call engine function, not CPU directly.
|
||||
|
||||
if (strncmp(cmd->ctx->evas->engine.module->definition->name, "software", 8))
|
||||
WRN("EXPERIMENTAL OpenGL support! ALL HELL WILL BREAK LOOSE!");
|
||||
|
||||
switch (cmd->mode)
|
||||
{
|
||||
case EVAS_FILTER_MODE_BLEND:
|
||||
|
@ -1436,7 +1512,9 @@ _filter_chain_run(Evas_Filter_Context *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
if (!ok) return EINA_FALSE;
|
||||
|
||||
return _filter_target_render(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1458,6 +1536,9 @@ evas_filter_run(Evas_Filter_Context *ctx, Eina_Bool do_async)
|
|||
if (!ctx->commands)
|
||||
return EINA_TRUE;
|
||||
|
||||
if (ctx->gl_engine)
|
||||
WRN("EXPERIMENTAL OpenGL support! Might very well crash or not render anything.");
|
||||
|
||||
if (do_async)
|
||||
{
|
||||
evas_thread_cmd_enqueue(_filter_thread_run_cb, ctx);
|
||||
|
|
|
@ -57,6 +57,14 @@ struct _Evas_Filter_Context
|
|||
void *data;
|
||||
} post_run;
|
||||
|
||||
struct
|
||||
{
|
||||
// Only used with the GL engine.
|
||||
int bufid;
|
||||
void *context;
|
||||
int x, y;
|
||||
} target;
|
||||
|
||||
Eina_Bool gl_engine : 1;
|
||||
};
|
||||
|
||||
|
@ -139,6 +147,7 @@ struct _Evas_Filter_Buffer
|
|||
|
||||
Evas_Object *source;
|
||||
void *backing;
|
||||
void *glimage;
|
||||
int w, h;
|
||||
|
||||
Eina_Bool alpha_only : 1; // 1 channel (A) instead of 4 (RGBA)
|
||||
|
|
|
@ -113,6 +113,7 @@ Eina_Bool evas_filter_buffer_data_set(Evas_Filter_Context *ctx, i
|
|||
Eina_Bool evas_filter_run(Evas_Filter_Context *ctx, Eina_Bool do_async);
|
||||
|
||||
Eina_Bool evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
|
||||
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Blend a source buffer into a destination buffer, allowing X,Y offsets, Alpha to RGBA conversion with color
|
||||
|
|
Loading…
Reference in New Issue