From 6bdf417b37b8b8d50facbb610ab2b936bf5cc626 Mon Sep 17 00:00:00 2001 From: Frank Binns Date: Tue, 13 Feb 2018 14:47:48 +0000 Subject: [PATCH] egl/tizen: expose EXT_yuv_surface support This adds support for NV12 and NV21 configs. --- src/egl/drivers/dri2/platform_tizen.c | 278 ++++++++++++++++++-------- 1 file changed, 200 insertions(+), 78 deletions(-) diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c index 2bc9b3e..b6478a1 100644 --- a/src/egl/drivers/dri2/platform_tizen.c +++ b/src/egl/drivers/dri2/platform_tizen.c @@ -100,37 +100,93 @@ create_image_from_native(struct dri2_egl_surface *dri2_surf, { _EGLSurface *surf = &dri2_surf->base; struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display); + struct dri2_egl_config *dri2_conf = dri2_egl_config(surf->Config); + const __DRIconfig *config = + dri2_get_dri_config(dri2_conf, surf->Type, surf->GLColorspace); tbm_bo tbm_buf; tbm_surface_info_s info; - int fd, fourcc, offset, pitch; + int fd[TBM_SURF_PLANE_MAX]; + int offset[TBM_SURF_PLANE_MAX]; + int pitch[TBM_SURF_PLANE_MAX]; + int fourcc; __DRIimage *dri_image; - - tbm_buf = tbm_surface_internal_get_bo(tbm_surf, 0); - if (!tbm_buf) { - _eglLog(_EGL_DEBUG, "%s: failed to get bo for tbm surface", __func__); - return NULL; - } + enum __DRIYUVColorSpace color_space; + enum __DRISampleRange sample_range; + unsigned csc_standard; + unsigned depth_range; + unsigned create_error; if (tbm_surface_get_info(tbm_surf, &info)) { _eglLog(_EGL_DEBUG, "%s: failed to get tbm surface info", __func__); return NULL; } - fd = tbm_bo_export_fd(tbm_buf); fourcc = dri2_fourcc_from_tbm_format(info.format); - offset = info.planes[0].offset; - pitch = info.planes[0].stride; - - dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, - info.width, - info.height, - fourcc, - &fd, - 1, - &pitch, - &offset, - loaderPrivate); - close(fd); + + for (unsigned i = 0; i < info.num_planes; i++) { + int index = tbm_surface_internal_get_plane_bo_idx(tbm_surf, i); + + tbm_buf = tbm_surface_internal_get_bo(tbm_surf, index); + if (!tbm_buf) { + while (i--) + close(fd[i]); + _eglLog(_EGL_DEBUG, "%s: failed to get bo %d for tbm surface", + __func__, i); + return NULL; + } + + fd[i] = tbm_bo_export_fd(tbm_buf); + offset[i] = info.planes[i].offset; + pitch[i] = info.planes[i].stride; + } + + dri2_dpy->core->getConfigAttrib(config, + __DRI_ATTRIB_YUV_CSC_STANDARD, &csc_standard); + switch (csc_standard) { + case __DRI_ATTRIB_YUV_CSC_STANDARD_601_BIT: + color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + break; + case __DRI_ATTRIB_YUV_CSC_STANDARD_709_BIT: + color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709; + break; + case __DRI_ATTRIB_YUV_CSC_STANDARD_2020_BIT: + color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020; + break; + default: + color_space = __DRI_YUV_COLOR_SPACE_UNDEFINED; + break; + } + + dri2_dpy->core->getConfigAttrib(config, + __DRI_ATTRIB_YUV_DEPTH_RANGE, &depth_range); + switch (depth_range) { + case __DRI_ATTRIB_YUV_DEPTH_RANGE_LIMITED_BIT: + sample_range = __DRI_YUV_NARROW_RANGE; + break; + case __DRI_ATTRIB_YUV_DEPTH_RANGE_FULL_BIT: + sample_range = __DRI_YUV_FULL_RANGE; + break; + default: + sample_range = __DRI_YUV_RANGE_UNDEFINED; + break; + } + + dri_image = dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, + info.width, + info.height, + fourcc, + fd, + info.num_planes, + pitch, + offset, + color_space, + sample_range, + __DRI_YUV_CHROMA_SITING_UNDEFINED, + __DRI_YUV_CHROMA_SITING_UNDEFINED, + &create_error, + loaderPrivate); + for (unsigned i = 0; i < info.num_planes; i++) + close(fd[i]); if (!dri_image) { _eglLog(_EGL_DEBUG, "%s: failed to create dri image from tbm bo", __func__); @@ -792,10 +848,22 @@ dri2_tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) { } +static unsigned +dri2_tizen_get_capability(void *loaderPrivate, enum dri_loader_cap cap) +{ + switch (cap) { + case DRI_LOADER_CAP_YUV_SURFACE_IMG: + return 1; + default: + return 0; + } +} + static const __DRIimageLoaderExtension tizen_image_loader_extension = { - .base = { __DRI_IMAGE_LOADER, 1 }, + .base = { __DRI_IMAGE_LOADER, 2 }, .getBuffers = dri2_tizen_get_buffers, .flushFrontBuffer = dri2_tizen_flush_front_buffer, + .getCapability = dri2_tizen_get_capability, }; static const __DRIextension *image_loader_extensions[] = { @@ -804,6 +872,41 @@ static const __DRIextension *image_loader_extensions[] = { NULL, }; +static EGLBoolean +derive_yuv_native_visual_from_config(struct dri2_egl_display *dri2_dpy, + const __DRIconfig *dri_config, + int *native_visual) +{ + unsigned order, subsample, num_planes, plane_bpp; + + dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_ORDER, + &order); + dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_SUBSAMPLE, + &subsample); + dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_NUMBER_OF_PLANES, + &num_planes); + dri2_dpy->core->getConfigAttrib(dri_config, __DRI_ATTRIB_YUV_PLANE_BPP, + &plane_bpp); + + if ((plane_bpp & __DRI_ATTRIB_YUV_PLANE_BPP_8_BIT) == 0) + return EGL_FALSE; + + if (num_planes != 2) + return EGL_FALSE; + + if (subsample & __DRI_ATTRIB_YUV_SUBSAMPLE_4_2_0_BIT) { + if (order & __DRI_ATTRIB_YUV_ORDER_YUV_BIT) { + *native_visual = TBM_FORMAT_NV12; + return EGL_TRUE; + } else if (order & __DRI_ATTRIB_YUV_ORDER_YVU_BIT) { + *native_visual = TBM_FORMAT_NV21; + return EGL_TRUE; + } + } + + return EGL_FALSE; +} + static EGLBoolean dri2_tizen_add_configs(_EGLDisplay *dpy) { @@ -811,83 +914,102 @@ dri2_tizen_add_configs(_EGLDisplay *dpy) int count = 0; for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) { - static const struct rgba_shifts_and_sizes pbuffer_sasa[] = { - { - /* ARGB8888 */ - { 16, 8, 0, 24 }, - { 8, 8, 8, 8 }, - }, - { - /* RGB888 */ - { 16, 8, 0, -1 }, - { 8, 8, 8, 0 }, - }, - { - /* RGB565 */ - { 11, 5, 0, -1 }, - { 5, 6, 5, 0 }, - }, - }; struct dri2_egl_config *dri2_cfg; - int shifts[4]; - unsigned int sizes[4]; + unsigned int render_type; unsigned int caveat = 0; int surface_type = 0; - tpl_bool_t is_slow; EGLint attr_list[] = { EGL_NATIVE_VISUAL_ID, 0, EGL_CONFIG_CAVEAT, EGL_NONE, EGL_NONE, }; - tpl_result_t res; - - dri2_get_shifts_and_sizes(dri2_dpy->core, dri2_dpy->driver_configs[i], - shifts, sizes); dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], - __DRI_ATTRIB_BUFFER_SIZE, &depth); + __DRI_ATTRIB_CONFIG_CAVEAT, &caveat); dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], - __DRI_ATTRIB_CONFIG_CAVEAT, &caveat); + __DRI_ATTRIB_RENDER_TYPE, &render_type); + + if (render_type & __DRI_ATTRIB_RGBA_BIT) { + static const struct rgba_shifts_and_sizes pbuffer_sasa[] = { + { + /* ARGB8888 */ + { 16, 8, 0, 24 }, + { 8, 8, 8, 8 }, + }, + { + /* RGB888 */ + { 16, 8, 0, -1 }, + { 8, 8, 8, 0 }, + }, + { + /* RGB565 */ + { 11, 5, 0, -1 }, + { 5, 6, 5, 0 }, + }, + }; + int shifts[4]; + unsigned int sizes[4]; + unsigned int depth; + tpl_bool_t is_slow; + tpl_result_t res; - res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_WINDOW, - sizes[0], sizes[1], sizes[2], sizes[3], - depth, &attr_list[1], &is_slow); - if (res != TPL_ERROR_NONE) - continue; - surface_type |= EGL_WINDOW_BIT; + dri2_get_shifts_and_sizes(dri2_dpy->core, dri2_dpy->driver_configs[i], + shifts, sizes); - if (is_slow) - caveat |= __DRI_ATTRIB_SLOW_BIT; + dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i], + __DRI_ATTRIB_BUFFER_SIZE, &depth); + + res = tpl_display_query_config(dri2_dpy->tpl_dpy, + TPL_SURFACE_TYPE_WINDOW, + sizes[0], sizes[1], sizes[2], sizes[3], + depth, &attr_list[1], &is_slow); + if (res != TPL_ERROR_NONE) + continue; - res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_PIXMAP, - sizes[0], sizes[1], sizes[2], sizes[3], - depth, NULL, &is_slow); - if (res == TPL_ERROR_NONE) { - surface_type |= EGL_PIXMAP_BIT; + surface_type |= EGL_WINDOW_BIT; if (is_slow) caveat |= __DRI_ATTRIB_SLOW_BIT; - } - for (unsigned j = 0; j < ARRAY_SIZE(pbuffer_sasa); j++) { - const struct rgba_shifts_and_sizes *pbuffer_sas = &pbuffer_sasa[j]; - - if (shifts[0] == pbuffer_sas->shifts[0] && - shifts[1] == pbuffer_sas->shifts[1] && - shifts[2] == pbuffer_sas->shifts[2] && - shifts[3] == pbuffer_sas->shifts[3] && - sizes[0] == pbuffer_sas->sizes[0] && - sizes[1] == pbuffer_sas->sizes[1] && - sizes[2] == pbuffer_sas->sizes[2] && - sizes[3] == pbuffer_sas->sizes[3]) { - surface_type |= EGL_PBUFFER_BIT; - break; + res = tpl_display_query_config(dri2_dpy->tpl_dpy, + TPL_SURFACE_TYPE_PIXMAP, + sizes[0], sizes[1], sizes[2], sizes[3], + depth, NULL, &is_slow); + if (res == TPL_ERROR_NONE) { + surface_type |= EGL_PIXMAP_BIT; + + if (is_slow) + caveat |= __DRI_ATTRIB_SLOW_BIT; } - } - if (dri2_dpy->image->base.version >= 9 && dri2_dpy->image->blitImage) - surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + for (unsigned j = 0; j < ARRAY_SIZE(pbuffer_sasa); j++) { + const struct rgba_shifts_and_sizes *pbuffer_sas = &pbuffer_sasa[j]; + + if (shifts[0] == pbuffer_sas->shifts[0] && + shifts[1] == pbuffer_sas->shifts[1] && + shifts[2] == pbuffer_sas->shifts[2] && + shifts[3] == pbuffer_sas->shifts[3] && + sizes[0] == pbuffer_sas->sizes[0] && + sizes[1] == pbuffer_sas->sizes[1] && + sizes[2] == pbuffer_sas->sizes[2] && + sizes[3] == pbuffer_sas->sizes[3]) { + surface_type |= EGL_PBUFFER_BIT; + break; + } + + } + + if (dri2_dpy->image->base.version >= 9 && dri2_dpy->image->blitImage) + surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + } else if (render_type & __DRI_ATTRIB_YUV_BIT) { + if (!derive_yuv_native_visual_from_config(dri2_dpy, + dri2_dpy->driver_configs[i], + &attr_list[1])) + continue; + surface_type = EGL_WINDOW_BIT; + caveat = 0; + } if (caveat & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) attr_list[3] = EGL_NON_CONFORMANT_CONFIG;