support nexell pp 72/166872/3
authorJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 12 Jan 2018 07:42:27 +0000 (16:42 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Mon, 15 Jan 2018 10:02:08 +0000 (19:02 +0900)
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 <jk0430.kim@samsung.com>
packaging/libtdm-nexell.spec
src/tdm_nexell.c
src/tdm_nexell.h
src/tdm_nexell_pp.c

index a797223..b021269 100644 (file)
@@ -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
index 0f1984b..f905f82 100644 (file)
@@ -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
index 4290cc1..30111b2 100644 (file)
@@ -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;
index 2a84266..50aa56f 100644 (file)
@@ -2,10 +2,10 @@
 #include "config.h"
 #endif
 
-#include <pixman.h>
+#include <linux/media-bus-format.h>
+#include <errno.h>
 
 #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,