jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=4cf2d75715d6d9c3bc7f02a246997b0ca7a330cd

commit 4cf2d75715d6d9c3bc7f02a246997b0ca7a330cd
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Tue Dec 9 21:36:45 2014 +0900

    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.
---
 src/lib/evas/canvas/evas_object_image.c            |  20 +--
 src/lib/evas/include/evas_private.h                |   1 +
 src/modules/evas/engines/gl_common/evas_gl_core.c  | 154 ++++++++++++++++-----
 src/modules/evas/engines/gl_common/evas_gl_core.h  |   7 +-
 .../evas/engines/gl_common/evas_gl_core_private.h  |   3 +
 src/modules/evas/engines/gl_generic/evas_engine.c  |  26 +++-
 .../evas/engines/software_generic/evas_engine.c    |   3 +-
 7 files changed, 167 insertions(+), 47 deletions(-)

diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index fdd7161..ce03b71 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -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
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 4f057c9..c00cc50 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -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);
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 c0d7a2b..9d58f02 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -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;
-
-   /* Normally direct rendering isn't allowed if rotation is not 0.
-    * BUT, if client_side_rotation or override is on, allow it.
+   if (!(rsc = _evgl_tls_resource_get()))
+     return;
+
+   /* 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
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 f74a9c1..9dcb5bb 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.h
@@ -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();
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h 
b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
index ec30529..a13d369 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
@@ -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;  
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index 6371fe7..45d35ea 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -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);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index f2a355a..ac9e086 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -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

-- 


Reply via email to