[Mesa-dev] [PATCH v5 05/10] egl/tizen: add support of dri2_loader (v3)
Gwan-gyeong Mun
elongbug at gmail.com
Wed Oct 25 16:50:58 UTC 2017
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_surface_fixup() helper
g) Use dri2_surface_set_back_buffer() helper
h) Use dri2_surface_update_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 <elongbug at gmail.com>
---
src/egl/drivers/dri2/egl_dri2.h | 6 +-
src/egl/drivers/dri2/platform_tizen.c | 256 ++++++++++++++++++++++++++++++++--
2 files changed, 246 insertions(+), 16 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 3c1f7524e4..4d41613960 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -73,9 +73,11 @@ struct zwp_linux_dmabuf_v1;
#include <tbm_surface_internal.h>
#endif /* HAVE_TIZEN_PLATFORM */
-#ifdef HAVE_ANDROID_PLATFORM
+#if defined(HAVE_ANDROID_PLATFORM) || defined(HAVE_TIZEN_PLATFORM)
/* Usually Android uses at most triple buffers in ANativeWindow so hardcode
- * the number of color_buffers to 3.
+ * 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
#else
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 7cee03f784..addb7c8862 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,13 @@ 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_surface_fixup(&dri2_surf->base, 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_surface_set_back_buffer(&dri2_surf->base, dri2_surf->tbm_surface);
return EGL_TRUE;
}
@@ -101,6 +141,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 +249,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 +295,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 +324,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 +348,17 @@ tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp,
if (dri2_surf->base.Type != EGL_WINDOW_BIT)
return EGL_TRUE;
+ dri2_surface_update_age(draw);
+
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 +399,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 +697,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 +721,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 +741,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 +762,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 +774,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 +862,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
More information about the mesa-dev
mailing list