[EvasGL] Add PreRotation
authorWonsik, Jung <sidein@samsung.com>
Wed, 30 Nov 2016 07:51:10 +0000 (16:51 +0900)
committerWonki Kim <wonki_.kim@samsung.com>
Mon, 2 Jan 2017 07:25:20 +0000 (16:25 +0900)
Add PreRotation feature for Evas GL's direct rendering

Change-Id: I72e840a6c6095fa6d8c456bcedf3feeb281cb993

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 9ed2986334983da86bea247a1199bf8ac5e254f6..c157871006596fe10c809a59404ef3cc03db4ea1 100644 (file)
@@ -348,6 +348,10 @@ struct _Evas_Engine_GL_Context
    RGBA_Image *font_surface;
    // TIZEN_ONLY(20160529): Set this flag for gl_drm engine surface
    int IsGLDRM;
+
+   //TIZEN_ONLY(20161121)
+   // If set, the driver will rotate the buffer itself
+   Eina_Bool pre_rotated : 1;
 };
 
 struct _Evas_GL_Texture_Pool
index 8391d312546d5aa5b02512a93c20b05336b5c684..74d8f6a3a6fa4df0ccdbbfef4ff5ab50b5f1a6aa 100644 (file)
@@ -1465,6 +1465,16 @@ try_again:
              sfc->alpha = (cfg->color_format == EVAS_GL_RGBA_8888);
 
              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))
+                    ERR("Prerotation does not work");
+               }
+             //
 
              cfg_index = i;
              break;
index 7f80585bb3c580e0a26e6a778263be273e1ebbc6..12cc6b058b2e5fac06171c282bd67c540d94f1bc 100644 (file)
@@ -80,6 +80,9 @@ 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);
 };
 
 struct _EVGL_Surface
index f74a4fb0bbc4edbe1a96e041239aee7a888957e6..020e06c7597bbf63e1165f1ecb3decb28e2edb44 100644 (file)
@@ -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
 };
 
 Eina_Bool
index 8c2e8560c30e35acca414167dd93fb6b9b86d321..a9c51f1d541e5d1424680bb7f16d36172c9e79a8 100755 (executable)
@@ -263,6 +263,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
 };
 
 
index 71dd9ac4e9abdf4ae34b98d2a7965e5164ffb701..fa5de9442e68e8c5192802a1ac6fe59035ae938e 100644 (file)
@@ -878,6 +878,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    evgl_eng_native_win_surface_config_get,
+   NULL, // native_win_prerotation_set
 };
 
 /* engine functions */
index 65843404fb3a1de67a1b601cdd1e98636684b9bc..8e50d350e7fb2b78e7b1a35181f4d1c0b2d46b08 100644 (file)
@@ -1202,6 +1202,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
 };
 
 //----------------------------------------------------------//
index c4772937b12bb9519b5d2032ab7971837854e437..552c9a732986423c3c17638a825890c5faed0cfb 100644 (file)
@@ -98,6 +98,14 @@ void (*glsym_evas_gl_common_surface_cache_dump)(void) = NULL;
         prefix##dst = (typ)dst##_thread_cmd; \
      }
 
+//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;
@@ -213,6 +221,38 @@ gl_symbols(void)
    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";
+   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)
 {
@@ -291,6 +331,42 @@ _re_winfree(Render_Engine *re)
    eng_window_unsurf(ob);
 }
 
+static void
+_evas_native_win_pre_rotation_set(struct wl_egl_window *win, int angle)
+{
+    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 = ROTATION_90;
+            break;
+         case 180:
+            rot = ROTATION_180;
+            break;
+         case 90:
+            rot = ROTATION_270;
+            break;
+         case 0:
+            rot = ROTATION_0;
+            break;
+         default:
+            rot = 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)
 {
@@ -862,6 +938,28 @@ evgl_eng_native_win_surface_config_get(void *data, int *win_depth,
        eng_get_ob(re)->detected.msaa);
 }
 
+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)->info->info.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;
+}
+
 static const EVGL_Interface evgl_funcs =
 {
    evgl_eng_display_get,
@@ -882,6 +980,7 @@ static const EVGL_Interface evgl_funcs =
    NULL, // OpenGL-ES 1
    NULL, // OpenGL-ES 1
    evgl_eng_native_win_surface_config_get,
+   evgl_eng_native_win_prerotation_set,
 };
 
 /* engine functions */
@@ -1084,9 +1183,17 @@ eng_setup(Evas *evas, void *info)
                   eng_get_ob(re)->gl_context->references--;
                }
              else if ((ob->w != epd->output.w) || (ob->h != epd->output.h) ||
-                      (ob->info->info.rotation != ob->rot))
+                      (ob->info->info.rotation != ob->rot) ||
+                      (ob->gl_context->pre_rotated))
                {
-                  eng_outbuf_reconfigure(ob, epd->output.w, epd->output.h,
+                 //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, epd->output.w, epd->output.h,
                                          ob->info->info.rotation, 0);
                }
           }
@@ -1840,6 +1947,10 @@ module_open(Evas_Module *em)
    evas_gl_thread_link_init();
    gl_symbols();
 
+   //TIZEN_ONLY(20161121) : Support PreRotation
+   pre_rotation_symbols();
+   //
+
    /* advertise out which functions we support */
    em->functions = (void *)(&func);
 
index a2d0e961f9858320e4cdf5e7d52a4d3e5543f061..0091f84cb1a1644d79041c038b029a60c6c43fab 100755 (executable)
@@ -92,6 +92,9 @@ struct _Outbuf
    int depth_bits;
    int stencil_bits;
    int msaa_bits;
+
+   //TIZEN_ONLY(20161121) : Support PreRotation
+   int support_pre_rotation;
 };
 
 struct _Context_3D
@@ -157,4 +160,12 @@ _re_wincheck(Outbuf *ob)
 // extern void (*glsym_evas_gl_context_restore_set) (Eina_Bool enable);
 //
 
+//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, wl_egl_window_rotation 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 002490edb83c09d5149eea0daedbc5d24d2264ef..d62f0aa1e1ea2fc80876d81cb6782f0c73d07ff0 100644 (file)
@@ -57,6 +57,8 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int
    gw->depth_bits = depth_bits;
    gw->stencil_bits = stencil_bits;
    gw->msaa_bits = msaa_bits;
+   //TIZEN_ONLY(20161121):Support PreRotation
+   gw->support_pre_rotation = 0;
 
    context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
    context_attrs[1] = 2;
@@ -145,6 +147,25 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int
         return NULL;
      }
 
+   //TIZEN_ONLY(20161121):Support PreRotation
+   if (glsym_wl_egl_win_get_capabilities)
+     {
+        int prerotation_cap = WL_EGL_WINDOW_CAPABILITY_NONE;
+        prerotation_cap = glsym_wl_egl_win_get_capabilities(gw->win);
+        if (prerotation_cap == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED)
+          {
+             gw->support_pre_rotation = 1;
+          }
+        else
+          {
+            gw->support_pre_rotation = 0;
+          }
+     }
+   else
+     {
+        DBG("PreRotation API is Invalid!!");
+     }
+
    gw->egl_context[0] = 
      eglCreateContext(gw->egl_disp, gw->egl_config, context, context_attrs);
    if (gw->egl_context[0] == EGL_NO_CONTEXT)