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

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


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

It adds dri_image_back/dri_image_back member variables to dri_egl_surface for
a management of back/front buffers.

v2:
 - Fixes from Emil's review:
   a) Use dri2_egl_surface_destroy_image_back() helper
   b) Use dri2_egl_surface_destroy_image_front() helper
   c) Use dri2_egl_surface_get_image_front() helper

 - Use get_stride helper on get_back_bo()

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

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index d24425dba1..d9215ea06e 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -340,6 +340,8 @@ struct dri2_egl_surface
    tpl_surface_t         *tpl_surface;
    tbm_surface_h          tbm_surface;
    tbm_format             tbm_format;
+   __DRIimage            *dri_image_back;
+   __DRIimage            *dri_image_front;
 
    /* 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)
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 091ae4dcef..87c7e1e6a2 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -225,6 +225,8 @@ tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp,
 
    mtx_lock(&disp->Mutex);
 
+   dri2_egl_surface_destroy_image_back(dri2_surf);
+
    return EGL_TRUE;
 
 cleanup:
@@ -329,7 +331,9 @@ tizen_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    if (!dri2_surf->tpl_surface)
       goto cleanup_surface;
 
-   if (dri2_dpy->dri2)
+   if (dri2_dpy->image_driver)
+      createNewDrawable = dri2_dpy->image_driver->createNewDrawable;
+   else if (dri2_dpy->dri2)
       createNewDrawable = dri2_dpy->dri2->createNewDrawable;
    else
       createNewDrawable = dri2_dpy->swrast->createNewDrawable;
@@ -380,6 +384,9 @@ tizen_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->tbm_surface)
       tizen_window_cancel_buffer(disp, dri2_surf);
 
+   dri2_egl_surface_destroy_image_back(dri2_surf);
+   dri2_egl_surface_destroy_image_front(dri2_surf);
+
    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 
    tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
@@ -404,6 +411,119 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
    return 0;
 }
 
+static int
+get_back_bo(struct dri2_egl_surface *dri2_surf)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   int fourcc, pitch;
+   int offset = 0, fd;
+   tbm_surface_info_s surf_info;
+
+   if (dri2_surf->dri_image_back)
+      return 0;
+
+   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+      if (!dri2_surf->tbm_surface) {
+         _eglLog(_EGL_WARNING, "Could not get native buffer");
+         return -1;
+      }
+
+      fd = get_native_buffer_fd(dri2_surf->tbm_surface);
+      if (fd < 0) {
+         _eglLog(_EGL_WARNING, "Could not get native buffer FD");
+         return -1;
+      }
+
+      pitch = get_stride(dri2_surf->tbm_surface);
+      fourcc = get_fourcc(dri2_surf->tbm_format);
+
+      if (fourcc == -1 || pitch == 0) {
+         _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
+                 fourcc, pitch);
+         return -1;
+      }
+
+      dri2_surf->base.Width = surf_info.width;
+      dri2_surf->base.Height = surf_info.height;
+
+      dri2_surf->dri_image_back =
+         dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+                                             dri2_surf->base.Width,
+                                             dri2_surf->base.Height,
+                                             fourcc,
+                                             &fd,
+                                             1,
+                                             &pitch,
+                                             &offset,
+                                             dri2_surf);
+
+      if (!dri2_surf->dri_image_back) {
+         _eglLog(_EGL_WARNING, "failed to create DRI image from FD");
+         return -1;
+      }
+   } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
+      /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
+       * the spec states that they have a back buffer but no front buffer, in
+       * contrast to pixmaps, which have a front buffer but no back buffer.
+       *
+       * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
+       * from the spec, following the precedent of Mesa's EGL X11 platform. The
+       * X11 platform correctly assigns pbuffers to single-buffered configs, but
+       * assigns the pbuffer a front buffer instead of a back buffer.
+       *
+       * Pbuffers in the X11 platform mostly work today, so let's just copy its
+       * behavior instead of trying to fix (and hence potentially breaking) the
+       * world.
+       */
+      _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
+   }
+
+   return 0;
+}
+
+/* Some drivers will pass multiple bits in buffer_mask.
+ * For such case, will go through all the bits, and
+ * will not return error when unsupported buffer is requested, only
+ * return error when the allocation for supported buffer failed.
+ */
+static int
+tizen_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
+                        uint32_t *stamp, void *loaderPrivate,
+                        uint32_t buffer_mask, struct __DRIimageList *images)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+   images->image_mask = 0;
+   images->front = NULL;
+   images->back = NULL;
+
+   if (update_buffers(dri2_surf) < 0)
+      return 0;
+
+   if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
+      if (dri2_egl_surface_get_image_front(dri2_surf, format) < 0)
+         return 0;
+
+      if (dri2_surf->dri_image_front) {
+         images->front = dri2_surf->dri_image_front;
+         images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
+      }
+   }
+
+   if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
+      if (get_back_bo(dri2_surf) < 0)
+         return 0;
+
+      if (dri2_surf->dri_image_back) {
+         images->back = dri2_surf->dri_image_back;
+         images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
+      }
+   }
+
+   return 1;
+}
+
 static EGLint
 tizen_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface)
 {
@@ -1042,6 +1162,13 @@ static const __DRIdri2LoaderExtension tizen_dri2_loader_extension = {
    .flushFrontBuffer     = tizen_flush_front_buffer,
 };
 
+static const __DRIimageLoaderExtension tizen_image_loader_extension = {
+   .base = { __DRI_IMAGE_LOADER, 1 },
+
+   .getBuffers          = tizen_image_get_buffers,
+   .flushFrontBuffer    = tizen_flush_front_buffer,
+};
+
 static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = {
    .base = { __DRI_SWRAST_LOADER, 2 },
 
@@ -1058,6 +1185,13 @@ static const __DRIextension *tizen_dri2_loader_extensions[] = {
    NULL,
 };
 
+static const __DRIextension *tizen_image_loader_extensions[] = {
+   &tizen_image_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,
@@ -1224,8 +1358,11 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy)
             goto cleanup;
          }
       } else {
-         err = "DRI2: render node is not suppported";
-         goto cleanup;
+         dri2_dpy->loader_extensions = tizen_image_loader_extensions;
+         if (!dri2_load_driver_dri3(dpy)) {
+            err = "DRI3: failed to load driver";
+            goto cleanup;
+         }
       }
 
    } else {
-- 
2.14.2



More information about the mesa-dev mailing list