evas: make Evas_GL work with multi output.
authorCedric BAIL <cedric@osg.samsung.com>
Fri, 25 Aug 2017 17:54:19 +0000 (10:54 -0700)
committerCedric BAIL <cedric@osg.samsung.com>
Fri, 25 Aug 2017 17:54:19 +0000 (10:54 -0700)
src/lib/evas/canvas/evas_object_image.c
src/lib/evas/canvas/evas_render.c
src/lib/evas/include/evas_private.h
src/modules/evas/engines/gl_generic/Evas_Engine_GL_Generic.h
src/modules/evas/engines/gl_generic/evas_engine.c
src/modules/evas/engines/software_generic/evas_engine.c

index 6d23f1a..097fb9d 100644 (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;
                }
           }
index 6531588..1dd9141 100644 (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);
 
index 849a7d5..146238b 100644 (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);
index 043d7f7..7fdea30 100644 (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;
index 67b5890..60f65ef 100644 (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);
index ade91f4..d7253de 100644 (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