It adds support of dri2_loader to egl dri2 tizen backend. - referenced a basic buffer flow and management implementation from android.
And it implements a query buffer age extesion for tizen and turn on swap_buffers_with_damage extension. - it add color buffer related member variables to dri_egl_surface for a management of color buffers. v2: Fixes from Emil's review: a) Remove a temporary variable and return directly on get_format_bpp() b) Remove unneeded compiler pragma c) Follow coding style d) Rename get_pitch() to get_stride() for using of consistent naming e) Remove mis-referencing from android implementation on treatment of buffer age. reference: https://lists.freedesktop.org/archives/mesa-dev/2017-June/158409.html f) Use dri2_egl_surface_free_outdated_buffers_and_update_size() helper g) Use dri2_egl_surface_record_buffers_and_update_back_buffer() helper h) Use add dri2_egl_surface_update_buffer_age() helper i) Use env_var_as_boolean for hw_accel variable on dri2_initialize_tizen() j) Remove getting of the device name and opening of the device node on dri2_initialize_tizen() And add duplicating of tbm_bufmgr_fd. As tbm_bufmgr_fd is managed by tbm_bufmgr, if mesa use this fd then we should duplicate it. k) Add comments why we can not drop the dri2 codepath on dri2_initialize_tizen() As some kernels ported for tizen don't support render node feature yet, currently we cannot drop the dri2 codepath. v3: Fixes from Rob and Emil's review: - Use refactored color_buffers structure Signed-off-by: Mun Gwan-gyeong <elong...@gmail.com> --- src/egl/drivers/dri2/egl_dri2.h | 2 + src/egl/drivers/dri2/platform_tizen.c | 257 ++++++++++++++++++++++++++++++++-- 2 files changed, 245 insertions(+), 14 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 4e1fead46b..12c46759d3 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -78,6 +78,8 @@ struct zwp_linux_dmabuf_v1; #else /* Usually Android uses at most triple buffers in ANativeWindow * so hardcode the number of color_buffers to 3. + * And usually Tizen uses at most triple buffers in tpl_surface + * (tbm_surface_queue) so hardcode the number of color_buffers to 3. */ #define COLOR_BUFFERS_SIZE 3 #endif diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c index 7cee03f784..72cef25364 100644 --- a/src/egl/drivers/dri2/platform_tizen.c +++ b/src/egl/drivers/dri2/platform_tizen.c @@ -46,6 +46,43 @@ #include "egl_dri2.h" #include "egl_dri2_fallbacks.h" #include "loader.h" +#include "util/debug.h" + +static int get_format_bpp(tbm_format format) +{ + switch (format) { + case TBM_FORMAT_BGRA8888: + case TBM_FORMAT_RGBA8888: + case TBM_FORMAT_RGBX8888: + case TBM_FORMAT_ARGB8888: + case TBM_FORMAT_XRGB8888: + return 4; + case TBM_FORMAT_RGB565: + return 2; + default: + return 0; + } +} + +static int get_stride(tbm_surface_h tbm_surface) +{ + tbm_surface_info_s surf_info; + + if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) + return 0; + + return surf_info.planes[0].stride; +} + +static int +get_native_buffer_name(tbm_surface_h tbm_surface) +{ + uint32_t bo_name; + + bo_name = tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)); + + return (bo_name != 0 ) ? (int)bo_name : -1; +} static EGLBoolean tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) @@ -60,10 +97,14 @@ tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) tbm_surface_internal_ref(dri2_surf->tbm_surface); tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height); - if (dri2_surf->base.Width != width || dri2_surf->base.Height != height) { - dri2_surf->base.Width = width; - dri2_surf->base.Height = height; - } + + dri2_egl_surface_free_outdated_buffers_and_update_size(dri2_surf, width, height); + + /* Record all the buffers created by tpl_surface (tbm_surface_queue) + * and update back buffer for updating buffer's age in swap_buffers. + */ + dri2_egl_surface_record_buffers_and_update_back_buffer(dri2_surf, + (void*)dri2_surf->tbm_surface); return EGL_TRUE; } @@ -101,6 +142,7 @@ tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp, tbm_surface_internal_unref(dri2_surf->tbm_surface); dri2_surf->tbm_surface = NULL; + dri2_surf->back = NULL; mtx_lock(&disp->Mutex); @@ -208,7 +250,10 @@ tizen_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, if (!dri2_surf->tpl_surface) goto cleanup_surface; - createNewDrawable = dri2_dpy->swrast->createNewDrawable; + if (dri2_dpy->dri2) + createNewDrawable = dri2_dpy->dri2->createNewDrawable; + else + createNewDrawable = dri2_dpy->swrast->createNewDrawable; dri2_surf->dri_drawable = (*createNewDrawable)(dri2_dpy->dri_screen, config, dri2_surf); @@ -251,6 +296,8 @@ tizen_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + dri2_egl_surface_free_local_buffers(dri2_surf); + if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->tbm_surface) tizen_window_cancel_buffer(disp, dri2_surf); @@ -278,6 +325,19 @@ update_buffers(struct dri2_egl_surface *dri2_surf) return 0; } +static EGLint +tizen_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, "tizen_query_buffer_age"); + return -1; + } + + return dri2_surf->back->age; +} + static EGLBoolean tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, const EGLint *rects, @@ -289,10 +349,17 @@ tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp, if (dri2_surf->base.Type != EGL_WINDOW_BIT) return EGL_TRUE; + dri2_egl_surface_update_buffer_age(dri2_surf); + if (dri2_surf->tbm_surface) tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, rects, n_rects); - dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); + if (dri2_dpy->swrast) { + dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); + } else { + dri2_flush_drawable_for_swapbuffers(disp, draw); + dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); + } return EGL_TRUE; } @@ -333,6 +400,87 @@ tizen_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, return _eglQuerySurface(drv, dpy, surf, attribute, value); } +static void +tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) +{ +} + +static int +tizen_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf, + unsigned int *attachments, int count) +{ + int num_buffers = 0; + + /* fill dri2_surf->buffers */ + for (int i = 0; i < count * 2; i += 2) { + __DRIbuffer *buf, *local; + + assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers)); + buf = &dri2_surf->buffers[num_buffers]; + + switch (attachments[i]) { + case __DRI_BUFFER_BACK_LEFT: + if (dri2_surf->base.Type == EGL_WINDOW_BIT) { + buf->attachment = attachments[i]; + buf->name = get_native_buffer_name(dri2_surf->tbm_surface); + buf->cpp = get_format_bpp(tbm_surface_get_format(dri2_surf->tbm_surface)); + buf->pitch = get_stride(dri2_surf->tbm_surface); + buf->flags = 0; + + if (buf->name) + num_buffers++; + + break; + } + /* fall through for pbuffers */ + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_STENCIL: + case __DRI_BUFFER_ACCUM: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_HIZ: + local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i], + attachments[i + 1]); + + if (local) { + *buf = *local; + num_buffers++; + } + break; + case __DRI_BUFFER_FRONT_LEFT: + case __DRI_BUFFER_FRONT_RIGHT: + case __DRI_BUFFER_FAKE_FRONT_LEFT: + case __DRI_BUFFER_FAKE_FRONT_RIGHT: + case __DRI_BUFFER_BACK_RIGHT: + default: + /* no front or right buffers */ + break; + } + } + + return num_buffers; +} + +static __DRIbuffer * +tizen_get_buffers_with_format(__DRIdrawable * driDrawable, + int *width, int *height, + unsigned int *attachments, int count, + int *out_count, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + if (update_buffers(dri2_surf) < 0) + return NULL; + + *out_count = tizen_get_buffers_parse_attachments(dri2_surf, attachments, count); + + if (width) + *width = dri2_surf->base.Width; + if (height) + *height = dri2_surf->base.Height; + + return dri2_surf->buffers; +} + static int tizen_swrast_get_stride_for_format(tbm_format format, int w) { @@ -550,13 +698,21 @@ static const struct dri2_egl_display_vtbl tizen_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 = tizen_query_buffer_age, .query_surface = tizen_query_surface, .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, .get_sync_values = dri2_fallback_get_sync_values, .get_dri_drawable = dri2_surface_get_dri_drawable, }; +static const __DRIdri2LoaderExtension tizen_dri2_loader_extension = { + .base = { __DRI_DRI2_LOADER, 3 }, + + .getBuffers = NULL, + .getBuffersWithFormat = tizen_get_buffers_with_format, + .flushFrontBuffer = tizen_flush_front_buffer, +}; + static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = { .base = { __DRI_SWRAST_LOADER, 2 }, @@ -566,6 +722,13 @@ static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = { .putImage2 = tizen_swrast_put_image2, }; +static const __DRIextension *tizen_dri2_loader_extensions[] = { + &tizen_dri2_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, @@ -579,6 +742,7 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy) tpl_display_t *tpl_display = NULL; const char *err; int tbm_bufmgr_fd = -1; + bool hw_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); loader_set_logger(_eglLog); @@ -599,7 +763,11 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy) } dri2_dpy->tpl_display = tpl_display; - /* Get tbm_bufmgr's fd */ + /* Get tbm_bufmgr's fd + * As tbm_bufmgr_fd is managed by tbm_bufmgr, if mesa use this fd then we + * should duplicate it. + * (When dri2_display_destroy() is called, it close dri2_dpy->fd) + */ tbm_bufmgr_fd = tbm_drm_helper_get_fd(); if (tbm_bufmgr_fd == -1) { @@ -607,13 +775,71 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy) goto cleanup; } - dri2_dpy->fd = tbm_bufmgr_fd; - dri2_dpy->driver_name = strdup("swrast"); - if (!dri2_load_driver_swrast(dpy)) { - err = "DRI2: failed to load swrast driver"; - goto cleanup; + if (hw_accel) { + int fd = -1; + + if (drmGetNodeTypeFromFd(tbm_bufmgr_fd) == DRM_NODE_RENDER) + fd = dup(tbm_bufmgr_fd); + else { + /* As some kernels ported for tizen don't support render node feature + * yet, currently we cannot drop the dri2 codepath. + */ + if (!tbm_drm_helper_get_auth_info(&fd, NULL, NULL)) { + /* FIXME: tbm_drm_helper_get_auth_info() does not support the case of + * display server for now. this code is fallback routine for + * that Enlightenment Server fails on tbm_drm_helper_get_auth_info. + * When tbm_drm_helper_get_auth_info() supports display server + * case, then remove below routine. + */ +#if 1 + fd = dup(tbm_bufmgr_fd); +#else + err = "DRI2: failed to get fd from tbm_drm_helper_get_auth_info()"; + goto cleanup; +#endif + } + } + + if (fd < 0) { + err = "DRI2: failed to get fd"; + goto cleanup; + } + dri2_dpy->fd = fd; + + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); + if (dri2_dpy->driver_name == NULL) { + err = "DRI2: failed to get driver name"; + goto cleanup; + } + + dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; + /* render nodes cannot use Gem names, and thus do not support + * the __DRI_DRI2_LOADER extension */ + + if (!dri2_dpy->is_render_node) { + dri2_dpy->loader_extensions = tizen_dri2_loader_extensions; + if (!dri2_load_driver(dpy)) { + err = "DRI2: failed to load driver"; + goto cleanup; + } + } else { + err = "DRI2: render node is not suppported"; + goto cleanup; + } + + } else { + dri2_dpy->fd = dup(tbm_bufmgr_fd); + if (dri2_dpy->fd < 0) { + err = "DRI2: failed to dup fd"; + goto cleanup; + } + dri2_dpy->driver_name = strdup("swrast"); + if (!dri2_load_driver_swrast(dpy)) { + err = "DRI2: failed to load swrast driver"; + goto cleanup; + } + dri2_dpy->loader_extensions = tizen_swrast_loader_extensions; } - dri2_dpy->loader_extensions = tizen_swrast_loader_extensions; if (!dri2_create_screen(dpy)) { err = "DRI2: failed to create screen"; @@ -637,6 +863,9 @@ dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy) */ dri2_dpy->vtbl = &tizen_display_vtbl; + dpy->Extensions.EXT_buffer_age = EGL_TRUE; + dpy->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE; + return EGL_TRUE; cleanup: -- 2.14.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev