evas: make Evas_GL work with multi output.

This commit is contained in:
Cedric BAIL 2017-08-25 10:54:19 -07:00
parent 7f8bbe4972
commit 545c1a70f4
6 changed files with 160 additions and 47 deletions

View File

@ -1647,10 +1647,10 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
if (!o->direct_render)
{
if (ENFN->gl_get_pixels_pre)
ENFN->gl_get_pixels_pre(output);
ENFN->gl_get_pixels_pre(engine, output);
o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, eo_obj);
if (ENFN->gl_get_pixels_post)
ENFN->gl_get_pixels_post(output);
ENFN->gl_get_pixels_post(engine, output);
}
if (!(obj->cur->geometry.x == x &&
@ -1674,6 +1674,8 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
{
Evas_Native_Surface *ns;
ns = ENFN->image_native_get(engine, o->engine_data);
fprintf(stderr, "direct render\n");
if (ENFN->gl_direct_override_get)
ENFN->gl_direct_override_get(engine, &direct_override, &direct_force_off);
if (ENFN->gl_surface_direct_renderable_get)
@ -1691,10 +1693,10 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
{
// Auto-fallback to FBO rendering (for perf & power consumption)
if (ENFN->gl_get_pixels_pre)
ENFN->gl_get_pixels_pre(engine);
ENFN->gl_get_pixels_pre(engine, output);
o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, obj->object);
if (ENFN->gl_get_pixels_post)
ENFN->gl_get_pixels_post(engine);
ENFN->gl_get_pixels_post(engine, output);
o->direct_render = EINA_FALSE;
}
}

View File

@ -3331,6 +3331,10 @@ evas_render_updates_internal(Evas *eo_e,
}
eina_evlog("-render_phase5", eo_e, 0.0, NULL);
/* Define the output for Evas_GL operation */
if (ENFN->gl_output_set)
ENFN->gl_output_set(ENC, ENDT);
/* phase 6. check if video surface should be inlined or stay in their hardware plane */
eina_evlog("+render_phase6", eo_e, 0.0, NULL);
alpha = ENFN->canvas_alpha_get(ENDT);
@ -3571,6 +3575,7 @@ evas_render_updates_internal(Evas *eo_e,
else if (obj->delete_me != 0) obj->delete_me++;
*/
}
for (i = 0; i < e->snapshot_objects.count; i++)
{
Evas_Object_Protected_Data *snap;
@ -3582,6 +3587,10 @@ evas_render_updates_internal(Evas *eo_e,
eina_evlog("-render_post", eo_e, 0.0, NULL);
IFRD(e->active_objects.len, 0, " ---]\n");
/* Set back Evas_GL output to NULL */
/* if (ENFN->gl_output_set) */
/* ENFN->gl_output_set(ENC, NULL); */
/* free our obscuring object list */
OBJS_ARRAY_CLEAN(&e->obscuring_objects);

View File

@ -1539,6 +1539,7 @@ struct _Evas_Func
int (*font_right_inset_get) (void *engine, Evas_Font_Set *font, const Evas_Text_Props *text_props);
/* EFL-GL Glue Layer */
void *(*gl_output_set) (void *engine, void *output);
void *(*gl_surface_create) (void *engine, void *config, int w, int h);
void *(*gl_pbuffer_surface_create) (void *engine, void *config, int w, int h, int const *attrib_list);
int (*gl_surface_destroy) (void *engine, void *surface);
@ -1562,8 +1563,8 @@ struct _Evas_Func
Eina_Bool (*gl_surface_direct_renderable_get) (void *engine, void *output, Evas_Native_Surface *ns, Eina_Bool *override, void *surface);
void (*gl_image_direct_set) (void *engine, void *image, Eina_Bool direct);
int (*gl_image_direct_get) (void *engine, void *image);
void (*gl_get_pixels_pre) (void *engine);
void (*gl_get_pixels_post) (void *engine);
void (*gl_get_pixels_pre) (void *engine, void *output);
void (*gl_get_pixels_post) (void *engine, void *output);
int (*image_load_error_get) (void *engine, void *image);
int (*font_run_end_get) (void *engine, 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);

View File

@ -22,11 +22,15 @@ struct _Render_Engine_GL_Generic
{
Render_Engine_Software_Generic software;
Render_Output_GL_Generic *current;
struct {
Evas_Object_Image_Pixels_Get_Cb get_pixels;
void *get_pixels_data;
Evas_Object *obj;
} func;
Eina_Bool evgl_initted : 1;
};
struct _Render_Output_GL_Generic
@ -42,8 +46,6 @@ struct _Render_Output_GL_Generic
Context_3D *context_3d;
E3D_Renderer *renderer_3d;
const EVGL_Interface *evgl_funcs;
Eina_Bool evgl_initted : 1;
};
static inline Eina_Bool
@ -96,8 +98,6 @@ evas_render_engine_gl_generic_init(Render_Engine_Software_Generic *engine,
re->renderer_3d = NULL;
re->evgl_funcs = evgl_funcs;
re->evgl_initted = EINA_FALSE;
evas_render_engine_software_generic_tile_strict_set(&re->software, EINA_TRUE);
return EINA_TRUE;

View File

@ -57,6 +57,37 @@ static Eina_Bool eng_gl_surface_read_pixels(void *data, void *surface, int x, in
Eina_Bool _need_context_restore = EINA_FALSE;
static Render_Output_GL_Generic *
_evgl_output_find(Render_Engine_GL_Generic *engine)
{
Render_Output_GL_Generic *output = NULL;
EVGL_Resource *rsc;
Eina_List *l;
if (engine->current)
{
output = engine->current;
goto picked;
}
rsc = _evgl_tls_resource_get();
if (rsc &&
rsc->stored.data)
{
EINA_LIST_FOREACH(engine->software.outputs, l, output)
if (output == rsc->stored.data) goto picked;
}
EINA_LIST_FOREACH(engine->software.outputs, l, output)
{
if (output->software.ob) goto picked;
}
return NULL;
picked:
return output;
}
static Evas_Func func, pfunc;
void
@ -1434,24 +1465,65 @@ eng_font_draw(void *engine EINA_UNUSED, void *data, void *context, void *surface
//--------------------------------//
// Evas GL Related Code
static int
evgl_init(Render_Output_GL_Generic *re)
static inline Eina_Bool
evgl_init_do(Render_Engine_GL_Generic *engine,
Render_Output_GL_Generic *output)
{
if (re->evgl_initted) return 1;
if (!evgl_engine_init(re, re->evgl_funcs)) return 0;
re->evgl_initted = EINA_TRUE;
return 1;
if (engine->evgl_initted) return EINA_TRUE;
if (!evgl_engine_init(output, output->evgl_funcs))
return EINA_FALSE;
engine->current = output;
engine->evgl_initted = EINA_TRUE;
return EINA_TRUE;
}
#define EVGLINIT(_re, _ret) if (!evgl_init(_re)) return _ret
static Render_Output_GL_Generic *
evgl_init(Render_Engine_GL_Generic *engine)
{
Render_Output_GL_Generic *output = NULL;
Eina_List *l;
if (engine->evgl_initted)
{
if (engine->current) return engine->current;
EINA_LIST_FOREACH(engine->software.outputs, l, output)
if (output->software.ob) return output;
ERR("Evas_GL backend initializeod, but no window found !");
return NULL;
}
EINA_LIST_FOREACH(engine->software.outputs, l, output)
{
if (!output->software.ob) continue;
if (evgl_init_do(engine, output))
return output;
}
return NULL;
}
#define EVGLINIT(_ret) Render_Output_GL_Generic *re; if ((re = evgl_init(engine)) == NULL) return _ret
static void *
eng_gl_output_set(void *eng, void *output)
{
Render_Engine_GL_Generic *engine = eng;
Render_Output_GL_Generic *previous = engine->current;
engine->current = output;
return previous;
}
static void *
eng_gl_surface_create(void *engine, void *config, int w, int h)
{
Evas_GL_Config *cfg = (Evas_GL_Config *)config;
EVGLINIT(engine, NULL);
return evgl_surface_create(engine, cfg, w, h);
EVGLINIT(NULL);
return evgl_surface_create(re, cfg, w, h);
}
static void *
@ -1459,18 +1531,20 @@ eng_gl_pbuffer_surface_create(void *engine, void *config, int w, int h, const in
{
Evas_GL_Config *cfg = (Evas_GL_Config *)config;
EVGLINIT(engine, NULL);
return evgl_pbuffer_surface_create(engine, cfg, w, h, attrib_list);
EVGLINIT(NULL);
return evgl_pbuffer_surface_create(re, cfg, w, h, attrib_list);
}
static int
eng_gl_surface_destroy(void *engine, void *surface)
{
EVGL_Surface *sfc = (EVGL_Surface *)surface;
Render_Engine_GL_Generic *e;
EVGLINIT(engine, 0);
CONTEXT_STORED_RESET(engine, surface);
return evgl_surface_destroy(engine, sfc);
EVGLINIT(0);
if (e->current == re) e->current = NULL;
CONTEXT_STORED_RESET(re, surface);
return evgl_surface_destroy(re, sfc);
}
static void *
@ -1480,8 +1554,8 @@ eng_gl_context_create(void *engine, void *share_context, int version,
{
EVGL_Context *sctx = (EVGL_Context *)share_context;
EVGLINIT(engine, NULL);
return evgl_context_create(engine, sctx, version, native_context_get, engine_data_get);
EVGLINIT(NULL);
return evgl_context_create(re, sctx, version, native_context_get, engine_data_get);
}
static int
@ -1489,15 +1563,17 @@ eng_gl_context_destroy(void *engine, void *context)
{
EVGL_Context *ctx = (EVGL_Context *)context;
EVGLINIT(engine, 0);
return evgl_context_destroy(engine, ctx);
EVGLINIT(0);
return evgl_context_destroy(re, ctx);
}
static int
eng_gl_make_current(void *engine, void *surface, void *context)
eng_gl_make_current(void *eng, void *surface, void *context)
{
Render_Engine_GL_Generic *engine = eng;
EVGL_Surface *sfc = (EVGL_Surface *)surface;
EVGL_Context *ctx = (EVGL_Context *)context;
Render_Output_GL_Generic *output;
int ret = 0;
// TODO: Add check for main thread before flush
@ -1516,8 +1592,11 @@ eng_gl_make_current(void *engine, void *surface, void *context)
}
}
ret = evgl_make_current(engine, sfc, ctx);
CONTEXT_STORE(engine, surface, context);
output = _evgl_output_find(engine);
if (!output) return ret;
ret = evgl_make_current(output, sfc, ctx);
CONTEXT_STORE(output, surface, context);
return ret;
}
@ -1537,25 +1616,32 @@ eng_gl_current_surface_get(void *engine EINA_UNUSED)
}
static int
eng_gl_rotation_angle_get(void *engine)
eng_gl_rotation_angle_get(void *eng)
{
Render_Engine_GL_Generic *engine = eng;
Render_Output_GL_Generic *output;
if (!evgl_engine->funcs->rotation_angle_get) return 0;
if (!_evgl_direct_enabled()) return 0;
return evgl_engine->funcs->rotation_angle_get(engine);
// It would be better if that this API was called Evas Output
output = _evgl_output_find(engine);
if (!output) return 0;
return evgl_engine->funcs->rotation_angle_get(output);
}
static const char *
eng_gl_string_query(void *engine, int name)
{
EVGLINIT(engine, NULL);
EVGLINIT(NULL);
return evgl_string_query(name);
}
static void *
eng_gl_proc_address_get(void *engine, const char *name)
{
Render_Output_GL_Generic *re = engine;
EVGLINIT(engine, NULL);
EVGLINIT(NULL);
void *fun = NULL;
if (!evgl_safe_extension_get(name, &fun))
@ -1586,9 +1672,10 @@ eng_gl_native_surface_get(void *engine EINA_UNUSED, void *surface, void *native_
static void *
eng_gl_api_get(void *engine, int version)
{
void *ret;
Render_Output_GL_Generic *output;
Evas_Engine_GL_Context *gl_context;
EVGLINIT(engine, NULL);
void *ret;
EVGLINIT(NULL);
gl_context = gl_generic_context_find(engine);
if (!gl_context)
@ -1601,7 +1688,9 @@ eng_gl_api_get(void *engine, int version)
ERR("Version not supported!");
return NULL;
}
ret = evgl_api_get(engine, version, EINA_TRUE);
output = _evgl_output_find(engine);
ret = evgl_api_get(output, version, EINA_TRUE);
//Disable GLES3 support if symbols not present
if ((!ret) && (version == EVAS_GL_GLES_3_X))
@ -1614,20 +1703,22 @@ eng_gl_api_get(void *engine, int version)
static void
eng_gl_direct_override_get(void *engine, Eina_Bool *override, Eina_Bool *force_off)
{
EVGLINIT(engine, );
EVGLINIT();
evgl_direct_override_get(override, force_off);
}
static Eina_Bool
eng_gl_surface_direct_renderable_get(void *engine, void *output, Evas_Native_Surface *ns, Eina_Bool *override, void *surface)
eng_gl_surface_direct_renderable_get(void *eng, void *output, Evas_Native_Surface *ns, Eina_Bool *override, void *surface)
{
Render_Engine_GL_Generic *engine = eng;
Render_Output_GL_Generic *re = output;
Eina_Bool direct_render, client_side_rotation;
Evas_Engine_GL_Context *gl_context;
Evas_GL_Image *sfc = surface;
if (!re) return EINA_FALSE;
EVGLINIT(engine, EINA_FALSE);
if (!evgl_init_do(engine, re))
return EINA_FALSE;
if (!ns) return EINA_FALSE;
if (!evgl_native_surface_direct_opts_get(ns, &direct_render, &client_side_rotation, override))
return EINA_FALSE;
@ -1656,14 +1747,18 @@ eng_gl_get_pixels_set(void *eng, void *get_pixels, void *get_pixels_data, void *
}
static void
eng_gl_get_pixels_pre(void *engine)
eng_gl_get_pixels_pre(void *e, void *o)
{
EVGLINIT(engine, );
Render_Engine_GL_Generic *engine = e;
Render_Output_GL_Generic *output = o;
if (!evgl_init_do(engine, output))
return ;
evgl_get_pixels_pre();
}
static void
eng_gl_get_pixels_post(void *engine EINA_UNUSED)
eng_gl_get_pixels_post(void *e EINA_UNUSED, void *o EINA_UNUSED)
{
evgl_get_pixels_post();
}
@ -1759,11 +1854,15 @@ eng_gl_surface_read_pixels(void *engine EINA_UNUSED, void *surface,
}
static Eina_Bool
eng_gl_surface_query(void *engine, void *surface, int attr, void *value)
eng_gl_surface_query(void *eng, void *surface, int attr, void *value)
{
Render_Output_GL_Generic *re = engine;
Render_Engine_GL_Generic *engine = eng;
Render_Output_GL_Generic *re;
EVGL_Surface *sfc = surface;
re = _evgl_output_find(engine);
if (!re) return EINA_FALSE;
#ifdef GL_GLES
if (sfc->pbuffer.is_pbuffer)
{
@ -3112,6 +3211,7 @@ module_open(Evas_Module *em)
ORD(font_cache_set);
ORD(font_cache_get);
ORD(gl_output_set);
ORD(gl_surface_create);
ORD(gl_pbuffer_surface_create);
ORD(gl_surface_destroy);

View File

@ -4799,6 +4799,7 @@ static Evas_Func func =
eng_font_pen_coords_get,
eng_font_text_props_info_create,
eng_font_right_inset_get,
NULL, // No need to set output for software engine
NULL, // need software mesa for gl rendering <- gl_surface_create
NULL, // need software mesa for gl rendering <- gl_pbuffer_surface_create
NULL, // need software mesa for gl rendering <- gl_surface_destroy