diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 63f777f04a..e4aa44863d 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 e01eb38e83..fe241d29e7 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 6a93c2c879..3602319ad7 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 757f4ba4d5..1155e901cc 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) { - DBG("Native surface %p (color_buf %d) was not found.", - ns, 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 + { + 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 585c1a388c..7eeca5d6a5 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 81361beb7d..3f199ed59a 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 b9239979e4..205baad172 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,