wayland_egl: use LINUX_DMA_BUF_EXT when EGLImage is created with tbm_surface 52/260552/9
authorChangyeon Lee <cyeon.lee@samsung.com>
Wed, 23 Jun 2021 10:48:49 +0000 (19:48 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Thu, 12 Aug 2021 06:27:38 +0000 (15:27 +0900)
It is possible gl driver doesn't support EGL_TIZEN_image_native_surface.
but if gl dirver support EGL_EXT_image_dma_buf_import, we can use it
instead of EGL_TIZEN_image_native_surface.

This patch try to use EGL_EXT_image_dma_buf_import extension if
EGL_TIZEN_image_native_surface extension isn't supported when
eglImage is created with tbm_surface.

Change-Id: Ia779101d32448d966343034495dad899574f8552

src/modules/evas/engines/wayland_egl/evas_engine.c

index b5749e2..decbef9 100755 (executable)
@@ -3,6 +3,8 @@
 #include "../gl_common/evas_gl_define.h"
 #include "../software_generic/evas_native_common.h"
 
+#include <tbm_bufmgr.h>
+
 #ifdef HAVE_DLSYM
 # include <dlfcn.h>
 #endif
 # define EGL_Y_INVERTED_NOK 0x307F
 #endif
 
+#ifndef DRM_FORMAT_MOD_LINEAR
+# define DRM_FORMAT_MOD_LINEAR 0
+#endif
+#ifndef DRM_FORMAT_MOD_INVALID
+# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
+#endif
+
+#ifndef EGL_DMA_BUF_PLANE3_FD_EXT
+# define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
+#endif
+#ifndef EGL_DMA_BUF_PLANE3_OFFSET_EXT
+# define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
+#endif
+#ifndef EGL_DMA_BUF_PLANE3_PITCH_EXT
+# define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
+#endif
+#ifndef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
+# define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#endif
+#ifndef EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT
+# define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#endif
+#ifndef EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT
+# define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#endif
+#ifndef EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT
+# define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#endif
+#ifndef EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT
+# define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#endif
+#ifndef EGL_DMA_BUF_PLANE2_MODIFIER_HIa_EXT
+# define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#endif
+#ifndef EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT
+# define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#endif
+#ifndef EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT
+# define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+#endif
+
 /* local structures */
 typedef struct _Render_Engine Render_Engine;
 struct _Render_Engine
@@ -34,6 +77,9 @@ typedef int (*glsym_func_int) ();
 typedef EGLBoolean (*glsym_func_bool) ();
 typedef unsigned int (*glsym_func_uint) ();
 typedef const char *(*glsym_func_const_char_ptr) ();
+typedef void  (*secsym_func_void) ();
+typedef void *(*secsym_func_void_ptr) ();
+typedef int (*secsym_func_int) ();
 
 Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL;
 Evas_GL_Common_Image_Call glsym_evas_gl_common_image_unref = NULL;
@@ -93,6 +139,17 @@ Eina_Bool partial_render = EINA_TRUE;          //enable/disable partial render o
 unsigned int (*glsym_prev_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL;
 unsigned int (*glsym_prev_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d) = NULL;
 
+static Eina_Bool has_tizen_native_surface = EINA_TRUE;
+static Eina_Bool has_dma_buf_import = EINA_TRUE;
+
+static void *tbm_lib_handle;
+
+void *(*secsym_tbm_surface_internal_get_bo) (void *surface, int bo_idx) = NULL;
+int (*secsym_tbm_surface_internal_get_plane_bo_idx) (void *surface, int plane_idx) = NULL;
+int (*secsym_tbm_surface_internal_get_num_planes) (unsigned int format) = NULL;
+int (*secsym_tbm_bo_get_handle) (void *bo, int device) = NULL;
+int (*secsym_tbm_surface_get_info) (void *surface, void *info) = NULL;
+
 /* local functions */
 static inline Outbuf *
 eng_get_ob(Render_Engine *re)
@@ -191,11 +248,45 @@ eng_gl_symbols(EGLDisplay edsp)
    FINDSYM(glsym_eglCreateSyncKHR, "eglCreateSyncKHR", glsym_func_void_ptr);
    FINDSYM(glsym_eglDestroySyncKHR, "eglDestroySyncKHR", glsym_func_bool);
    FINDSYM(glsym_eglWaitSyncKHR, "eglWaitSyncKHR", glsym_func_int);
+#undef FINDSYM
 
    done = EINA_TRUE;
 }
 
 static void
+tbm_symbols(void)
+{
+   static Eina_Bool tbm_sym_done = EINA_FALSE;
+   if (tbm_sym_done) return;
+   tbm_sym_done = EINA_TRUE;
+
+#ifdef GL_GLES
+   tbm_lib_handle = dlopen("libtbm.so.1", RTLD_NOW);
+   if (!tbm_lib_handle)
+     {
+        DBG("Unable to open libtbm:  %s", dlerror());
+        return;
+     }
+
+#define FINDSYM(dst, sym, typ) \
+   if (!dst) dst = (typ)dlsym(tbm_lib_handle, sym); \
+   if (!dst)  \
+     { \
+        ERR("Symbol not found %s\n", sym); \
+        return; \
+     }
+
+   FINDSYM(secsym_tbm_surface_internal_get_bo, "tbm_surface_internal_get_bo", secsym_func_void_ptr);
+   FINDSYM(secsym_tbm_surface_internal_get_plane_bo_idx, "tbm_surface_internal_get_plane_bo_idx", secsym_func_int);
+   FINDSYM(secsym_tbm_surface_internal_get_num_planes, "tbm_surface_internal_get_num_planes", secsym_func_int);
+   FINDSYM(secsym_tbm_bo_get_handle, "tbm_bo_get_handle", secsym_func_int);
+   FINDSYM(secsym_tbm_surface_get_info, "tbm_surface_get_info", secsym_func_int);
+
+#undef FINDSYM
+#endif
+}
+
+static void
 gl_extn_veto(Render_Engine *re)
 {
    const char *str = NULL;
@@ -253,6 +344,11 @@ gl_extn_veto(Render_Engine *re)
         if (strstr(str, "EGL_TIZEN_image_native_surface"))
           {
              eng_get_ob(re)->gl_context->shared->info.egl_tbm_ext = 1;
+             has_tizen_native_surface = EINA_TRUE;
+          }
+        if (strstr(str, "EGL_EXT_image_dma_buf_import"))
+          {
+             has_dma_buf_import = EINA_TRUE;
           }
      }
    else
@@ -1793,12 +1889,66 @@ eng_image_native_set(void *engine, void *image, void *native)
                n->ns_data.tbm.buffer = buffer;
 
                if (glsym_evas_gl_common_eglDestroyImage)
-                 n->ns_data.tbm.surface =
-                   glsym_evas_gl_common_eglCreateImage(ob->egl_disp,
-                                                       EGL_NO_CONTEXT,
-                                                       EGL_NATIVE_SURFACE_TIZEN,
-                                                       (void *)buffer,
-                                                       NULL);
+                 {
+                    if (has_tizen_native_surface)
+                      {
+                         n->ns_data.tbm.surface = glsym_evas_gl_common_eglCreateImage(ob->egl_disp,
+                                                                                      EGL_NO_CONTEXT,
+                                                                                      EGL_NATIVE_SURFACE_TIZEN,
+                                                                                      (void *)buffer,
+                                                                                      NULL);
+                      }
+                    else if (has_dma_buf_import)
+                      {
+                         tbm_surface_info_s info = {0, };
+                         EGLint attribs[50];
+                         int atti = 0;
+                         tbm_bo tbo = NULL;
+                         int bo_idx, num_planes, i;
+                         int plane_fd_ext[4] = {EGL_DMA_BUF_PLANE0_FD_EXT,
+                                                EGL_DMA_BUF_PLANE1_FD_EXT,
+                                                EGL_DMA_BUF_PLANE2_FD_EXT,
+                                                EGL_DMA_BUF_PLANE3_FD_EXT};
+                         int plane_offset_ext[4] = {EGL_DMA_BUF_PLANE0_OFFSET_EXT,
+                                                    EGL_DMA_BUF_PLANE1_OFFSET_EXT,
+                                                    EGL_DMA_BUF_PLANE2_OFFSET_EXT,
+                                                    EGL_DMA_BUF_PLANE3_OFFSET_EXT};
+                         int plane_pitch_ext[4] = {EGL_DMA_BUF_PLANE0_PITCH_EXT,
+                                                   EGL_DMA_BUF_PLANE1_PITCH_EXT,
+                                                   EGL_DMA_BUF_PLANE2_PITCH_EXT,
+                                                   EGL_DMA_BUF_PLANE3_PITCH_EXT};
+
+                         secsym_tbm_surface_get_info(buffer, &info);
+
+                         attribs[atti++] = EGL_WIDTH;
+                         attribs[atti++] = info.width;
+                         attribs[atti++] = EGL_HEIGHT;
+                         attribs[atti++] = info.height;
+                         attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
+                         attribs[atti++] = info.format;
+
+                         num_planes = secsym_tbm_surface_internal_get_num_planes(info.format);
+                         for (i = 0; i < num_planes; i++)
+                           {
+                              bo_idx = secsym_tbm_surface_internal_get_plane_bo_idx(buffer, i);
+                              tbo = secsym_tbm_surface_internal_get_bo(buffer, bo_idx);
+                              attribs[atti++] = plane_fd_ext[i];
+                              attribs[atti++] = secsym_tbm_bo_get_handle(tbo, TBM_DEVICE_3D);
+                              attribs[atti++] = plane_offset_ext[i];
+                              attribs[atti++] = info.planes[i].offset;
+                              attribs[atti++] = plane_pitch_ext[i];
+                              attribs[atti++] = info.planes[i].stride;
+                           }
+
+                         attribs[atti++] = EGL_NONE;
+
+                         n->ns_data.tbm.surface = glsym_evas_gl_common_eglCreateImage(ob->egl_disp,
+                                                                                      EGL_NO_CONTEXT,
+                                                                                      EGL_LINUX_DMA_BUF_EXT,
+                                                                                      NULL,
+                                                                                      attribs);
+                      }
+                 }
                else
                  ERR("Try eglCreateImage on EGL with no support");
                if (!n->ns_data.tbm.surface)
@@ -1899,6 +2049,7 @@ module_open(Evas_Module *em)
    //
    evas_gl_thread_link_init();
    symbols();
+   tbm_symbols();
 
    /* advertise out which functions we support */
    em->functions = (void *)(&func);