EvasGL: Add PreRotation
authorWonsik, Jung <sidein@samsung.com>
Tue, 12 Dec 2017 09:47:52 +0000 (18:47 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 13:28:35 +0000 (22:28 +0900)
Add PreRotation feature for Evas GL's direct rendering

@TIZEN_ONLY
Change-Id: I7548a8f7ec516aebc30df64cc2216dcb1dcd41a0

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_core.c
src/modules/evas/engines/gl_common/evas_gl_core_private.h
src/modules/evas/engines/gl_drm/evas_engine.c
src/modules/evas/engines/gl_sdl/evas_engine.c
src/modules/evas/engines/gl_tbm/evas_engine.c
src/modules/evas/engines/gl_x11/evas_engine.c
src/modules/evas/engines/wayland_egl/evas_engine.c
src/modules/evas/engines/wayland_egl/evas_engine.h
src/modules/evas/engines/wayland_egl/evas_wl_main.c

index 7b8189f..08acdf0 100755 (executable)
@@ -392,6 +392,10 @@ struct _Evas_Engine_GL_Context
 
    GLuint preserve_bit;
    int    gles_version;
+
+   //TIZEN_ONLY(20161121)
+   // If set, the driver will rotate the buffer itself
+   Eina_Bool pre_rotated : 1;
 };
 
 struct _Evas_GL_Texture_Pool
index bcd286b..a899965 100755 (executable)
@@ -1650,6 +1650,16 @@ try_again:
 
              // Extra flags for render thread // TIZEN_ONLY(20171114) : EvasGL Render Thread
              sfc->thread_rendering = !!(cfg->options_bits & EVAS_GL_OPTIONS_THREAD);
+            //TIZEN_ONLY(20161121)
+             // Pre-rotation should be enabled only when direct rendering is set but client side rotation is not set
+             if ((sfc->direct_fb_opt) &&
+                 (!sfc->client_side_rotation) &&
+                 (evgl_engine->funcs->native_win_prerotation_set))
+               {
+                  if (!evgl_engine->funcs->native_win_prerotation_set(eng_data))
+                    DBG("Prerotation does not work");
+               }
+             //
 
              cfg_index = i;
              break;
index 8b8aaec..582fcf8 100755 (executable)
@@ -354,6 +354,10 @@ struct _EVGL_Interface
    // Check native window surface config for Evas GL Direct Rendering
    void        (*native_win_surface_config_get)(void *data, int *win_depth, int *win_stencil, int *win_msaa);
 
+   //TIZEN_ONLY(20161121) Support PreRotation
+   int         (*native_win_prerotation_set)(void *data);
+
+
    // TIZEN_ONLY(20171206) : Disable Partial Rendering On EvasGL
    // partial rendering enable
    void        (*partial_rendering_enable)();
index d294d41..e3419d9 100755 (executable)
@@ -119,6 +119,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    NULL, // native_win_surface_config_get
+   NULL, // native_win_prerotation_set
    NULL, //partial_rendering_enable
    NULL, //partial_rendering_disable
 };
index c7c64d8..e6a968d 100755 (executable)
@@ -259,6 +259,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    NULL, // native_win_surface_config_get
+   NULL, // native_win_prerotation_set
    NULL, //partial_rendering_enable
    NULL, //partial_rendering_disable
 };
index 882ec41..5c1f716 100755 (executable)
@@ -896,9 +896,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    evgl_eng_native_win_surface_config_get,
-#if 0
    NULL, // native_win_prerotation_set
-#endif
    NULL, //partial_rendering_enable
    NULL, //partial_rendering_disable
 };
index 50ee951..c13b0c3 100755 (executable)
@@ -1261,6 +1261,7 @@ static const EVGL_Interface evgl_funcs =
    evgl_eng_indirect_surface_destroy,
    evgl_eng_gles_context_create,
    evgl_eng_native_win_surface_config_get,
+   NULL, // native_win_prerotation_set
    NULL, //partial_rendering_enable
    NULL, //partial_rendering_disable
 };
index 7139c6a..dbd0c5c 100755 (executable)
@@ -76,6 +76,14 @@ unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGL
 unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d) = NULL;
 unsigned int (*glsym_eglQueryWaylandBufferWL)(EGLDisplay a, void *b, EGLint c, EGLint *d) = NULL;
 
+//TIZEN_ONLY(20161121) : Support PreRotation
+////////////////////////////////////
+//libwayland-client.so.0
+static void *wl_client_lib_handle = NULL;
+wl_egl_win_get_capabilities glsym_wl_egl_win_get_capabilities = NULL;
+wl_egl_win_set_rotation glsym_wl_egl_win_set_rotation = NULL;
+//
+
 /* local variables */
 static Eina_Bool initted = EINA_FALSE;
 static int gl_wins = 0;
@@ -185,6 +193,38 @@ eng_gl_symbols(EGLDisplay edsp)
    done = EINA_TRUE;
 }
 
+//TIZEN_ONLY(20161121) : Support PreRotation
+static void
+pre_rotation_symbols(void)
+{
+   static Eina_Bool init_pre_rotation_syms = EINA_FALSE;
+   if (init_pre_rotation_syms) return;
+   init_pre_rotation_syms = EINA_TRUE;
+
+#ifdef GL_GLES
+   const char *wayland_egl_lib = LIBDIR"/libwayland-egl.so.1";
+   wl_client_lib_handle = dlopen(wayland_egl_lib, RTLD_NOW);
+   if (!wl_client_lib_handle)
+     {
+        ERR("Unable to open libtbm: %s", dlerror());
+        return;
+     }
+
+#define FIND_EGL_WL_SYM(dst, sym, typ) \
+   if (!dst) dst = (typ)dlsym(wl_client_lib_handle, sym); \
+   if (!dst)  \
+     { \
+        ERR("Symbol not found %s\n", sym); \
+        return; \
+     }
+
+   FIND_EGL_WL_SYM(glsym_wl_egl_win_set_rotation, "wl_egl_window_set_rotation", glsym_func_void);
+   FIND_EGL_WL_SYM(glsym_wl_egl_win_get_capabilities, "wl_egl_window_get_capabilities", glsym_func_int);
+
+#undef FIND_EGL_WL_SYM
+#endif
+}
+
 static void
 gl_extn_veto(Render_Engine *re)
 {
@@ -263,6 +303,43 @@ _re_winfree(Render_Engine *re)
    eng_window_unsurf(ob);
 }
 
+//TIZEN_ONLY(20161121) : Support PreRotation
+static void
+_evas_native_win_pre_rotation_set(struct wl_egl_window *win, int angle)
+{
+    evas_wl_egl_window_rotation rot;
+    if (!win) return;
+    if (!glsym_wl_egl_win_set_rotation)
+      {
+         ERR("Not supported PreRotation");
+         return;
+      }
+
+    switch (angle)
+      {
+         case 270:
+            rot = EVAS_ROTATION_90;
+            break;
+         case 180:
+            rot = EVAS_ROTATION_180;
+            break;
+         case 90:
+            rot = EVAS_ROTATION_270;
+            break;
+         case 0:
+            rot = EVAS_ROTATION_0;
+            break;
+         default:
+            rot = EVAS_ROTATION_0;
+            break;
+      }
+
+    if (glsym_wl_egl_win_set_rotation)
+      {
+         glsym_wl_egl_win_set_rotation(win, rot);
+      }
+}
+
 static void *
 evgl_eng_display_get(void *data)
 {
@@ -589,6 +666,29 @@ evgl_eng_pbuffer_surface_destroy(void *data, void *surface)
    return 1;
 }
 
+//TIZEN_ONLY(20161121) : Support PreRotation
+static int
+evgl_eng_native_win_prerotation_set(void *data)
+{
+   Render_Engine *re = data;
+   if (!re) return 0;
+   if (!(eng_get_ob(re)->support_pre_rotation)) return 0;
+   if (eng_get_ob(re)->gl_context->pre_rotated) return 0;
+
+   _evas_native_win_pre_rotation_set(eng_get_ob(re)->win, eng_get_ob(re)->info->info.rotation);
+
+   // re->win's h & w are not modified
+   eng_get_ob(re)->rot = 0;
+
+   /* There maybe bad frame due to mismatch of surface and
+    * window size if orientation changes in the middle of
+    * rendering pipeline, therefore recreate the surface.
+    */
+   eng_get_ob(re)->gl_context->pre_rotated = EINA_TRUE;
+
+   return 1;
+}
+
 // TIZEN_ONLY(20171206) : Disable Partial Rendering On EvasGL
 static void
 evgl_eng_partial_rendering_enable()
@@ -625,6 +725,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    NULL, // native_win_surface_config_get
+   evgl_eng_native_win_prerotation_set,
    evgl_eng_partial_rendering_enable,
    evgl_eng_partial_rendering_disable,
 };
@@ -818,8 +919,16 @@ eng_output_update(void *engine EINA_UNUSED, void *data, void *info, unsigned int
              gl_wins++;
           }
         else if ((ob->w != (int)w) || (ob->h != (int)h) ||
-                 (ob->info->info.rotation != ob->rot))
+                 (ob->info->info.rotation != ob->rot) ||
+                 (ob->gl_context->pre_rotated))
           {
+            //TIZEN_ONLY(20161121) : Support PreRotation
+            if (ob->support_pre_rotation && ob->gl_context->pre_rotated)
+              {
+                 ob->gl_context->pre_rotated = EINA_FALSE;
+                 evgl_eng_native_win_prerotation_set(re);
+              }
+
              eng_outbuf_reconfigure(ob, w, h,
                                     ob->info->info.rotation, 0);
           }
@@ -1550,6 +1659,10 @@ module_open(Evas_Module *em)
    evas_gl_thread_link_init();
    symbols();
 
+   //TIZEN_ONLY(20161121) : Support PreRotation
+   pre_rotation_symbols();
+   //
+
    /* advertise out which functions we support */
    em->functions = (void *)(&func);
 
index f5aedbb..951c053 100755 (executable)
@@ -91,6 +91,9 @@ struct _Outbuf
    int depth_bits;
    int stencil_bits;
    int msaa_bits;
+
+   //TIZEN_ONLY(20161121) : Support PreRotation
+   int support_pre_rotation;
 };
 
 struct _Context_3D
@@ -153,4 +156,26 @@ _re_wincheck(Outbuf *ob)
    return 0;
 }
 
+enum evas_wl_egl_window_capability_rotation {
+    EVAS_WL_EGL_WINDOW_CAPABILITY_NONE = 0,
+    EVAS_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED = (1 << 0),
+    EVAS_WL_EGL_WINDOW_CAPABILITY_ROTATION_UNSUPPORTED = (1 << 1),
+    EVAS_WL_EGL_WINDOW_CAPABILITY_ROTATION_UNKNOWN = (1 << 2),
+};
+
+typedef enum {
+    EVAS_ROTATION_0 = 0,
+    EVAS_ROTATION_90 = 90,
+    EVAS_ROTATION_180 = 180,
+    EVAS_ROTATION_270 = 270
+} evas_wl_egl_window_rotation;
+
+//TIZEN_ONLY(20161121) : Support PreRotation
+typedef int (*wl_egl_win_get_capabilities) (struct wl_egl_window *egl_window);
+typedef void (*wl_egl_win_set_rotation) (struct wl_egl_window *egl_window, int rotation);
+
+extern wl_egl_win_get_capabilities glsym_wl_egl_win_get_capabilities;
+extern wl_egl_win_set_rotation glsym_wl_egl_win_set_rotation;
+//
+
 #endif
index 206cafd..51da9de 100755 (executable)
@@ -118,6 +118,10 @@ eng_window_new(Evas_Engine_Info_Wayland *einfo, int w, int h, Render_Output_Swap
    gw->stencil_bits = einfo->stencil_bits;
    gw->msaa_bits = einfo->msaa_bits;
 //
+//TIZEN_ONLY(20161121):Support PreRotation
+   gw->support_pre_rotation = 0;
+//
+
    context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
    context_attrs[1] = 2;
    context_attrs[2] = EGL_NONE;
@@ -225,6 +229,26 @@ eng_window_new(Evas_Engine_Info_Wayland *einfo, int w, int h, Render_Output_Swap
     }
 // TIZEN_ONLY(20171123)
 
+//TIZEN_ONLY(20161121):Support PreRotation
+   if (!getenv("EVAS_GL_PREROTATION_DISABLE") && glsym_wl_egl_win_get_capabilities)
+     {
+        int prerotation_cap = EVAS_WL_EGL_WINDOW_CAPABILITY_NONE;
+        prerotation_cap = glsym_wl_egl_win_get_capabilities(gw->win);
+        if (prerotation_cap == EVAS_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED)
+          {
+             gw->support_pre_rotation = 1;
+          }
+        else
+          {
+             gw->support_pre_rotation = 0;
+          }
+     }
+   else
+     {
+        DBG("PreRotation is invalid!!");
+     }
+//TIZEN_ONLY(20161121)
+
    context = _tls_context_get();
    gw->egl_context =
      GL_TH(eglCreateContext, gw->egl_disp, gw->egl_config, context, context_attrs);