[Mesa-dev] [PATCH 2/3] egl: Allow creation of per surface out fence

Emil Velikov emil.l.velikov at gmail.com
Fri Sep 15 17:32:42 UTC 2017


From: Zhongmin Wu <zhongmin.wu at intel.com>

Add plumbing to allow creation of per display surface out fence.

This can be used to implement explicit sync. One user of which is
Android - which will be addressed with next commit.

Signed-off-by: Zhongmin Wu <zhongmin.wu at intel.com>
Signed-off-by: Yogesh Marathe <yogesh.marathe at intel.com>
Reviewed-by: Emil Velikov <emil.velikov at collabora.com>
Reviewed-by: Tomasz Figa <tfiga at chromium.org>
[Emil Velikov: reorder so there's no intermetent regressions, split]
Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
---
 src/egl/drivers/dri2/egl_dri2.c             | 72 +++++++++++++++++++++++++++++
 src/egl/drivers/dri2/egl_dri2.h             |  9 ++++
 src/egl/drivers/dri2/platform_android.c     |  3 +-
 src/egl/drivers/dri2/platform_drm.c         |  3 +-
 src/egl/drivers/dri2/platform_surfaceless.c |  3 +-
 src/egl/drivers/dri2/platform_wayland.c     |  3 +-
 src/egl/drivers/dri2/platform_x11.c         |  3 +-
 src/egl/drivers/dri2/platform_x11_dri3.c    |  3 +-
 8 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 2667aa5d647..42bca61cfda 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1388,6 +1388,45 @@ dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
    return EGL_TRUE;
 }
 
+EGLBoolean
+dri2_init_surface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
+        _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean enable_out_fence)
+{
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+
+   dri2_surf->out_fence_fd = -1;
+   dri2_surf->enable_out_fence = false;
+   if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 &&
+       dri2_dpy->fence->get_capabilities &&
+       (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) &
+        __DRI_FENCE_CAP_NATIVE_FD)) {
+      dri2_surf->enable_out_fence = enable_out_fence;
+   }
+
+   return _eglInitSurface(surf, dpy, type, conf, attrib_list);
+}
+
+static void
+dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd)
+{
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+   if (dri2_surf->out_fence_fd >= 0)
+      close(dri2_surf->out_fence_fd);
+
+   dri2_surf->out_fence_fd = fence_fd;
+}
+
+void
+dri2_fini_surface(_EGLSurface *surf)
+{
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+   dri2_surface_set_out_fence_fd(surf, -1);
+   dri2_surf->enable_out_fence = false;
+}
+
 static EGLBoolean
 dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
 {
@@ -1399,6 +1438,28 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
    return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
 }
 
+static void
+dri2_surf_update_fence_fd(_EGLContext *ctx,
+                          _EGLDisplay *dpy, _EGLSurface *surf)
+{
+   __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+   int fence_fd = -1;
+   void *fence;
+
+   if (!dri2_surf->enable_out_fence)
+      return;
+
+   fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1);
+   if (fence) {
+      fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
+                                               fence);
+      dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence);
+   }
+   dri2_surface_set_out_fence_fd(surf, fence_fd);
+}
+
 /**
  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  */
@@ -1435,6 +1496,9 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
 
    if (old_ctx) {
       __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
+
+      if (old_dsurf)
+         dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
       dri2_dpy->core->unbindContext(old_cctx);
    }
 
@@ -1573,6 +1637,10 @@ static EGLBoolean
 dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+   _EGLContext *ctx = _eglGetCurrentContext();
+
+   if (ctx && surf)
+      dri2_surf_update_fence_fd(ctx, dpy, surf);
    return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
 }
 
@@ -1582,6 +1650,10 @@ dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
                               const EGLint *rects, EGLint n_rects)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+   _EGLContext *ctx = _eglGetCurrentContext();
+
+   if (ctx && surf)
+      dri2_surf_update_fence_fd(ctx, dpy, surf);
    return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
                                                    rects, n_rects);
 }
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 4a52b490a87..10a41518172 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -327,6 +327,8 @@ struct dri2_egl_surface
       __DRIimage           *front;
       unsigned int         visual;
 #endif
+   int out_fence_fd;
+   EGLBoolean enable_out_fence;
 };
 
 struct dri2_egl_config
@@ -462,4 +464,11 @@ dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
 void
 dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf);
 
+EGLBoolean
+dri2_init_surface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
+        _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean enable_out_fence);
+
+void
+dri2_fini_surface(_EGLSurface *surf);
+
 #endif /* EGL_DRI2_INCLUDED */
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index a864a2af3d7..38c1122339f 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -289,7 +289,7 @@ droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surface;
 
    if (type == EGL_WINDOW_BIT) {
@@ -389,6 +389,7 @@ droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 
    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 
+   dri2_fini_surface(surf);
    free(dri2_surf);
 
    return EGL_TRUE;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 0ccbd9a30a0..fbdf8b1672a 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -110,7 +110,7 @@ dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
+   if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list, false))
       goto cleanup_surf;
 
    surf = gbm_dri_surface(surface);
@@ -178,6 +178,7 @@ dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 
    dri2_egl_surface_free_local_buffers(dri2_surf);
 
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c
index 1091b4febdb..ff8f88d5375 100644
--- a/src/egl/drivers/dri2/platform_surfaceless.c
+++ b/src/egl/drivers/dri2/platform_surfaceless.c
@@ -124,7 +124,7 @@ dri2_surfaceless_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surface;
 
    config = dri2_get_dri_config(dri2_conf, type,
@@ -165,6 +165,7 @@ surfaceless_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *sur
 
    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 
+   dri2_fini_surface(surf);
    free(dri2_surf);
    return EGL_TRUE;
 }
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index eb10a7dd137..dc6fcc1d072 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -143,7 +143,7 @@ dri2_wl_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
+   if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list, false))
       goto cleanup_surf;
 
    if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) {
@@ -296,6 +296,7 @@ dri2_wl_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
       wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
    wl_event_queue_destroy(dri2_surf->wl_queue);
 
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index d80eee2969a..ab9a142f415 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -233,7 +233,7 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       return NULL;
    }
    
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surf;
 
    dri2_surf->region = XCB_NONE;
@@ -395,6 +395,7 @@ dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    if (surf->Type == EGL_PBUFFER_BIT)
       xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
 
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index a83e7839528..45bb56ca17e 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -101,6 +101,7 @@ dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 
    loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
 
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
@@ -137,7 +138,7 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri3_surf->surf.base, disp, type, conf, attrib_list))
+   if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf, attrib_list, false))
       goto cleanup_surf;
 
    if (type == EGL_PBUFFER_BIT) {
-- 
2.14.1



More information about the mesa-dev mailing list