[Mesa-dev] [PATCH v2 5/9] egl/tizen: add support of dri2_loader

Gwan-gyeong Mun elongbug at gmail.com
Sun Sep 17 18:01:03 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.

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 | 289 ++++++++++++++++++++++++++++++++--
 2 files changed, 289 insertions(+), 9 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 4b29b0d406..46d56e93a2 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       tbm_surface;
+      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 efdf79682b..77684d3c1a 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -47,6 +47,53 @@
 #include "egl_dri2_fallbacks.h"
 #include "loader.h"
 
+static int get_format_bpp(tbm_format format)
+{
+   int bpp;
+
+   switch (format) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+   case TBM_FORMAT_BGRA8888:
+   case TBM_FORMAT_RGBA8888:
+   case TBM_FORMAT_RGBX8888:
+   case TBM_FORMAT_ARGB8888:
+#pragma GCC diagnostic pop
+   case TBM_FORMAT_XRGB8888:
+      bpp = 4;
+      break;
+   case TBM_FORMAT_RGB565:
+      bpp = 2;
+      break;
+   default:
+      bpp = 0;
+      break;
+   }
+
+   return bpp;
+}
+
+static int get_pitch(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)
 {
@@ -63,6 +110,33 @@ tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
    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_local_buffers(dri2_surf);
+   }
+
+   /* Record all the buffers created by tpl_surface (tbm_surface_queue)
+    *   and update back buffer * for updating buffer's age in swap_buffers.
+    */
+   EGLBoolean updated = EGL_FALSE;
+   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+      if (!dri2_surf->color_buffers[i].tbm_surface) {
+         dri2_surf->color_buffers[i].tbm_surface = dri2_surf->tbm_surface;
+         dri2_surf->color_buffers[i].age = 0;
+      }
+      if (dri2_surf->color_buffers[i].tbm_surface == dri2_surf->tbm_surface) {
+         dri2_surf->back = &dri2_surf->color_buffers[i];
+         updated = EGL_TRUE;
+         break;
+      }
+   }
+
+   if (!updated) {
+      /* In case of all the buffers were recreated , reset the color_buffers */
+      for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+         dri2_surf->color_buffers[i].tbm_surface = NULL;
+         dri2_surf->color_buffers[i].age = 0;
+      }
+      dri2_surf->color_buffers[0].tbm_surface = dri2_surf->tbm_surface;
+      dri2_surf->back = &dri2_surf->color_buffers[0];
    }
 
    return EGL_TRUE;
@@ -100,6 +174,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);
 
@@ -200,7 +275,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);
@@ -243,6 +321,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) {
       if (dri2_surf->tbm_surface)
          tizen_window_cancel_buffer(disp, dri2_surf);
@@ -272,6 +352,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 ? dri2_surf->back->age : 0;
+}
+
 static EGLBoolean
 tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
                                _EGLSurface *draw, const EGLint *rects,
@@ -283,10 +376,23 @@ tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
    if (dri2_surf->base.Type != EGL_WINDOW_BIT)
       return EGL_TRUE;
 
+   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+      if (dri2_surf->color_buffers[i].age > 0)
+         dri2_surf->color_buffers[i].age++;
+   }
+
+   if (dri2_surf->back)
+      dri2_surf->back->age = 1;
+
    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;
 }
@@ -329,6 +435,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_pitch(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)
 {
@@ -523,13 +710,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 },
 
@@ -539,6 +734,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,
    NULL,
@@ -551,6 +753,8 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
    tpl_display_t *tpl_display = NULL;
    const char *err;
    int tbm_bufmgr_fd = -1;
+   char *tbm_bufmgr_device_name = NULL;
+   int hw_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
 
    loader_set_logger(_eglLog);
 
@@ -579,13 +783,77 @@ 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) {
+
+         tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
+         if (tbm_bufmgr_device_name == NULL) {
+            err = "DRI2: failed to get tbm_bufmgr device name";
+            goto cleanup;
+         }
+         fd = loader_open_device(tbm_bufmgr_device_name);
+
+      } else {
+         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
+            tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
+            if (tbm_bufmgr_device_name == NULL) {
+               err = "DRI2: failed to get tbm_bufmgr device name";
+               goto cleanup;
+            }
+            fd = loader_open_device(tbm_bufmgr_device_name);
+#else
+            err = "DRI2: failed to get fd from tbm_drm_helper_get_auth_info()";
+            goto cleanup;
+#endif
+         }
+      }
+
+      if (fd == -1) {
+         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 = tbm_bufmgr_fd;
+      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";
@@ -609,6 +877,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.1



More information about the mesa-dev mailing list