From: Zhongmin Wu <zhongmin...@intel.com>

Before we queued the buffer with a invalid fence (-1), it causes
benchmarks such as flatland to fail. This patch enables explicit
sync feature on android.

Now we get the out fence during the flushing buffer and then pass
it to SurfaceFlinger in eglSwapbuffer function.

v2: a) Also implement the fence in cancelBuffer.
    b) The last sync fence is stored in drawable object
       rather than brw context.
    c) format clear.

v3: a) Save the last fence fd in DRI Context object.
    b) Return the last fence if the batch buffer is empty and
       nothing to be flushed when _intel_batchbuffer_flush_fence
    c) Add the new interface in vbtl to set the retrieve fence

v3.1 a) close fd in the new vbtl interface on none Android platform

v4: a) The last fence is saved in brw context.
    b) The retrieve fd is for all the platform but not just Android
    c) Add a uniform dri2 interface to initialize the surface.

v4.1: a) make some changes of variable name.
      b) the patch is broken into two patches.

v4.2: a) Add a deinit interface for surface to clear the out fence

v5: a) Add enable_out_fence to init, platform sets it true or
       false
    b) Change get fd to update fd and check for fence
    c) Commit description updated

Signed-off-by: Zhongmin Wu <zhongmin...@intel.com>
Signed-off-by: Yogesh Marathe <yogesh.mara...@intel.com>
---
 src/egl/drivers/dri2/egl_dri2.c             | 57 +++++++++++++++++++++++++++++
 src/egl/drivers/dri2/egl_dri2.h             |  9 +++++
 src/egl/drivers/dri2/platform_android.c     | 12 ++++--
 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, 84 insertions(+), 9 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index a197e04..f4c521d 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1315,6 +1315,34 @@ dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLContext *ctx)
    return EGL_TRUE;
 }
 
+EGLBoolean
+dri2_surf_init(_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);
+   dri2_surf->out_fence_fd = -1;
+   dri2_surf->enable_out_fence = enable_out_fence;
+   return _eglInitSurface(surf, dpy, type, conf, attrib_list);
+}
+
+static void
+dri2_surface_set_out_fence( _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_surf_deinit(_EGLSurface *surf)
+{
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+   dri2_surface_set_out_fence(surf, -1);
+   dri2_surf->enable_out_fence = false;
+}
+
 static EGLBoolean
 dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
 {
@@ -1326,6 +1354,26 @@ 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)
+{
+   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;
+   __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context;
+   if (dri2_surf->enable_out_fence && dri2_dpy->fence) {
+      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(surf, fence_fd);
+}
+
 /**
  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  */
@@ -1360,8 +1408,11 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *dsurf,
    rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL;
    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
 
+   int fence_fd = -1;
    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);
    }
 
@@ -1498,6 +1549,9 @@ 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);
 }
 
@@ -1507,6 +1561,9 @@ 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 ccfefef..1a3e9f8 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -326,6 +326,8 @@ struct dri2_egl_surface
       __DRIimage           *front;
       unsigned int         visual;
 #endif
+   int out_fence_fd;
+   bool enable_out_fence;
 };
 
 struct dri2_egl_config
@@ -451,4 +453,11 @@ dri2_set_WL_bind_wayland_display(_EGLDriver *drv, 
_EGLDisplay *disp)
 void
 dri2_display_destroy(_EGLDisplay *disp);
 
+EGLBoolean
+dri2_surf_init(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
+        _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean 
enable_out_fence);
+
+void
+dri2_surf_deinit(_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 300e2d9..a3ac7a2 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -241,7 +241,8 @@ droid_window_enqueue_buffer(_EGLDisplay *disp, struct 
dri2_egl_surface *dri2_sur
     *    is passed to queueBuffer, and the ANativeWindow implementation
     *    is responsible for closing it.
     */
-   int fence_fd = -1;
+   int fence_fd = dri2_surf->out_fence_fd;
+   dri2_surf->out_fence_fd = -1;
    dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
                                   fence_fd);
 
@@ -263,8 +264,10 @@ static void
 droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
 {
    int ret;
-
-   ret = dri2_surf->window->cancelBuffer(dri2_surf->window, dri2_surf->buffer, 
-1);
+   int fence_fd = dri2_surf->out_fence_fd;
+   dri2_surf->out_fence_fd = -1;
+   ret = dri2_surf->window->cancelBuffer(dri2_surf->window,
+                                         dri2_surf->buffer, fence_fd);
    if (ret < 0) {
       _eglLog(_EGL_WARNING, "ANativeWindow::cancelBuffer failed");
       dri2_surf->base.Lost = EGL_TRUE;
@@ -323,7 +326,7 @@ droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, 
EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_surf_init(&dri2_surf->base, disp, type, conf, attrib_list, true))
       goto cleanup_surface;
 
    if (type == EGL_WINDOW_BIT) {
@@ -423,6 +426,7 @@ droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *surf)
 
    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
 
+   dri2_surf_deinit(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 d59009f..964dcf3 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -110,7 +110,7 @@ dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, 
EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_surf_init(&dri2_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surf;
 
    switch (type) {
@@ -202,6 +202,7 @@ dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay 
*disp, _EGLSurface *surf)
                                        dri2_surf->dri_buffers[i]);
    }
 
+   dri2_surf_deinit(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 1091b4f..ade73e5 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_surf_init(&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_surf_deinit(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 ff35507..971fe63 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -146,7 +146,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_surf_init(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, 
attrib_list, false))
       goto cleanup_surf;
 
    if (dri2_dpy->wl_drm) {
@@ -310,6 +310,7 @@ dri2_wl_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *surf)
    wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
    wl_event_queue_destroy(dri2_surf->wl_queue);
 
+   dri2_surf_deinit(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 b01f739..4d0ee7a 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -224,7 +224,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_surf_init(&dri2_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surf;
 
    dri2_surf->region = XCB_NONE;
@@ -392,6 +392,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_surf_deinit(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 515be27..a83f5f3 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -145,6 +145,7 @@ dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *surf)
 
    loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
 
+   dri2_surf_deinit(surf);
    free(surf);
 
    return EGL_TRUE;
@@ -183,7 +184,7 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, 
EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri3_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_surf_init(&dri3_surf->base, disp, type, conf, attrib_list, false))
       goto cleanup_surf;
 
    if (type == EGL_PBUFFER_BIT) {
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to