From cf77d969314e92870ffb6d3b59b73291f974e066 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 12 Jan 2018 16:42:27 +0900 Subject: [PATCH] support nexell pp erase pixman. use nexell scaling. support only YUV420 format. set pp preferred align to 32. restrition: support only scanout buffer. align(src_width:32, dst_width:8) Change-Id: I8d362c2d24d9990cb50c5fcef625ee3e1d5d542e Signed-off-by: Junkyeong Kim --- packaging/libtdm-nexell.spec | 8 + src/tdm_nexell.c | 6 + src/tdm_nexell.h | 1 + src/tdm_nexell_pp.c | 346 +++++++++++++++++-------------------------- 4 files changed, 151 insertions(+), 210 deletions(-) diff --git a/packaging/libtdm-nexell.spec b/packaging/libtdm-nexell.spec index a797223..b021269 100644 --- a/packaging/libtdm-nexell.spec +++ b/packaging/libtdm-nexell.spec @@ -4,12 +4,20 @@ Release: 0 Summary: Tizen Display Manager Nexell Back-End Library Group: Development/Libraries License: MIT +ExclusiveArch: %{arm} aarch64 Source0: %{name}-%{version}.tar.gz Source1001: %{name}.manifest BuildRequires: pkgconfig(libdrm) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libtdm) BuildRequires: pkgconfig(pixman-1) +%ifarch %{arm} +BuildRequires: artik530-raptor-linux-kernel-headers +BuildConflicts: linux-glibc-devel +%else +BuildRequires: artik710-raptor-linux-kernel-headers +BuildConflicts: linux-glibc-devel +%endif %description Back-End library of Tizen Display Manager Nexell : libtdm-mgr Nexell library diff --git a/src/tdm_nexell.c b/src/tdm_nexell.c index 0f1984b..f905f82 100644 --- a/src/tdm_nexell.c +++ b/src/tdm_nexell.c @@ -225,6 +225,8 @@ tdm_nexell_deinit(tdm_backend_data *bdata) drmModeFreeResources(nexell_data->mode_res); if (nexell_data->drm_fd >= 0) close(nexell_data->drm_fd); + if (nexell_data->scaler_fd >= 0) + close(nexell_data->scaler_fd); free(nexell_data); nexell_data = NULL; @@ -346,6 +348,10 @@ tdm_nexell_init(tdm_display *dpy, tdm_error *error) TDM_INFO("master fd(%d)", nexell_data->drm_fd); + nexell_data->scaler_fd = open("/dev/scaler", O_RDWR); + if (nexell_data->scaler_fd < 0) + TDM_ERR("scaler open fail. cannot use pp."); + #ifdef HAVE_UDEV _tdm_nexell_udev_init(nexell_data); #endif diff --git a/src/tdm_nexell.h b/src/tdm_nexell.h index 4290cc1..30111b2 100644 --- a/src/tdm_nexell.h +++ b/src/tdm_nexell.h @@ -105,6 +105,7 @@ typedef struct _tdm_nexell_data tdm_display *dpy; int drm_fd; + int scaler_fd; #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4 && LIBDRM_MICRO_VERSION >= 47 int has_universal_plane; diff --git a/src/tdm_nexell_pp.c b/src/tdm_nexell_pp.c index 2a84266..50aa56f 100644 --- a/src/tdm_nexell_pp.c +++ b/src/tdm_nexell_pp.c @@ -2,10 +2,10 @@ #include "config.h" #endif -#include +#include +#include #include "tdm_nexell.h" -#include "tdm_helper.h" typedef struct _tdm_nexell_pp_buffer { tbm_surface_h src; @@ -27,225 +27,140 @@ typedef struct _tdm_nexell_pp_data { struct list_head link; } tdm_nexell_pp_data; +#define MAX_PLANE_NUM 3 -static tbm_format pp_formats[] = { - TBM_FORMAT_ARGB8888, - TBM_FORMAT_XRGB8888, - TBM_FORMAT_YUV420, - TBM_FORMAT_YVU420 +struct rect { + int x; + int y; + int width; + int height; }; -#define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0])) - -static int pp_list_init; -static struct list_head pp_list; - -static pixman_format_code_t -_tdm_nexell_pp_pixman_get_format(tbm_format tbmfmt) -{ - switch (tbmfmt) { - case TBM_FORMAT_ARGB8888: - return PIXMAN_a8r8g8b8; - case TBM_FORMAT_XRGB8888: - return PIXMAN_x8r8g8b8; - case TBM_FORMAT_YUV420: - case TBM_FORMAT_YVU420: - return PIXMAN_yv12; - default: - return 0; - } -} - -int -_tdm_nexell_pp_pixman_convert(pixman_op_t op, - unsigned char *srcbuf, unsigned char *dstbuf, - pixman_format_code_t src_format, pixman_format_code_t dst_format, - int sbw, int sbh, int sx, int sy, int sw, int sh, - int dbw, int dbh, int dx, int dy, int dw, int dh, - int rotate, int hflip, int vflip) -{ - pixman_image_t *src_img; - pixman_image_t *dst_img; - struct pixman_f_transform ft; - pixman_transform_t transform; - int src_stride, dst_stride; - int src_bpp; - int dst_bpp; - double scale_x, scale_y; - int rotate_step; - int ret = 0; - - RETURN_VAL_IF_FAIL(srcbuf != NULL, 0); - RETURN_VAL_IF_FAIL(dstbuf != NULL, 0); - - TDM_DBG("src(%dx%d: %d,%d %dx%d) dst(%dx%d: %d,%d %dx%d) flip(%d,%d), rot(%d)", - sbw, sbh, sx, sy, sw, sh, dbw, dbh, dx, dy, dw, dh, hflip, vflip, rotate); +typedef struct _tdm_nexell_scaler_context { + int src_plane_num; + int src_fds[MAX_PLANE_NUM]; + int src_stride[MAX_PLANE_NUM]; + unsigned int src_width; + unsigned int src_height; + unsigned int src_code; - src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8; - RETURN_VAL_IF_FAIL(src_bpp > 0, 0); + int dst_plane_num; + int dst_fds[MAX_PLANE_NUM]; + int dst_stride[MAX_PLANE_NUM]; + unsigned int dst_width; + unsigned int dst_height; + unsigned int dst_code; - dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8; - RETURN_VAL_IF_FAIL(dst_bpp > 0, 0); + struct rect crop; +} tdm_nexell_scaler_context; - rotate_step = (rotate + 360) / 90 % 4; - - src_stride = sbw * src_bpp; - dst_stride = dbw * dst_bpp; - - src_img = pixman_image_create_bits(src_format, sbw, sbh, (uint32_t *)srcbuf, - src_stride); - dst_img = pixman_image_create_bits(dst_format, dbw, dbh, (uint32_t *)dstbuf, - dst_stride); +static tbm_format pp_formats[] = { + TBM_FORMAT_YUV420 +}; - GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT); - GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT); +#define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0])) +#define IOC_NX_MAGIC 0x6e78 /* nx */ +enum { + IOCTL_SCALER_SET_AND_RUN = _IO(IOC_NX_MAGIC, 1), +}; - pixman_f_transform_init_identity(&ft); +#ifndef ALIGN +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#endif - if (hflip) { - pixman_f_transform_scale(&ft, NULL, -1, 1); - pixman_f_transform_translate(&ft, NULL, dw, 0); - } +static int pp_list_init; +static struct list_head pp_list; - if (vflip) { - pixman_f_transform_scale(&ft, NULL, 1, -1); - pixman_f_transform_translate(&ft, NULL, 0, dh); - } +static int +_tdm_drm_ioctl(int fd, unsigned long request, void *arg) +{ + int ret; - if (rotate_step > 0) { - int c = 0, s = 0, tx = 0, ty = 0; + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - if (rotate_step == 1) /* 90 degrees */ - s = -1, tx = -dw; - else if (rotate_step == 2) /* 180 degrees */ - c = -1, tx = -dw, ty = -dh; - else /* 270 degrees */ - s = 1, ty = -dh; + return ret; +} - pixman_f_transform_translate(&ft, NULL, tx, ty); - pixman_f_transform_rotate(&ft, NULL, c, s); - } +static int +_tdm_gem_to_dmafd(int drm_fd, int gem_fd) +{ + int ret; + struct drm_prime_handle arg = {0, }; - if (rotate_step % 2 == 0) { - scale_x = (double)sw / dw; - scale_y = (double)sh / dh; - } else { - scale_x = (double)sw / dh; - scale_y = (double)sh / dw; + arg.handle = gem_fd; + ret = _tdm_drm_ioctl(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg); + if (0 != ret) { + return -1; } - - pixman_f_transform_scale(&ft, NULL, scale_x, scale_y); - pixman_f_transform_translate(&ft, NULL, sx, sy); - - pixman_transform_from_pixman_f_transform(&transform, &ft); - pixman_image_set_transform(src_img, &transform); - - pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, dx, dy, dw, dh); - - ret = 1; - -CANT_CONVERT: - if (src_img) - pixman_image_unref(src_img); - if (dst_img) - pixman_image_unref(dst_img); - - return ret; + return arg.fd; } static tdm_error -_tdm_nexell_pp_convert(tdm_nexell_pp_buffer *buffer, tdm_info_pp *info) +_tdm_nexell_pp_convert(tdm_nexell_pp_buffer *buffer, tdm_info_pp *info, int drm_fd, int scaler_fd) { - tbm_surface_info_s src_info, dst_info; - pixman_format_code_t src_format, dst_format; - int sbw, dbw; - int rotate = 0, hflip = 0; - tbm_bo bo = NULL; - int bo_cnt = 0; - int bo_size = 0; - - RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(buffer->src != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(buffer->dst != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER); - - bo_cnt = tbm_surface_internal_get_num_bos(buffer->src); - RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER); - - bo_cnt = tbm_surface_internal_get_num_bos(buffer->dst); - RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER); - - bo = tbm_surface_internal_get_bo(buffer->src, 0); - RETURN_VAL_IF_FAIL(bo != NULL, TDM_ERROR_INVALID_PARAMETER); - - bo_size = tbm_bo_size(bo); - - /* not handle buffers which have 2 more gem handles */ - - memset(&src_info, 0, sizeof(tbm_surface_info_s)); - tbm_surface_map(buffer->src, TBM_OPTION_READ, &src_info); - GOTO_IF_FAIL(src_info.planes[0].ptr != NULL, fail_convert); - - memset(&dst_info, 0, sizeof(tbm_surface_info_s)); - tbm_surface_map(buffer->dst, TBM_OPTION_WRITE, &dst_info); - GOTO_IF_FAIL(dst_info.planes[0].ptr != NULL, fail_convert); - - src_format = _tdm_nexell_pp_pixman_get_format(src_info.format); - GOTO_IF_FAIL(src_format > 0, fail_convert); - dst_format = _tdm_nexell_pp_pixman_get_format(dst_info.format); - GOTO_IF_FAIL(dst_format > 0, fail_convert); - - if (src_info.format == TBM_FORMAT_YUV420) { - if (dst_info.format == TBM_FORMAT_XRGB8888) - dst_format = PIXMAN_x8b8g8r8; - else if (dst_info.format == TBM_FORMAT_ARGB8888) - dst_format = PIXMAN_a8b8g8r8; - else if (dst_info.format == TBM_FORMAT_YVU420) { - TDM_ERR("can't convert %c%c%c%c to %c%c%c%c", - FOURCC_STR(src_info.format), FOURCC_STR(dst_info.format)); - goto fail_convert; - } - } - /* need checking for other formats also? */ - - if (IS_RGB(src_info.format)) - sbw = src_info.planes[0].stride >> 2; - else - sbw = src_info.planes[0].stride; - - if (IS_RGB(dst_info.format)) - dbw = dst_info.planes[0].stride >> 2; - else - dbw = dst_info.planes[0].stride; - - rotate = (info->transform % 4) * 90; - if (info->transform >= TDM_TRANSFORM_FLIPPED) - hflip = 1; - - if (bo_size < src_info.planes[0].stride * src_info.height) { - TDM_WRN("bo size(%d) is smaller than the expected size(%d)", - bo_size, src_info.planes[0].stride * src_info.height); - goto fail_convert; - } - - _tdm_nexell_pp_pixman_convert(PIXMAN_OP_SRC, - src_info.planes[0].ptr, dst_info.planes[0].ptr, - src_format, dst_format, - sbw, src_info.height, - info->src_config.pos.x, info->src_config.pos.y, - info->src_config.pos.w, info->src_config.pos.h, - dbw, dst_info.height, - info->dst_config.pos.x, info->dst_config.pos.y, - info->dst_config.pos.w, info->dst_config.pos.h, - rotate, hflip, 0); - tbm_surface_unmap(buffer->src); - tbm_surface_unmap(buffer->dst); + tdm_nexell_scaler_context ctx; + unsigned int src_y_stride; + unsigned int src_c_stride; + unsigned int dst_y_stride; + unsigned int dst_c_stride; + tbm_bo bo_src = NULL; + tbm_bo bo_dst = NULL; + __u32 handle_src; + __u32 handle_dst; + + bo_src = tbm_surface_internal_get_bo(buffer->src, 0); + RETURN_VAL_IF_FAIL(bo_src != NULL, TDM_ERROR_OPERATION_FAILED); + handle_src = (__u32)tbm_bo_get_handle(bo_src, TBM_DEVICE_DEFAULT).u32; + ctx.src_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_src); + ctx.src_fds[1] = ctx.src_fds[0]; + ctx.src_fds[2] = ctx.src_fds[0]; + + bo_dst = tbm_surface_internal_get_bo(buffer->dst, 0); + RETURN_VAL_IF_FAIL(bo_dst != NULL, TDM_ERROR_OPERATION_FAILED); + handle_dst = (__u32)tbm_bo_get_handle(bo_dst, TBM_DEVICE_DEFAULT).u32; + ctx.dst_fds[0] = _tdm_gem_to_dmafd(drm_fd, handle_dst); + ctx.dst_fds[1] = ctx.dst_fds[0]; + ctx.dst_fds[2] = ctx.dst_fds[0]; + + src_y_stride = ALIGN(info->src_config.size.h, 32); + src_c_stride = ALIGN(src_y_stride >> 1, 16); + dst_y_stride = ALIGN(info->dst_config.size.h, 8); + dst_c_stride = ALIGN(dst_y_stride >> 1, 4); + + ctx.src_plane_num = 1; + ctx.src_width = info->src_config.size.h; + ctx.src_height = info->src_config.size.v; + ctx.src_code = MEDIA_BUS_FMT_YUYV8_2X8; + ctx.src_stride[0] = src_y_stride; + ctx.src_stride[1] = src_c_stride; + ctx.src_stride[2] = src_c_stride; + + ctx.dst_plane_num = 1; + ctx.dst_width = info->dst_config.size.h; + ctx.dst_height = info->dst_config.size.v; + ctx.dst_code = MEDIA_BUS_FMT_YUYV8_2X8; + ctx.dst_stride[0] = dst_y_stride; + ctx.dst_stride[1] = dst_c_stride; + ctx.dst_stride[2] = dst_c_stride; + + ctx.crop.x = info->src_config.pos.x; + ctx.crop.y = info->src_config.pos.y; + ctx.crop.width = info->src_config.pos.w; + ctx.crop.height = info->src_config.pos.h; + + TDM_DBG("pp %p(%d, %d). src(%dx%d, (%d,%d,%d) (%d,%d,%d)) dst(%dx%d, (%d,%d,%d) (%d,%d,%d)) crop(%dx%d, %dx%d)", info, drm_fd, scaler_fd, + ctx.src_width, ctx.src_height, ctx.src_stride[0], ctx.src_stride[1], ctx.src_stride[2], ctx.src_fds[0], ctx.src_fds[1], ctx.src_fds[2], + ctx.dst_width, ctx.dst_height, ctx.dst_stride[0], ctx.dst_stride[1], ctx.dst_stride[2], ctx.dst_fds[0], ctx.dst_fds[1], ctx.dst_fds[2], + ctx.crop.x, ctx.crop.y, ctx.crop.width, ctx.crop.height); + + ioctl(scaler_fd, IOCTL_SCALER_SET_AND_RUN, &ctx); + + close(ctx.src_fds[0]); + close(ctx.dst_fds[0]); return TDM_ERROR_NONE; -fail_convert: - tbm_surface_unmap(buffer->src); - tbm_surface_unmap(buffer->dst); - return TDM_ERROR_OPERATION_FAILED; } tdm_error @@ -258,7 +173,12 @@ tdm_nexell_pp_get_capability(tdm_nexell_data *nexell_data, tdm_caps_pp *caps) return TDM_ERROR_INVALID_PARAMETER; } - caps->capabilities = TDM_PP_CAPABILITY_SYNC; + if (nexell_data->scaler_fd < 0 ) { + TDM_ERR("no scaler_fd. not support pp."); + return TDM_ERROR_BAD_MODULE; + } + + caps->capabilities = TDM_PP_CAPABILITY_SYNC | TDM_PP_CAPABILITY_SCANOUT; caps->format_count = NUM_PP_FORMAT; @@ -275,7 +195,7 @@ tdm_nexell_pp_get_capability(tdm_nexell_data *nexell_data, tdm_caps_pp *caps) caps->min_h = 8; caps->max_w = -1; /* not defined */ caps->max_h = -1; - caps->preferred_align = 16; + caps->preferred_align = 32; return TDM_ERROR_NONE; } @@ -283,7 +203,16 @@ tdm_nexell_pp_get_capability(tdm_nexell_data *nexell_data, tdm_caps_pp *caps) tdm_pp * tdm_nexell_pp_create(tdm_nexell_data *nexell_data, tdm_error *error) { - tdm_nexell_pp_data *pp_data = calloc(1, sizeof(tdm_nexell_pp_data)); + tdm_nexell_pp_data *pp_data = NULL; + + if (nexell_data->scaler_fd < 0 ) { + TDM_ERR("no scaler_fd."); + if (error) + *error = TDM_ERROR_BAD_MODULE; + return NULL; + } + + pp_data = calloc(1, sizeof(tdm_nexell_pp_data)); if (!pp_data) { TDM_ERR("alloc failed"); if (error) @@ -346,12 +275,6 @@ nexell_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) RETURN_VAL_IF_FAIL(src, TDM_ERROR_INVALID_PARAMETER); RETURN_VAL_IF_FAIL(dst, TDM_ERROR_INVALID_PARAMETER); - if (tbm_surface_internal_get_num_bos(src) > 1 || - tbm_surface_internal_get_num_bos(dst) > 1) { - TDM_ERR("can't handle multiple tbm bos"); - return TDM_ERROR_OPERATION_FAILED; - } - buffer = calloc(1, sizeof(tdm_nexell_pp_buffer)); if (!buffer) { TDM_ERR("alloc failed"); @@ -371,13 +294,16 @@ nexell_pp_commit(tdm_pp *pp) { tdm_nexell_pp_data *pp_data = pp; tdm_nexell_pp_buffer *b = NULL, *bb = NULL; + tdm_nexell_data *nexell_data; RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER); + nexell_data = pp_data->nexell_data; + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) { LIST_DEL(&b->link); - _tdm_nexell_pp_convert(b, &pp_data->info); + _tdm_nexell_pp_convert(b, &pp_data->info, nexell_data->drm_fd, nexell_data->scaler_fd); if (pp_data->done_func) pp_data->done_func(pp_data, -- 2.7.4