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

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

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 | 201 +++++++++++++++++++++++++++++++++-
 2 files changed, 200 insertions(+), 3 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 46d56e93a2..8b85704065 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 1efcb0e4fa..1840bade50 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -213,6 +213,7 @@ tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp,
                                         EGLint n_rects)
 {
    tpl_result_t ret;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
 
    /* To avoid blocking other EGL calls, release the display mutex before
     * we enter tizen_window_enqueue_buffer() and re-acquire the mutex upon
@@ -242,6 +243,11 @@ tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp,
 
    mtx_lock(&disp->Mutex);
 
+   if (dri2_surf->dri_image_back) {
+      dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
+      dri2_surf->dri_image_back = NULL;
+   }
+
    return EGL_TRUE;
 }
 
@@ -339,7 +345,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;
@@ -392,6 +400,18 @@ tizen_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
          tizen_window_cancel_buffer(disp, dri2_surf);
    }
 
+   if (dri2_surf->dri_image_back) {
+      _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
+      dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
+      dri2_surf->dri_image_back = NULL;
+   }
+
+   if (dri2_surf->dri_image_front) {
+      _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
+      dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
+      dri2_surf->dri_image_front = NULL;
+   }
+
    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 
    tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
@@ -416,6 +436,157 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
    return 0;
 }
 
+static int
+get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   if (dri2_surf->dri_image_front)
+      return 0;
+
+   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+      /* According current EGL spec, front buffer rendering
+       * for window surface is not supported now.
+       * and mesa doesn't have the implementation of this case.
+       * Add warning message, but not treat it as error.
+       */
+      _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
+   } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
+      dri2_surf->dri_image_front =
+         dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+                                      dri2_surf->base.Width,
+                                      dri2_surf->base.Height,
+                                      format,
+                                      0,
+                                      dri2_surf);
+      if (!dri2_surf->dri_image_front) {
+         _eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
+         return -1;
+      }
+   }
+
+   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;
+      }
+
+      if (tbm_surface_get_info(dri2_surf->tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
+         _eglLog(_EGL_WARNING, "Could not get pitch");
+         return -1;
+      }
+
+      pitch = surf_info.planes[0].stride;
+      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 (get_front_bo(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)
 {
@@ -445,6 +616,13 @@ tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
          dri2_surf->color_buffers[i].age++;
    }
 
+   /* Make sure we have a back buffer in case we're swapping without
+    * ever rendering. */
+   if (get_back_bo(dri2_surf) < 0) {
+      _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
+      return EGL_FALSE;
+   }
+
    if (dri2_surf->back)
       dri2_surf->back->age = 1;
 
@@ -1049,6 +1227,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 },
 
@@ -1065,6 +1250,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,
    NULL,
@@ -1248,8 +1440,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.1



More information about the mesa-dev mailing list