[Mesa-dev] [PATCH v3 08/22] egl/tizen: add support of dri2_loader (v2)

Gwan-gyeong Mun elongbug at gmail.com
Wed Oct 4 06:50:20 UTC 2017


It adds support of dri2_loader to egl dri2 tizen backend.
  - referenced a basic buffer flow and management implementation from android.

And it implements a query buffer age extesion for tizen and turn on
swap_buffers_with_damage extension.
  - it add color buffer related member variables to dri_egl_surface for a
    management of color buffers.

v2: Fixes from Emil's review:
   a) Remove a temporary variable and return directly on get_format_bpp()
   b) Remove unneeded compiler pragma
   c) Follow coding style
   d) Rename get_pitch() to get_stride() for using of consistent naming
   e) Remove mis-referencing from android implementation on treatment of buffer
      age.
      reference: https://lists.freedesktop.org/archives/mesa-dev/2017-June/158409.html
   f) Use dri2_egl_surface_free_outdated_buffers_and_update_size() helper
   g) Use dri2_egl_surface_record_buffers_and_update_back_buffer() helper
   h) Use add dri2_egl_surface_update_buffer_age() helper
   i) Use env_var_as_boolean for hw_accel variable on dri2_initialize_tizen()
   j) Remove getting of the device name and opening of the device node on dri2_initialize_tizen()
      And add duplicating of tbm_bufmgr_fd. As tbm_bufmgr_fd is managed by tbm_bufmgr,
      if mesa use this fd then we should duplicate it.
   k) Add comments why we can not drop the dri2 codepath on dri2_initialize_tizen()
      As some kernels ported for tizen don't support render node feature yet,
      currently we cannot drop the dri2 codepath.

Signed-off-by: Mun Gwan-gyeong <elongbug at gmail.com>
---
 src/egl/drivers/dri2/egl_dri2.h       |   9 ++
 src/egl/drivers/dri2/platform_tizen.c | 257 ++++++++++++++++++++++++++++++++--
 2 files changed, 252 insertions(+), 14 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 6f9d936ca5..7d047bf5dd 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -340,6 +340,15 @@ struct dri2_egl_surface
    tpl_surface_t         *tpl_surface;
    tbm_surface_h          tbm_surface;
    tbm_format             tbm_format;
+
+   /* Used to record all the tbm_surface created by tpl_surface and their ages.
+    * Usually Tizen uses at most triple buffers in tpl_surface (tbm_surface_queue)
+    * so hardcode the number of color_buffers to 3.
+    */
+   struct {
+      tbm_surface_h       buffer;
+      int                 age;
+   } color_buffers[3], *back;
 #endif
 
 #if defined(HAVE_SURFACELESS_PLATFORM)
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 7cee03f784..72cef25364 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -46,6 +46,43 @@
 #include "egl_dri2.h"
 #include "egl_dri2_fallbacks.h"
 #include "loader.h"
+#include "util/debug.h"
+
+static int get_format_bpp(tbm_format format)
+{
+   switch (format) {
+   case TBM_FORMAT_BGRA8888:
+   case TBM_FORMAT_RGBA8888:
+   case TBM_FORMAT_RGBX8888:
+   case TBM_FORMAT_ARGB8888:
+   case TBM_FORMAT_XRGB8888:
+      return 4;
+   case TBM_FORMAT_RGB565:
+      return 2;
+   default:
+      return 0;
+   }
+}
+
+static int get_stride(tbm_surface_h tbm_surface)
+{
+   tbm_surface_info_s surf_info;
+
+   if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE)
+      return 0;
+
+   return surf_info.planes[0].stride;
+}
+
+static int
+get_native_buffer_name(tbm_surface_h tbm_surface)
+{
+   uint32_t bo_name;
+
+   bo_name = tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0));
+
+   return (bo_name != 0 ) ? (int)bo_name : -1;
+}
 
 static EGLBoolean
 tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
@@ -60,10 +97,14 @@ tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
    tbm_surface_internal_ref(dri2_surf->tbm_surface);
 
    tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height);
-   if (dri2_surf->base.Width != width || dri2_surf->base.Height != height) {
-      dri2_surf->base.Width = width;
-      dri2_surf->base.Height = height;
-   }
+
+   dri2_egl_surface_free_outdated_buffers_and_update_size(dri2_surf, width, height);
+
+   /* Record all the buffers created by tpl_surface (tbm_surface_queue)
+    * and update back buffer for updating buffer's age in swap_buffers.
+    */
+   dri2_egl_surface_record_buffers_and_update_back_buffer(dri2_surf,
+                                                          (void*)dri2_surf->tbm_surface);
 
    return EGL_TRUE;
 }
@@ -101,6 +142,7 @@ tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp,
 
    tbm_surface_internal_unref(dri2_surf->tbm_surface);
    dri2_surf->tbm_surface = NULL;
+   dri2_surf->back = NULL;
 
    mtx_lock(&disp->Mutex);
 
@@ -208,7 +250,10 @@ tizen_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    if (!dri2_surf->tpl_surface)
       goto cleanup_surface;
 
-   createNewDrawable = dri2_dpy->swrast->createNewDrawable;
+   if (dri2_dpy->dri2)
+      createNewDrawable = dri2_dpy->dri2->createNewDrawable;
+   else
+      createNewDrawable = dri2_dpy->swrast->createNewDrawable;
 
    dri2_surf->dri_drawable = (*createNewDrawable)(dri2_dpy->dri_screen, config,
                                                   dri2_surf);
@@ -251,6 +296,8 @@ tizen_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
 
+   dri2_egl_surface_free_local_buffers(dri2_surf);
+
    if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->tbm_surface)
       tizen_window_cancel_buffer(disp, dri2_surf);
 
@@ -278,6 +325,19 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
    return 0;
 }
 
+static EGLint
+tizen_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface)
+{
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
+
+   if (update_buffers(dri2_surf) < 0) {
+      _eglError(EGL_BAD_ALLOC, "tizen_query_buffer_age");
+      return -1;
+   }
+
+   return dri2_surf->back->age;
+}
+
 static EGLBoolean
 tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
                                _EGLSurface *draw, const EGLint *rects,
@@ -289,10 +349,17 @@ tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
    if (dri2_surf->base.Type != EGL_WINDOW_BIT)
       return EGL_TRUE;
 
+   dri2_egl_surface_update_buffer_age(dri2_surf);
+
    if (dri2_surf->tbm_surface)
       tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, rects, n_rects);
 
-   dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
+   if (dri2_dpy->swrast) {
+      dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
+   } else {
+      dri2_flush_drawable_for_swapbuffers(disp, draw);
+      dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
+   }
 
    return EGL_TRUE;
 }
@@ -333,6 +400,87 @@ tizen_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
    return _eglQuerySurface(drv, dpy, surf, attribute, value);
 }
 
+static void
+tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+}
+
+static int
+tizen_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
+                                    unsigned int *attachments, int count)
+{
+   int num_buffers = 0;
+
+   /* fill dri2_surf->buffers */
+   for (int i = 0; i < count * 2; i += 2) {
+      __DRIbuffer *buf, *local;
+
+      assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
+      buf = &dri2_surf->buffers[num_buffers];
+
+      switch (attachments[i]) {
+      case __DRI_BUFFER_BACK_LEFT:
+         if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+            buf->attachment = attachments[i];
+            buf->name = get_native_buffer_name(dri2_surf->tbm_surface);
+            buf->cpp = get_format_bpp(tbm_surface_get_format(dri2_surf->tbm_surface));
+            buf->pitch = get_stride(dri2_surf->tbm_surface);
+            buf->flags = 0;
+
+            if (buf->name)
+               num_buffers++;
+
+            break;
+         }
+         /* fall through for pbuffers */
+      case __DRI_BUFFER_DEPTH:
+      case __DRI_BUFFER_STENCIL:
+      case __DRI_BUFFER_ACCUM:
+      case __DRI_BUFFER_DEPTH_STENCIL:
+      case __DRI_BUFFER_HIZ:
+         local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i],
+                                                     attachments[i + 1]);
+
+         if (local) {
+            *buf = *local;
+            num_buffers++;
+         }
+         break;
+      case __DRI_BUFFER_FRONT_LEFT:
+      case __DRI_BUFFER_FRONT_RIGHT:
+      case __DRI_BUFFER_FAKE_FRONT_LEFT:
+      case __DRI_BUFFER_FAKE_FRONT_RIGHT:
+      case __DRI_BUFFER_BACK_RIGHT:
+      default:
+         /* no front or right buffers */
+         break;
+      }
+   }
+
+   return num_buffers;
+}
+
+static __DRIbuffer *
+tizen_get_buffers_with_format(__DRIdrawable * driDrawable,
+                              int *width, int *height,
+                              unsigned int *attachments, int count,
+                              int *out_count, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+   if (update_buffers(dri2_surf) < 0)
+      return NULL;
+
+   *out_count = tizen_get_buffers_parse_attachments(dri2_surf, attachments, count);
+
+   if (width)
+      *width = dri2_surf->base.Width;
+   if (height)
+      *height = dri2_surf->base.Height;
+
+   return dri2_surf->buffers;
+}
+
 static int
 tizen_swrast_get_stride_for_format(tbm_format format, int w)
 {
@@ -550,13 +698,21 @@ static const struct dri2_egl_display_vtbl tizen_display_vtbl = {
    .swap_buffers_region = dri2_fallback_swap_buffers_region,
    .post_sub_buffer = dri2_fallback_post_sub_buffer,
    .copy_buffers = dri2_fallback_copy_buffers,
-   .query_buffer_age = dri2_fallback_query_buffer_age,
+   .query_buffer_age = tizen_query_buffer_age,
    .query_surface = tizen_query_surface,
    .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
    .get_sync_values = dri2_fallback_get_sync_values,
    .get_dri_drawable = dri2_surface_get_dri_drawable,
 };
 
+static const __DRIdri2LoaderExtension tizen_dri2_loader_extension = {
+   .base = { __DRI_DRI2_LOADER, 3 },
+
+   .getBuffers           = NULL,
+   .getBuffersWithFormat = tizen_get_buffers_with_format,
+   .flushFrontBuffer     = tizen_flush_front_buffer,
+};
+
 static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = {
    .base = { __DRI_SWRAST_LOADER, 2 },
 
@@ -566,6 +722,13 @@ static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = {
    .putImage2       = tizen_swrast_put_image2,
 };
 
+static const __DRIextension *tizen_dri2_loader_extensions[] = {
+   &tizen_dri2_loader_extension.base,
+   &image_lookup_extension.base,
+   &use_invalidate.base,
+   NULL,
+};
+
 static const __DRIextension *tizen_swrast_loader_extensions[] = {
    &tizen_swrast_loader_extension.base,
    &image_lookup_extension.base,
@@ -579,6 +742,7 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
    tpl_display_t *tpl_display = NULL;
    const char *err;
    int tbm_bufmgr_fd = -1;
+   bool hw_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
 
    loader_set_logger(_eglLog);
 
@@ -599,7 +763,11 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
    }
    dri2_dpy->tpl_display = tpl_display;
 
-   /* Get tbm_bufmgr's fd */
+   /* Get tbm_bufmgr's fd
+    * As tbm_bufmgr_fd is managed by tbm_bufmgr, if mesa use this fd then we
+    * should duplicate it.
+    * (When dri2_display_destroy() is called, it close dri2_dpy->fd)
+    */
    tbm_bufmgr_fd = tbm_drm_helper_get_fd();
 
    if (tbm_bufmgr_fd == -1) {
@@ -607,13 +775,71 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
       goto cleanup;
    }
 
-   dri2_dpy->fd = tbm_bufmgr_fd;
-   dri2_dpy->driver_name = strdup("swrast");
-   if (!dri2_load_driver_swrast(dpy)) {
-      err = "DRI2: failed to load swrast driver";
-      goto cleanup;
+   if (hw_accel) {
+      int fd = -1;
+
+      if (drmGetNodeTypeFromFd(tbm_bufmgr_fd) == DRM_NODE_RENDER)
+         fd = dup(tbm_bufmgr_fd);
+      else {
+         /* As some kernels ported for tizen don't support render node feature
+          * yet, currently we cannot drop the dri2 codepath.
+          */
+         if (!tbm_drm_helper_get_auth_info(&fd, NULL, NULL)) {
+            /* FIXME: tbm_drm_helper_get_auth_info() does not support the case of
+             *        display server for now. this code is fallback routine for
+             *        that Enlightenment Server fails on tbm_drm_helper_get_auth_info.
+             *        When tbm_drm_helper_get_auth_info() supports display server
+             *        case, then remove below routine.
+             */
+#if 1
+            fd = dup(tbm_bufmgr_fd);
+#else
+            err = "DRI2: failed to get fd from tbm_drm_helper_get_auth_info()";
+            goto cleanup;
+#endif
+         }
+      }
+
+      if (fd < 0) {
+         err = "DRI2: failed to get fd";
+         goto cleanup;
+      }
+      dri2_dpy->fd = fd;
+
+      dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
+      if (dri2_dpy->driver_name == NULL) {
+         err = "DRI2: failed to get driver name";
+         goto cleanup;
+      }
+
+      dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
+      /* render nodes cannot use Gem names, and thus do not support
+       * the __DRI_DRI2_LOADER extension */
+
+      if (!dri2_dpy->is_render_node) {
+         dri2_dpy->loader_extensions = tizen_dri2_loader_extensions;
+         if (!dri2_load_driver(dpy)) {
+            err = "DRI2: failed to load driver";
+            goto cleanup;
+         }
+      } else {
+         err = "DRI2: render node is not suppported";
+         goto cleanup;
+      }
+
+   } else {
+      dri2_dpy->fd = dup(tbm_bufmgr_fd);
+      if (dri2_dpy->fd < 0) {
+         err = "DRI2: failed to dup fd";
+         goto cleanup;
+      }
+      dri2_dpy->driver_name = strdup("swrast");
+      if (!dri2_load_driver_swrast(dpy)) {
+         err = "DRI2: failed to load swrast driver";
+         goto cleanup;
+      }
+      dri2_dpy->loader_extensions = tizen_swrast_loader_extensions;
    }
-   dri2_dpy->loader_extensions = tizen_swrast_loader_extensions;
 
    if (!dri2_create_screen(dpy)) {
       err = "DRI2: failed to create screen";
@@ -637,6 +863,9 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
     */
    dri2_dpy->vtbl = &tizen_display_vtbl;
 
+   dpy->Extensions.EXT_buffer_age = EGL_TRUE;
+   dpy->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
+
    return EGL_TRUE;
 
 cleanup:
-- 
2.14.2



More information about the mesa-dev mailing list