forked from enlightenment/efl
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
This commit is contained in:
parent
a8e79114db
commit
a14492ef73
|
@ -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 ?
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue