[Mesa-dev] [PATCH v2 7/9] egl/tizen: add tizen specific implementation for EGL_WAYLAND_BUFFER_WL target of eglCreateImageKHR()
Gwan-gyeong Mun
elongbug at gmail.com
Sun Sep 17 18:01:05 UTC 2017
In the tizen platform, a wl_buffer wraps a tbm_surface. The tbm_surface contains
gem name or prime fd. For creating dri_image, we need to extract the tbm_surface
from the wl_buffer and we use tpl_display_get_buffer_from_native_pixmap() api
for that.
Signed-off-by: Mun Gwan-gyeong <elongbug at gmail.com>
---
src/egl/drivers/dri2/platform_tizen.c | 309 +++++++++++++++++++++++++++++++++-
1 file changed, 308 insertions(+), 1 deletion(-)
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
index 19db84b553..3fe6cb504b 100644
--- a/src/egl/drivers/dri2/platform_tizen.c
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -47,6 +47,60 @@
#include "egl_dri2_fallbacks.h"
#include "loader.h"
+/* createImageFromFds requires fourcc format */
+static int get_fourcc(tbm_format format)
+{
+ switch (format) {
+ case TBM_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
+ case TBM_FORMAT_BGRA8888: return __DRI_IMAGE_FOURCC_ARGB8888;
+ case TBM_FORMAT_RGBA8888: return __DRI_IMAGE_FOURCC_ABGR8888;
+ case TBM_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
+ case TBM_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
+ case TBM_FORMAT_RGBX8888: return __DRI_IMAGE_FOURCC_XBGR8888;
+ case TBM_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
+ default:
+ _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
+ }
+ return -1;
+}
+
+static int get_fourcc_yuv(tbm_format format)
+{
+ switch (format) {
+ case TBM_FORMAT_NV12: return __DRI_IMAGE_FOURCC_NV12;
+ case TBM_FORMAT_NV21: return __DRI_IMAGE_FOURCC_NV12;
+ case TBM_FORMAT_YUV420: return __DRI_IMAGE_FOURCC_YUV420;
+ case TBM_FORMAT_YVU420: return __DRI_IMAGE_FOURCC_YVU420;
+ default:
+ _eglLog(_EGL_WARNING, "unsupported native yuv buffer format 0x%x", format);
+ }
+ return -1;
+}
+
+static bool is_yuv_format(tbm_format format)
+{
+ if (get_fourcc_yuv(format) == -1)
+ return false;
+ else
+ return true;
+}
+
+static int get_format(tbm_format format)
+{
+ switch (format) {
+ case TBM_FORMAT_RGB565: return __DRI_IMAGE_FORMAT_RGB565;
+ case TBM_FORMAT_BGRA8888: return __DRI_IMAGE_FORMAT_ARGB8888;
+ case TBM_FORMAT_RGBA8888: return __DRI_IMAGE_FORMAT_ABGR8888;
+ case TBM_FORMAT_ARGB8888: return __DRI_IMAGE_FORMAT_ARGB8888;
+ case TBM_FORMAT_ABGR8888: return __DRI_IMAGE_FORMAT_ABGR8888;
+ case TBM_FORMAT_RGBX8888: return __DRI_IMAGE_FORMAT_XBGR8888;
+ case TBM_FORMAT_XRGB8888: return __DRI_IMAGE_FORMAT_XRGB8888;
+ default:
+ _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
+ }
+ return -1;
+}
+
static int get_format_bpp(tbm_format format)
{
int bpp;
@@ -84,6 +138,16 @@ static int get_pitch(tbm_surface_h tbm_surface)
return surf_info.planes[0].stride;
}
+static int
+get_native_buffer_fd(tbm_surface_h tbm_surface)
+{
+ tbm_bo_handle bo_handle;
+ bo_handle = tbm_bo_get_handle(tbm_surface_internal_get_bo(tbm_surface, 0),
+ TBM_DEVICE_3D);
+
+ return (bo_handle.ptr != NULL) ? (int)bo_handle.u32 : -1;
+}
+
static int
get_native_buffer_name(tbm_surface_h tbm_surface)
{
@@ -403,6 +467,215 @@ tizen_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
return tizen_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
}
+static _EGLImage *
+tizen_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
+ tbm_surface_h tbm_surface)
+
+{
+ tbm_surface_info_s surf_info;
+ tbm_fd bo_fd[TBM_SURF_PLANE_MAX];
+ tbm_bo bo[TBM_SURF_PLANE_MAX];
+ int num_planes;
+ int i;
+ int fourcc;
+ size_t offsets[3] = {0, 0, 0};
+ size_t pitches[3] = {0, 0, 0};
+ int fds[3] = {-1, -1, -1};
+
+ if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
+ _eglLog(_EGL_WARNING, "Could not get tbm_surface_info");
+ return NULL;
+ }
+
+ num_planes = surf_info.num_planes;
+ for (i = 0; i < num_planes; i++) {
+ tbm_bo_handle bo_handle;
+ int bo_idx = tbm_surface_internal_get_plane_bo_idx(tbm_surface, i);
+ bo[i] = tbm_surface_internal_get_bo (tbm_surface, bo_idx);
+ if (bo[i] == NULL) {
+ _eglLog(_EGL_WARNING, "Could not get tbm_surface_internal_bo");
+ return NULL;
+ }
+ bo_handle = tbm_bo_get_handle(bo[i], TBM_DEVICE_3D);
+ bo_fd[i] = bo_handle.u32;
+ }
+
+ fourcc = get_fourcc_yuv(tbm_surface_get_format(tbm_surface));
+ if (fourcc == -1) {
+ _eglLog(_EGL_WARNING, "Unsupported native yuv format");
+ return NULL;
+ }
+
+ switch (fourcc) {
+ case __DRI_IMAGE_FOURCC_NV12:
+ fds[0] = bo_fd[0];
+ fds[1] = bo_fd[1];
+ offsets[0] = surf_info.planes[0].offset;
+ offsets[1] = surf_info.planes[1].offset;
+ pitches[0] = surf_info.planes[0].stride;
+ pitches[1] = surf_info.planes[1].stride;
+ break;
+ case __DRI_IMAGE_FOURCC_YUV420:
+ fds[0] = bo_fd[0];
+ fds[1] = bo_fd[1];
+ fds[2] = bo_fd[2];
+ offsets[0] = surf_info.planes[0].offset;
+ offsets[1] = surf_info.planes[1].offset;
+ offsets[2] = surf_info.planes[2].offset;
+ pitches[0] = surf_info.planes[0].stride;
+ pitches[1] = surf_info.planes[1].stride;
+ pitches[2] = surf_info.planes[2].stride;
+ break;
+ case __DRI_IMAGE_FOURCC_YVU420:
+ fds[0] = bo_fd[0];
+ fds[1] = bo_fd[2];
+ fds[2] = bo_fd[1];
+ offsets[0] = surf_info.planes[0].offset;
+ offsets[1] = surf_info.planes[2].offset;
+ offsets[2] = surf_info.planes[1].offset;
+ pitches[0] = surf_info.planes[0].stride;
+ pitches[1] = surf_info.planes[2].stride;
+ pitches[2] = surf_info.planes[1].stride;
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "Unsupported native yuv format");
+ return NULL;
+ }
+
+ if (num_planes == 2) {
+ const EGLint attr_list_2plane[] = {
+ EGL_WIDTH, surf_info.width,
+ EGL_HEIGHT, surf_info.height,
+ EGL_LINUX_DRM_FOURCC_EXT, fourcc,
+ EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
+ EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
+ EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
+ EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
+ EGL_NONE, 0
+ };
+ return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
+ } else if (num_planes == 3) {
+ const EGLint attr_list_3plane[] = {
+ EGL_WIDTH, surf_info.width,
+ EGL_HEIGHT, surf_info.height,
+ EGL_LINUX_DRM_FOURCC_EXT, fourcc,
+ EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
+ EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
+ EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
+ EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
+ EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
+ EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
+ EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
+ EGL_NONE, 0
+ };
+ return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
+ } else {
+ _eglLog(_EGL_WARNING, "Unsupported yuv planes");
+ return NULL;
+ }
+}
+
+static _EGLImage *
+tizen_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
+ tbm_surface_h tbm_surface , int fd)
+{
+ unsigned int pitch;
+ tbm_surface_info_s surf_info;
+
+ if (is_yuv_format(tbm_surface_get_format(tbm_surface)))
+ return tizen_create_image_from_prime_fd_yuv(disp, ctx, tbm_surface);
+
+ const int fourcc = get_fourcc(tbm_surface_get_format(tbm_surface));
+ if (fourcc == -1) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+ pitch = surf_info.planes[0].stride;
+
+ if (pitch == 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ const EGLint attr_list[] = {
+ EGL_WIDTH, surf_info.width,
+ EGL_HEIGHT, surf_info.height,
+ EGL_LINUX_DRM_FOURCC_EXT, fourcc,
+ EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
+ EGL_NONE, 0
+ };
+
+ return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
+}
+
+static _EGLImage *
+tizen_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
+ tbm_surface_h tbm_surface)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_image *dri2_img;
+ int name;
+ int format;
+ unsigned int pitch;
+ tbm_surface_info_s surf_info;
+
+ name = get_native_buffer_name(tbm_surface);
+ if (!name) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ format = get_format(tbm_surface_get_format(tbm_surface));
+ if (format == -1)
+ return NULL;
+
+ if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+ pitch = surf_info.planes[0].stride;
+
+ if (pitch == 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ dri2_img = calloc(1, sizeof(*dri2_img));
+ if (!dri2_img) {
+ _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
+ return NULL;
+ }
+
+ _eglInitImage(&dri2_img->base, disp);
+
+ dri2_img->dri_image =
+ dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
+ surf_info.width,
+ surf_info.height,
+ format,
+ name,
+ pitch,
+ dri2_img);
+ if (!dri2_img->dri_image) {
+ free(dri2_img);
+ _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
+ return NULL;
+ }
+
+ return &dri2_img->base;
+}
+
static EGLBoolean
tizen_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint attribute, EGLint *value)
@@ -435,6 +708,40 @@ tizen_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
return _eglQuerySurface(drv, dpy, surf, attribute, value);
}
+static _EGLImage *
+dri2_create_image_tizen_wl_buffer(_EGLDisplay *disp,
+ _EGLContext *ctx,
+ tpl_handle_t native_pixmap)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ int fd;
+ tbm_surface_h tbm_surface = NULL;
+
+ tbm_surface = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_display,
+ (tpl_handle_t)native_pixmap);
+ if (!tbm_surface)
+ return NULL;
+
+ fd = get_native_buffer_fd(tbm_surface);
+ if (fd >= 0)
+ return tizen_create_image_from_prime_fd(disp, ctx, tbm_surface, fd);
+
+ return tizen_create_image_from_name(disp, ctx, tbm_surface);
+}
+
+static _EGLImage *
+tizen_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLContext *ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ switch (target) {
+ case EGL_WAYLAND_BUFFER_WL:
+ return dri2_create_image_tizen_wl_buffer(disp, ctx, (tpl_handle_t)buffer);
+ default:
+ return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+ }
+}
+
static void
tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
{
@@ -703,7 +1010,7 @@ static const struct dri2_egl_display_vtbl tizen_display_vtbl = {
.create_pixmap_surface = tizen_create_pixmap_surface,
.create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
.destroy_surface = tizen_destroy_surface,
- .create_image = dri2_create_image_khr,
+ .create_image = tizen_create_image_khr,
.swap_interval = dri2_fallback_swap_interval,
.swap_buffers = tizen_swap_buffers,
.swap_buffers_with_damage = tizen_swap_buffers_with_damage,
--
2.14.1
More information about the mesa-dev
mailing list