From 2acc69da8cefe622139d38985af897be5be1e169 Mon Sep 17 00:00:00 2001 From: Xiaosong Wei Date: Wed, 8 Feb 2017 10:46:02 +0800 Subject: [PATCH] EGL/Android: Add EGL_EXT_buffer_age extension MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch implements the EGL_EXT_buffer_age extension for Android. https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_buffer_age.txt Reviewed-by: Tapani Pälli Acked-by: Emil Velikov --- src/egl/drivers/dri2/egl_dri2.h | 9 +++++ src/egl/drivers/dri2/platform_android.c | 51 ++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index f3437e2b5a2..f981e3890b6 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -300,6 +300,15 @@ struct dri2_egl_surface /* EGL-owned buffers */ __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT]; + + /* Used to record all the buffers created by ANativeWindow and their ages. + * Usually Android uses at most triple buffers in ANativeWindow + * so hardcode the number of color_buffers to 3. + */ + struct { + struct ANativeWindowBuffer *buffer; + int age; + } color_buffers[3], *back; #endif #if defined(HAVE_SURFACELESS_PLATFORM) diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 511b696192a..14e13b8e85c 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -203,6 +203,33 @@ droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer); #endif + /* Record all the buffers created by ANativeWindow 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].buffer) { + dri2_surf->color_buffers[i].buffer = dri2_surf->buffer; + } + if (dri2_surf->color_buffers[i].buffer == dri2_surf->buffer) { + dri2_surf->back = &dri2_surf->color_buffers[i]; + updated = EGL_TRUE; + break; + } + } + + if (!updated) { + /* In case of all the buffers were recreated by ANativeWindow, reset + * the color_buffers + */ + for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { + dri2_surf->color_buffers[i].buffer = NULL; + dri2_surf->color_buffers[i].age = 0; + } + dri2_surf->color_buffers[0].buffer = dri2_surf->buffer; + dri2_surf->back = &dri2_surf->color_buffers[0]; + } + return EGL_TRUE; } @@ -239,6 +266,7 @@ droid_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_sur dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common); dri2_surf->buffer = NULL; + dri2_surf->back = NULL; mtx_lock(&disp->Mutex); @@ -579,6 +607,20 @@ droid_image_get_buffers(__DRIdrawable *driDrawable, return 1; } +static EGLint +droid_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, "droid_query_buffer_age"); + return 0; + } + + return dri2_surf->back->age; +} + static EGLBoolean droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { @@ -588,6 +630,12 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 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++; + } + dri2_surf->back->age = 1; + dri2_flush_drawable_for_swapbuffers(disp, draw); if (dri2_surf->buffer) @@ -1042,7 +1090,7 @@ static struct dri2_egl_display_vtbl droid_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 = droid_query_buffer_age, .query_surface = droid_query_surface, .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, .get_sync_values = dri2_fallback_get_sync_values, @@ -1141,6 +1189,7 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE; dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; dpy->Extensions.ANDROID_recordable = EGL_TRUE; + dpy->Extensions.EXT_buffer_age = EGL_TRUE; /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. -- 2.30.2