forked from enlightenment/efl
Evas GL: Fix direct rendering with client-side rotation
There was a problem when checking whether the current surface is compatible with direct rendering. In case of client-side rotation (it's a flag set on the surface by the app), a surface can be directly rendered even if the rotation is not 0. But, before this patch, it was assumed that the surface was current. Which doesn't make sense because make_current is called by the pixel callback, from the application, and this happens *after* we check for direct rendering. As a consequence, it was not possible to mix directly rendered surfaces with FBO-based ones, and use client-side rotation. This patch should solve that issue.
This commit is contained in:
parent
f52be78699
commit
4cf2d75715
|
@ -2759,25 +2759,27 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
(ns->data.opengl.texture_id) &&
|
||||
(!ns->data.opengl.framebuffer_id) )
|
||||
{
|
||||
Eina_Bool direct_renderable = EINA_FALSE;
|
||||
|
||||
// Check if we can do direct rendering...
|
||||
if (ENFN->gl_direct_override_get)
|
||||
ENFN->gl_direct_override_get(output, &direct_override, &direct_force_off);
|
||||
if ( (((obj->cur->geometry.w == o->cur->image.w) &&
|
||||
if (ENFN->gl_surface_direct_renderable_get)
|
||||
direct_renderable = ENFN->gl_surface_direct_renderable_get(output, ns);
|
||||
|
||||
if ( ((direct_override) ||
|
||||
((direct_renderable) &&
|
||||
(obj->cur->geometry.w == o->cur->image.w) &&
|
||||
(obj->cur->geometry.h == o->cur->image.h) &&
|
||||
(obj->cur->color.r == 255) &&
|
||||
(obj->cur->color.g == 255) &&
|
||||
(obj->cur->color.b == 255) &&
|
||||
(obj->cur->color.a == 255) &&
|
||||
(!obj->map->cur.map)) ||
|
||||
(direct_override)) &&
|
||||
(!direct_force_off) )
|
||||
(!obj->map->cur.map))
|
||||
) && (!direct_force_off) )
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ENFN->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj);
|
||||
o->direct_render = EINA_TRUE;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1273,6 +1273,7 @@ struct _Evas_Func
|
|||
void *(*gl_current_surface_get) (void *data);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
|
|
@ -1111,7 +1111,7 @@ _internal_config_set(EVGL_Surface *sfc, Evas_GL_Config *cfg)
|
|||
// TODO: Implement surface reconfigure and add depth+stencil support
|
||||
|
||||
// Direct Rendering Option
|
||||
if ((!depth_bit && !stencil_bit) || evgl_engine->direct_override)
|
||||
if ((!depth_bit && !stencil_bit && !msaa_samples) || evgl_engine->direct_override)
|
||||
sfc->direct_fb_opt = cfg->options_bits & EVAS_GL_OPTIONS_DIRECT;
|
||||
|
||||
// Extra flags for direct rendering
|
||||
|
@ -1271,6 +1271,27 @@ _evgl_not_in_pixel_get(void)
|
|||
|
||||
EVGL_Context *ctx = rsc->current_ctx;
|
||||
|
||||
if (evgl_engine->direct_force_off)
|
||||
return 0;
|
||||
|
||||
if (rsc->id != evgl_engine->main_tid)
|
||||
return 0;
|
||||
|
||||
if (!ctx || !ctx->current_sfc)
|
||||
return 0;
|
||||
|
||||
if (!ctx->current_sfc->direct_fb_opt)
|
||||
return 0;
|
||||
|
||||
if (rsc->direct.rot == 0)
|
||||
return !rsc->direct.enabled;
|
||||
|
||||
if (!ctx->current_sfc->client_side_rotation)
|
||||
return 0;
|
||||
|
||||
return !rsc->direct.enabled;
|
||||
|
||||
/* was:
|
||||
if ((!evgl_engine->direct_force_off) &&
|
||||
(rsc->id == evgl_engine->main_tid) &&
|
||||
(ctx) &&
|
||||
|
@ -1280,6 +1301,7 @@ _evgl_not_in_pixel_get(void)
|
|||
return 1;
|
||||
else
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1354,6 +1376,7 @@ EVGL_Engine *
|
|||
evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
|
||||
{
|
||||
int direct_mem_opt = 0, direct_off = 0, direct_soff = 0, debug_mode = 0;
|
||||
int direct_override = 0;
|
||||
char *s = NULL;
|
||||
|
||||
if (evgl_engine) return evgl_engine;
|
||||
|
@ -1436,6 +1459,12 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
|
|||
if (direct_mem_opt == 1)
|
||||
evgl_engine->direct_mem_opt = 1;
|
||||
|
||||
// Check for Direct rendering override env var.
|
||||
s = getenv("EVAS_GL_DIRECT_OVERRIDE");
|
||||
if (s) direct_override = atoi(s);
|
||||
if (direct_override == 1)
|
||||
evgl_engine->direct_override = 1;
|
||||
|
||||
// Check if Direct Rendering Override Force Off flag is on
|
||||
s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF");
|
||||
if (s) direct_off = atoi(s);
|
||||
|
@ -1461,6 +1490,9 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
|
|||
if (!gl_funcs) gl_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
|
||||
if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
|
||||
|
||||
// Direct surfaces map texid->Evas_GL_Surface
|
||||
evgl_engine->direct_surfaces = eina_hash_int32_new(NULL);
|
||||
|
||||
return evgl_engine;
|
||||
|
||||
error:
|
||||
|
@ -1496,6 +1528,12 @@ evgl_engine_shutdown(void *eng_data)
|
|||
// Destroy internal resources
|
||||
_evgl_tls_resource_destroy(eng_data);
|
||||
|
||||
if (evgl_engine->direct_surfaces)
|
||||
{
|
||||
eina_hash_free(evgl_engine->direct_surfaces);
|
||||
evgl_engine->direct_surfaces = NULL;
|
||||
}
|
||||
|
||||
LKD(evgl_engine->resource_lock);
|
||||
|
||||
// Free engine
|
||||
|
@ -1507,8 +1545,6 @@ void *
|
|||
evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
|
||||
{
|
||||
EVGL_Surface *sfc = NULL;
|
||||
char *s = NULL;
|
||||
int direct_override = 0, direct_mem_opt = 0;
|
||||
Eina_Bool need_reconfigure = EINA_FALSE;
|
||||
Eina_Bool dbg;
|
||||
|
||||
|
@ -1537,25 +1573,6 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Check for Direct rendering override env var.
|
||||
if (!evgl_engine->direct_override)
|
||||
if ((s = getenv("EVAS_GL_DIRECT_OVERRIDE")))
|
||||
{
|
||||
direct_override = atoi(s);
|
||||
if (direct_override == 1)
|
||||
evgl_engine->direct_override = 1;
|
||||
}
|
||||
|
||||
// Check if Direct Rendering Memory Optimzation flag is on
|
||||
// Creates resources on demand when it fallsback to fbo rendering
|
||||
if (!evgl_engine->direct_mem_opt)
|
||||
if ((s = getenv("EVAS_GL_DIRECT_MEM_OPT")))
|
||||
{
|
||||
direct_mem_opt = atoi(s);
|
||||
if (direct_mem_opt == 1)
|
||||
evgl_engine->direct_mem_opt = 1;
|
||||
}
|
||||
|
||||
// Allocate surface structure
|
||||
sfc = calloc(1, sizeof(EVGL_Surface));
|
||||
if (!sfc)
|
||||
|
@ -1629,6 +1646,12 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
|
|||
LKL(evgl_engine->resource_lock);
|
||||
evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
|
||||
|
||||
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->direct_fb_opt &&
|
||||
(sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
|
||||
{
|
||||
|
@ -1776,6 +1799,7 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
|
|||
EVGL_Resource *rsc;
|
||||
Eina_Bool need_reconfigure = EINA_FALSE;
|
||||
Eina_Bool dbg;
|
||||
GLuint texid;
|
||||
|
||||
// FIXME: This does some make_current(0,0) which may have side effects
|
||||
|
||||
|
@ -1842,6 +1866,7 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
|
|||
|
||||
|
||||
// Destroy created buffers
|
||||
texid = sfc->color_buf;
|
||||
if (!_surface_buffers_destroy(sfc))
|
||||
{
|
||||
ERR("Error deleting surface resources.");
|
||||
|
@ -1875,6 +1900,12 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
|
|||
LKL(evgl_engine->resource_lock);
|
||||
evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
|
||||
|
||||
if (sfc->direct_fb_opt)
|
||||
{
|
||||
eina_hash_del(evgl_engine->direct_surfaces, &texid, sfc);
|
||||
DBG("Removed tex %d from the direct surface: %p", texid, sfc);
|
||||
}
|
||||
|
||||
if (sfc->direct_fb_opt &&
|
||||
(sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
|
||||
{
|
||||
|
@ -2369,23 +2400,77 @@ evgl_direct_rendered()
|
|||
return rsc->direct.rendered;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function can tell the engine whether a surface can be directly
|
||||
* rendered to the Evas, despite any window rotation. For that purpose,
|
||||
* we let the engine know the surface flags for this texture
|
||||
*/
|
||||
Eina_Bool
|
||||
evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
|
||||
Eina_Bool *direct_render,
|
||||
Eina_Bool *client_side_rotation)
|
||||
{
|
||||
EVGL_Surface *sfc;
|
||||
|
||||
if (direct_render) *direct_render = 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (evgl_engine->api_debug_mode)
|
||||
{
|
||||
DBG("Found native surface: texid:%u DR:%d CSR:%d",
|
||||
ns->data.opengl.texture_id, (int) sfc->direct_fb_opt,
|
||||
(int) sfc->client_side_rotation);
|
||||
}
|
||||
|
||||
if (direct_render) *direct_render = sfc->direct_fb_opt;
|
||||
if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
evgl_direct_info_set(int win_w, int win_h, int rot,
|
||||
int img_x, int img_y, int img_w, int img_h,
|
||||
int clip_x, int clip_y, int clip_w, int clip_h)
|
||||
int clip_x, int clip_y, int clip_w, int clip_h,
|
||||
unsigned int texid)
|
||||
{
|
||||
EVGL_Resource *rsc;
|
||||
EVGL_Surface *sfc;
|
||||
|
||||
if (!(rsc=_evgl_tls_resource_get())) return;
|
||||
if (!(rsc = _evgl_tls_resource_get()))
|
||||
return;
|
||||
|
||||
/* Normally direct rendering isn't allowed if rotation is not 0.
|
||||
* BUT, if client_side_rotation or override is on, allow it.
|
||||
/* Check for direct rendering
|
||||
*
|
||||
* DR is allowed iif:
|
||||
* - Rotation == 0
|
||||
* OR: - Client-Side Rotation is set on the surface
|
||||
* - Direct Override is set
|
||||
*
|
||||
* If the surface is not found, we assume indirect rendering.
|
||||
*/
|
||||
if ((rot == 0) || evgl_engine->direct_override ||
|
||||
(rsc->current_ctx &&
|
||||
rsc->current_ctx->current_sfc &&
|
||||
rsc->current_ctx->current_sfc->client_side_rotation))
|
||||
|
||||
sfc = eina_hash_find(evgl_engine->direct_surfaces, &texid);
|
||||
|
||||
if ((rot == 0) ||
|
||||
evgl_engine->direct_override ||
|
||||
(sfc && sfc->client_side_rotation))
|
||||
{
|
||||
if (evgl_engine->api_debug_mode)
|
||||
DBG("Direct rendering is enabled.");
|
||||
|
||||
rsc->direct.enabled = EINA_TRUE;
|
||||
|
||||
rsc->direct.win_w = win_w;
|
||||
|
@ -2404,6 +2489,9 @@ evgl_direct_info_set(int win_w, int win_h, int rot,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (evgl_engine->api_debug_mode)
|
||||
DBG("Direct rendering is disabled.");
|
||||
|
||||
rsc->direct.enabled = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -2459,8 +2547,8 @@ evgl_direct_partial_info_clear()
|
|||
void
|
||||
evgl_direct_override_get(int *override, int *force_off)
|
||||
{
|
||||
*override = evgl_engine->direct_override;
|
||||
*force_off = evgl_engine->direct_force_off;
|
||||
if (override) *override = evgl_engine->direct_override;
|
||||
if (force_off) *force_off = evgl_engine->direct_force_off;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -40,9 +40,14 @@ int evgl_direct_rendered();
|
|||
void evgl_direct_override_get(int *override, int *force_off);
|
||||
void evgl_direct_info_set(int win_w, int win_h, int rot,
|
||||
int img_x, int img_y, int img_w, int img_h,
|
||||
int clip_x, int clip_y, int clip_w, int clip_h);
|
||||
int clip_x, int clip_y, int clip_w, int clip_h,
|
||||
unsigned int texid);
|
||||
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);
|
||||
|
||||
void evgl_direct_partial_info_set(int pres);
|
||||
void evgl_direct_partial_info_clear();
|
||||
void evgl_direct_partial_render_start();
|
||||
|
|
|
@ -294,6 +294,8 @@ struct _EVGL_Engine
|
|||
|
||||
int direct_override;
|
||||
int direct_mem_opt;
|
||||
|
||||
// Add more debug logs (DBG levels 4 and 6)
|
||||
int api_debug_mode;
|
||||
|
||||
// Force Off for Debug purposes
|
||||
|
@ -305,6 +307,7 @@ struct _EVGL_Engine
|
|||
// Keep track of all the current surfaces/contexts
|
||||
Eina_List *surfaces;
|
||||
Eina_List *contexts;
|
||||
Eina_Hash *direct_surfaces; // unsigned (texid) --> EVGL_Surface*
|
||||
Eina_List *direct_depth_stencil_surfaces;
|
||||
|
||||
//void *engine_data;
|
||||
|
|
|
@ -818,8 +818,6 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
|
|||
(n->data.opengl.framebuffer_id == 0) &&
|
||||
re->func.get_pixels)
|
||||
{
|
||||
DBG("Rendering Directly to the window: %p", data);
|
||||
|
||||
gl_context->dc = context;
|
||||
if ((gl_context->master_clip.enabled) &&
|
||||
(gl_context->master_clip.w > 0) &&
|
||||
|
@ -837,7 +835,8 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
|
|||
gl_context->dc->clip.x,
|
||||
gl_context->dc->clip.y,
|
||||
gl_context->dc->clip.w,
|
||||
gl_context->dc->clip.h);
|
||||
gl_context->dc->clip.h,
|
||||
n->data.opengl.texture_id);
|
||||
|
||||
// Call pixel get function
|
||||
re->func.get_pixels(re->func.get_pixels_data, re->func.obj);
|
||||
|
@ -1245,6 +1244,26 @@ eng_gl_direct_override_get(void *data, int *override, int *force_off)
|
|||
evgl_direct_override_get(override, force_off);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eng_gl_surface_direct_renderable_get(void *data, Evas_Native_Surface *ns)
|
||||
{
|
||||
Render_Engine_GL_Generic *re = data;
|
||||
Eina_Bool direct_render, client_side_rotation;
|
||||
|
||||
EVGLINIT(data, EINA_FALSE);
|
||||
if (!re || !ns) return EINA_FALSE;
|
||||
if (!evgl_native_surface_direct_opts_get(ns, &direct_render, &client_side_rotation))
|
||||
return EINA_FALSE;
|
||||
|
||||
if (!direct_render)
|
||||
return EINA_FALSE;
|
||||
|
||||
if ((re->software.outbuf_get_rot(re->software.ob) != 0) && (!client_side_rotation))
|
||||
return EINA_FALSE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj)
|
||||
{
|
||||
|
@ -1926,6 +1945,7 @@ module_open(Evas_Module *em)
|
|||
ORD(gl_native_surface_get);
|
||||
ORD(gl_api_get);
|
||||
ORD(gl_direct_override_get);
|
||||
ORD(gl_surface_direct_renderable_get);
|
||||
ORD(gl_get_pixels_set);
|
||||
ORD(gl_surface_lock);
|
||||
ORD(gl_surface_read_pixels);
|
||||
|
|
|
@ -3098,6 +3098,7 @@ static Evas_Func func =
|
|||
NULL, // need software mesa for gl rendering <- gl_current_surface_get
|
||||
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
|
||||
eng_image_load_error_get,
|
||||
eng_font_run_font_end_get,
|
||||
eng_image_animated_get,
|
||||
|
@ -3106,7 +3107,7 @@ static Evas_Func func =
|
|||
eng_image_animated_loop_count_get,
|
||||
eng_image_animated_frame_duration_get,
|
||||
eng_image_animated_frame_set,
|
||||
NULL,
|
||||
NULL, // image_max_size_get
|
||||
eng_multi_font_draw,
|
||||
eng_pixel_alpha_get,
|
||||
NULL, // eng_context_flush - software doesn't use it
|
||||
|
|
Loading…
Reference in New Issue