jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=a14492ef73c9267042c5bf505080d0e90af394de
commit a14492ef73c9267042c5bf505080d0e90af394de Author: Jean-Philippe Andre <jp.an...@samsung.com> Date: Tue Mar 3 16:38:52 2015 +0900 Evas GL: Automatic fallback to indirect rendering when the scene has not changed. Automatically fallback to indirect rendering on FBO or X11 Pixmap if the Evas Object Image is not marked as dirty. This should improve the performance and/or power consumption in those rare cases where this area of the canvas needs to be redrawn but the GL content has not changed. @feature --- src/lib/evas/canvas/evas_object_image.c | 37 +++++++--- src/lib/evas/include/evas_private.h | 2 + .../evas/engines/gl_common/evas_gl_common.h | 1 + src/modules/evas/engines/gl_common/evas_gl_core.c | 81 +++++++++++++++------- src/modules/evas/engines/gl_common/evas_gl_core.h | 2 +- src/modules/evas/engines/gl_generic/evas_engine.c | 43 ++++++++++-- .../evas/engines/software_generic/evas_engine.c | 2 + 7 files changed, 130 insertions(+), 38 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 63f777f..e4aa448 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -2853,11 +2853,9 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, if (ENFN->image_native_get) { Evas_Native_Surface *ns; + ns = ENFN->image_native_get(ENDT, o->engine_data); - if ( (ns) && - (ns->type == EVAS_NATIVE_SURFACE_OPENGL) && - (ns->data.opengl.texture_id) && - (!ns->data.opengl.framebuffer_id) ) + if (ns) { Eina_Bool direct_renderable = EINA_FALSE; @@ -2880,6 +2878,8 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, { if (ENFN->gl_get_pixels_set) ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj); + if (ENFN->gl_image_direct_set) + ENFN->gl_image_direct_set(output, o->engine_data, EINA_TRUE); o->direct_render = EINA_TRUE; } else @@ -2919,9 +2919,28 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, else { // Check if the it's not dirty but it has direct rendering - if (o->direct_render) + if (o->direct_render && ENFN->image_native_get) { - ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj); + Evas_Native_Surface *ns; + ns = ENFN->image_native_get(output, o->engine_data); + if (ENFN->gl_direct_override_get) + ENFN->gl_direct_override_get(output, &direct_override, &direct_force_off); + if (ENFN->gl_surface_direct_renderable_get) + ENFN->gl_surface_direct_renderable_get(output, ns, &direct_override); + + if (direct_override && !direct_force_off) + { + // always use direct rendering + ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj); + } + else + { + // Auto-fallback to FBO rendering (for perf & power consumption) + o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, obj->object); + //if (ENFN->get_pixels_render_post) + //ENFN->get_pixels_render_post(output); + o->direct_render = EINA_FALSE; + } } } @@ -3019,9 +3038,9 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v // Clear out the pixel get stuff.. if (ENFN->gl_get_pixels_set) - { - ENFN->gl_get_pixels_set(output, NULL, NULL, NULL); - } + ENFN->gl_get_pixels_set(output, NULL, NULL, NULL); + if (ENFN->gl_image_direct_set) + ENFN->gl_image_direct_set(output, o->engine_data, EINA_FALSE); Evas_Object_Protected_Data *source = (o->cur->source ? diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index e01eb38..fe241d2 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1309,6 +1309,8 @@ struct _Evas_Func int (*gl_rotation_angle_get) (void *data); Eina_Bool (*gl_surface_query) (void *data, void *surface, int attr, void *value); Eina_Bool (*gl_surface_direct_renderable_get) (void *data, Evas_Native_Surface *ns, Eina_Bool *override); + void (*gl_image_direct_set) (void *data, void *image, Eina_Bool direct); + int (*gl_image_direct_get) (void *data, void *image); int (*image_load_error_get) (void *data, void *image); int (*font_run_end_get) (void *data, Evas_Font_Set *font, Evas_Font_Instance **script_fi, Evas_Font_Instance **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len); diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 6a93c2c..3602319 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -623,6 +623,7 @@ struct _Evas_GL_Image unsigned char alpha : 1; unsigned char tex_only : 1; unsigned char locked : 1; // gl_surface_lock/unlock + unsigned char direct : 1; // evas gl direct renderable }; struct _Evas_GL_Font_Texture diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c index 757f4ba..1155e90 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -1690,8 +1690,16 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h) if (sfc->direct_fb_opt) { - eina_hash_add(evgl_engine->direct_surfaces, &sfc->color_buf, sfc); - DBG("Added tex %d as direct surface: %p", sfc->color_buf, sfc); + if (!sfc->gles1_indirect) + { + eina_hash_add(evgl_engine->direct_surfaces, &sfc->color_buf, sfc); + DBG("Added tex %d as direct surface: %p", sfc->color_buf, sfc); + } + else + { + eina_hash_add(evgl_engine->direct_surfaces, &sfc->gles1_sfc_native, sfc); + DBG("Added tex %d as direct surface: %p", sfc->gles1_sfc_native, sfc); + } } if (sfc->direct_fb_opt && @@ -2362,7 +2370,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) if (dbg) DBG("Surface sfc %p is a normal surface.", sfc); // Attach fbo and the buffers - if ((ctx->current_sfc != sfc) || (ctx != sfc->current_ctx)) + if ((rsc->current_ctx != ctx) || (ctx->current_sfc != sfc) || (rsc->direct.rendered)) { sfc->current_ctx = ctx; if ((evgl_engine->direct_mem_opt) && (evgl_engine->direct_override)) @@ -2469,17 +2477,24 @@ evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns) return 0; } - ns->type = EVAS_NATIVE_SURFACE_OPENGL; - ns->version = EVAS_NATIVE_SURFACE_VERSION; - ns->data.opengl.texture_id = sfc->color_buf; - ns->data.opengl.framebuffer_id = sfc->color_buf; - ns->data.opengl.x = 0; - ns->data.opengl.y = 0; - ns->data.opengl.w = sfc->w; - ns->data.opengl.h = sfc->h; - - if (sfc->direct_fb_opt) - ns->data.opengl.framebuffer_id = 0; + if (!sfc->gles1_indirect) + { + ns->type = EVAS_NATIVE_SURFACE_OPENGL; + ns->version = EVAS_NATIVE_SURFACE_VERSION; + ns->data.opengl.texture_id = sfc->color_buf; + ns->data.opengl.framebuffer_id = sfc->color_buf; + ns->data.opengl.x = 0; + ns->data.opengl.y = 0; + ns->data.opengl.w = sfc->w; + ns->data.opengl.h = sfc->h; + } + else + { + ns->type = EVAS_NATIVE_SURFACE_X11; + ns->version = EVAS_NATIVE_SURFACE_VERSION; + ns->data.x11.pixmap = (unsigned long)(intptr_t)sfc->gles1_sfc_native; + ns->data.x11.visual = sfc->gles1_sfc_visual; + } return 1; } @@ -2503,24 +2518,42 @@ Eina_Bool evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns, Eina_Bool *direct_render, Eina_Bool *client_side_rotation, - Eina_Bool *override) + Eina_Bool *direct_override) { EVGL_Surface *sfc; - if (override) *override = EINA_FALSE; if (direct_render) *direct_render = EINA_FALSE; + if (direct_override) *direct_override = EINA_FALSE; if (client_side_rotation) *client_side_rotation = EINA_FALSE; if (!evgl_engine) return EINA_FALSE; - if (!ns || (ns->type != EVAS_NATIVE_SURFACE_OPENGL)) return EINA_FALSE; - if (ns->data.opengl.framebuffer_id != 0) return EINA_FALSE; - if (ns->data.opengl.texture_id == 0) return EINA_FALSE; + if (!ns) return EINA_FALSE; - sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.opengl.texture_id); - if (!sfc) + if (ns->type == EVAS_NATIVE_SURFACE_OPENGL && + ns->data.opengl.texture_id) + { + sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.opengl.texture_id); + if (!sfc) + { + DBG("Native surface %p (color_buf %d) was not found.", + ns, ns->data.opengl.texture_id); + return EINA_FALSE; + } + } + else if (ns->type == EVAS_NATIVE_SURFACE_X11 && + ns->data.x11.pixmap) + { + sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.x11.pixmap); + if (!sfc) + { + DBG("Native surface %p (pixmap %x) was not found.", + ns, ns->data.x11.pixmap); + return EINA_FALSE; + } + } + else { - DBG("Native surface %p (color_buf %d) was not found.", - ns, ns->data.opengl.texture_id); + ERR("Only EVAS_NATIVE_SURFACE_OPENGL or EVAS_NATIVE_SURFACE_X11 can be used for direct rendering"); return EINA_FALSE; } @@ -2532,7 +2565,7 @@ evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns, } if (direct_render) *direct_render = sfc->direct_fb_opt; - if (override) *override |= sfc->direct_override; + if (direct_override) *direct_override |= sfc->direct_override; if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation; return EINA_TRUE; } diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.h b/src/modules/evas/engines/gl_common/evas_gl_core.h index 585c1a3..7eeca5d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core.h @@ -47,7 +47,7 @@ void evgl_direct_info_clear(); Eina_Bool evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns, Eina_Bool *direct_render, Eina_Bool *client_side_rotation, - Eina_Bool *override); + Eina_Bool *direct_override); void evgl_direct_partial_info_set(int pres); void evgl_direct_partial_info_clear(); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 81361be..3f199ed 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -28,6 +28,8 @@ static int _evas_engine_GL_log_dom = -1; +static int eng_gl_image_direct_get(void *data EINA_UNUSED, void *image); + static void eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED) { @@ -817,10 +819,10 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, gl_context = re->window_gl_context_get(re->software.ob); re->window_use(re->software.ob); - if ((n) && (n->type == EVAS_NATIVE_SURFACE_OPENGL) && - (n->data.opengl.framebuffer_id == 0) && - re->func.get_pixels) + if (eng_gl_image_direct_get(data, image)) { + unsigned int texid; + gl_context->dc = context; if ((gl_context->master_clip.enabled) && (gl_context->master_clip.w > 0) && @@ -830,6 +832,16 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, evgl_direct_partial_info_set(gl_context->preserve_bit); } + if (n->type == EVAS_NATIVE_SURFACE_OPENGL) + texid = n->data.opengl.texture_id; + else if (n->type == EVAS_NATIVE_SURFACE_X11) + texid = n->data.x11.pixmap; + else + { + ERR("This native surface type is not supported for direct rendering"); + return EINA_FALSE; + } + // Set necessary info for direct rendering evgl_direct_info_set(gl_context->w, gl_context->h, @@ -839,7 +851,7 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, gl_context->dc->clip.y, gl_context->dc->clip.w, gl_context->dc->clip.h, - n->data.opengl.texture_id); + texid); // Call pixel get function re->func.get_pixels(re->func.get_pixels_data, re->func.obj); @@ -1533,6 +1545,27 @@ eng_gl_surface_query(void *data, void *surface, int attr, void *value) #endif } +static int +eng_gl_image_direct_get(void *data EINA_UNUSED, void *image) +{ + Evas_GL_Image *im = image; + if (!im) return EINA_FALSE; + return im->direct; +} + +static void +eng_gl_image_direct_set(void *data, void *image, Eina_Bool direct) +{ + Render_Engine_GL_Generic *re = data; + Evas_GL_Image *im = image; + + if (!im) return; + if (im->native.data && direct && re && re->func.get_pixels) + im->direct = EINA_TRUE; + else + im->direct = EINA_FALSE; +} + //--------------------------------// static int @@ -2114,6 +2147,8 @@ module_open(Evas_Module *em) // gl_current_context_get is in engine ORD(gl_current_surface_get); ORD(gl_rotation_angle_get); + ORD(gl_image_direct_get); + ORD(gl_image_direct_set); ORD(image_load_error_get); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index b923997..205baad 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -3572,6 +3572,8 @@ static Evas_Func func = NULL, // need software mesa for gl rendering <- gl_rotation_angle_get NULL, // need software mesa for gl rendering <- gl_surface_query NULL, // need software mesa for gl rendering <- gl_surface_direct_renderable_get + NULL, // need software mesa for gl rendering <- gl_image_direct_set + NULL, // need software mesa for gl rendering <- gl_image_direct_get eng_image_load_error_get, eng_font_run_font_end_get, eng_image_animated_get, --