diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2018-08-09 14:41:43 +0200 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2019-04-25 17:59:27 +0900 |
commit | a3c749e12b4596b5165f74d0ac6b20e69e9081af (patch) | |
tree | 4af6b77b322b4abaaa6e3bd097f8caee1be0ff44 | |
parent | b8a1aeee6b582531b263ebaa6dc0268e1c31e83d (diff) | |
download | libdrm-a3c749e12b4596b5165f74d0ac6b20e69e9081af.tar.gz libdrm-a3c749e12b4596b5165f74d0ac6b20e69e9081af.tar.bz2 libdrm-a3c749e12b4596b5165f74d0ac6b20e69e9081af.zip |
ipptest: add support for newly merged Exynos DRM IPPv2 kernel interface
This patch allows to run ipptool on latest kernels.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Change-Id: I0a1a1a74b199d62b880012d14217d420e08b5e8a
-rw-r--r-- | tests/ipptest/Makefile.am | 3 | ||||
-rw-r--r-- | tests/ipptest/fimc-ipp_v2.c | 274 | ||||
-rw-r--r-- | tests/ipptest/fimc.c | 2 | ||||
-rw-r--r-- | tests/ipptest/fimc.h | 12 | ||||
-rw-r--r-- | tests/ipptest/fimctest.c | 31 |
5 files changed, 316 insertions, 6 deletions
diff --git a/tests/ipptest/Makefile.am b/tests/ipptest/Makefile.am index 7b10df95..59dcae86 100644 --- a/tests/ipptest/Makefile.am +++ b/tests/ipptest/Makefile.am @@ -16,7 +16,8 @@ ipptest_SOURCES = \ fimctest.c \ gem.c \ util.c \ - fimc.c + fimc.c \ + fimc-ipp_v2.c ipptest_LDADD = \ $(top_builddir)/libdrm.la \ diff --git a/tests/ipptest/fimc-ipp_v2.c b/tests/ipptest/fimc-ipp_v2.c new file mode 100644 index 00000000..84c8cea4 --- /dev/null +++ b/tests/ipptest/fimc-ipp_v2.c @@ -0,0 +1,274 @@ +/* + * DRM based IPPv2 test program + * Copyright 2018 Samsung Electronics + * Marek Szyprowski <m.szyprowski@sasmsung.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mman.h> + +#include "exynos_drm.h" +#include "fimctest.h" +#include "gem.h" +#include "util.h" +#include "fimc.h" + + +#include "drm_fourcc.h" +#include "drm_mode.h" +#include "libkms.h" +#include "internal.h" + +struct exynos_drm_ipp_std_task { + struct drm_exynos_ipp_task_buffer buf[2]; + struct drm_exynos_ipp_task_rect rect[2]; + struct drm_exynos_ipp_task_transform transform; +} __packed; + +void fimc_v2_m2m_set_mode(struct device *dev, struct connector *c, int count, + enum drm_exynos_degree degree, enum drm_exynos_ipp_cmd_m2m display, + long int *usec) +{ + struct drm_exynos_sz def_sz; + struct drm_exynos_sz src_sz; + void *usr_addr1[MAX_BUF], *usr_addr2[MAX_BUF]; + uint32_t handles[4], pitches[4], offsets[4] = {0}; + struct kms_bo *bo_src[MAX_BUF] = { NULL, }, *bo_dst = NULL; + struct pipe_arg pipe; + unsigned int fb_id_dst; + int ret, i, j; + + struct timeval begin, end; + char filename[80]; + + struct exynos_drm_ipp_std_task task = { 0 }; + struct drm_exynos_ioctl_ipp_commit arg = { 0 }; + + src_sz = c[0].src_sz; + printf("source image resolution [%ux%u]\n", src_sz.hsize, src_sz.vsize); + + dev->mode.width = 0; + dev->mode.height = 0; + + /* For crtc and mode */ + for (i = 0; i < count; i++) { + ret = pipe_find_crtc_and_mode(dev, &pipe, &c[i]); + if (ret < 0) + continue; + + dev->mode.width += pipe.mode->hdisplay; + if (dev->mode.height < pipe.mode->vdisplay) + dev->mode.height = pipe.mode->vdisplay; + } + + for (i = 0; i < MAX_BUF; i++) { + /* For source buffer */ + bo_src[i] = util_kms_gem_create_mmap(dev->kms, DRM_FORMAT_XRGB8888, + src_sz.hsize, src_sz.vsize, + handles, pitches, offsets); + if (!bo_src[i]) + goto err_ipp_src_buff_close; + + usr_addr1[i] = bo_src[i]->ptr; + } + + /* Create test Image + * Display is YUV422 format, file is RGB888 format + */ + if (display == IPP_CMD_M2M_DISPLAY) + util_draw_buffer_yuv(usr_addr1, src_sz.hsize, src_sz.vsize); + else + fill_smpte_rgb32(usr_addr1[0], src_sz.hsize, src_sz.vsize, + src_sz.hsize * 4); + + /* For destination buffer */ + bo_dst = util_kms_gem_create_mmap(dev->kms, DRM_FORMAT_XRGB8888, + dev->mode.width, dev->mode.height, + handles, pitches, offsets); + if (!bo_dst) + goto err_ipp_src_buff_close; + + usr_addr2[0] = bo_dst->ptr; + + def_sz.hsize = dev->mode.width; + def_sz.vsize = dev->mode.height; + + /* src buf */ + task.buf[0].id = DRM_EXYNOS_IPP_TASK_BUFFER | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE; + task.buf[0].width = src_sz.hsize; + task.buf[0].height = src_sz.vsize; + task.buf[0].fourcc = (display == IPP_CMD_M2M_FILE) ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_YUV422; + for (i = 0; i < MAX_BUF; i++) + task.buf[0].gem_id[i] = bo_src[i]->handle; + + /* dst buf */ + task.buf[1].id = DRM_EXYNOS_IPP_TASK_BUFFER | DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION; + task.buf[1].fourcc = DRM_FORMAT_XRGB8888; + task.buf[1].width = def_sz.hsize; + task.buf[1].height = def_sz.vsize; + task.buf[1].gem_id[0] = bo_dst->handle; + task.buf[1].pitch[0] = bo_dst->pitch; + task.buf[1].offset[0] = bo_dst->offset; + + task.rect[0].id = DRM_EXYNOS_IPP_TASK_RECTANGLE | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE; + task.rect[0].x = 0; + task.rect[0].y = 0; + task.rect[0].w = src_sz.hsize; + task.rect[0].h = src_sz.vsize; + + task.rect[1].id = DRM_EXYNOS_IPP_TASK_RECTANGLE | DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION; + task.rect[1].x = 0; + task.rect[1].y = 0; + task.rect[1].w = def_sz.hsize; + task.rect[1].h = def_sz.vsize; + + task.transform.id = DRM_EXYNOS_IPP_TASK_TRANSFORM; + if (degree == EXYNOS_DRM_DEGREE_0) + task.transform.rotation = DRM_MODE_ROTATE_0; + else if (degree == EXYNOS_DRM_DEGREE_90) + task.transform.rotation = DRM_MODE_ROTATE_90; + else if (degree == EXYNOS_DRM_DEGREE_180) + task.transform.rotation = DRM_MODE_ROTATE_180; + else if (degree == EXYNOS_DRM_DEGREE_270) + task.transform.rotation = DRM_MODE_ROTATE_270; + else { + fprintf(stderr, "invalid rotation value\n"); + goto err_ipp_close; + } + + /* prepare ioctl data */ + arg.flags = 0; /* BLOCKING call, no event */ + arg.ipp_id = 0; /* use first IPP module available */ + arg.params_size = sizeof(task); + arg.params_ptr = (unsigned long)(&task); + arg.user_data = 0; /* unused */ + + /* Display OR File */ + switch (display) { + case IPP_CMD_M2M_FILE: + + /* For src image write file */ + sprintf(filename, RESULT_PATH "fimc_m2m_org_src.bmp"); + util_write_bmp(filename, usr_addr1[0], + src_sz.hsize, src_sz.vsize); + + for (j = 0; j < MAX_LOOP; j++) { + + gettimeofday(&begin, NULL); + ret = ioctl(dev->fd, DRM_IOCTL_EXYNOS_IPP_COMMIT, &arg); + if (ret) { + fprintf(stderr, "failed to process image\n"); + goto err_ipp_close; + } + + gettimeofday(&end, NULL); + + usec[j] = (end.tv_sec - begin.tv_sec) * 1000000 + + (end.tv_usec - begin.tv_usec); + + sprintf(filename, RESULT_PATH "fimc_m2m_dst%d.bmp", j); + util_write_bmp(filename, usr_addr2[0], def_sz.hsize, def_sz.vsize); + } + break; + + case IPP_CMD_M2M_DISPLAY: + /* Add fb2 dst */ + ret = drmModeAddFB2(dev->fd, dev->mode.width, dev->mode.height, + pipe.fourcc, handles, pitches, + offsets, &fb_id_dst, 0); + if (ret) { + fprintf(stderr, "failed to add fb (%ux%u):%d\n", + dev->mode.width, dev->mode.height, + errno); + goto err_ipp_close; + } + + for (j = 0; j < 2; j++) { + + gettimeofday(&begin, NULL); + ret = ioctl(dev->fd, DRM_IOCTL_EXYNOS_IPP_COMMIT, &arg); + if (ret) { + fprintf(stderr, "failed to process image\n"); + goto err_ipp_close; + } + gettimeofday(&end, NULL); + usec[j] = (end.tv_sec - begin.tv_sec) * 1000000 + + (end.tv_usec - begin.tv_usec); + + if (j == 0) { + /* Set crtc */ + ret = drmModeSetCrtc(dev->fd, pipe.crtc->crtc->crtc_id, + fb_id_dst, 0, 0, pipe.con_ids, + pipe.num_cons, pipe.mode); + if (ret) { + fprintf(stderr, "failed to set crtc: %d\n", errno); + goto err_ipp_close; + } + /* reset rotation for the next frame */ + task.transform.rotation = DRM_MODE_ROTATE_0; + } else { + /* Set Flip */ + ret = drmModePageFlip(dev->fd, pipe.crtc->crtc->crtc_id, + fb_id_dst, 0, &pipe); + if (ret) { + fprintf(stderr, "failed to page flip: %d\n", + errno); + goto err_ipp_close; + } + } + + getchar(); + } + break; + case IPP_CMD_M2M_NONE: + break; + } + +err_ipp_close: +err_ipp_dst_buff_close: + util_kms_gem_destroy_mmap(&bo_dst); +err_ipp_src_buff_close: + /* Close source buffer */ + for (i = 0; i < MAX_BUF; i++) { + ret = util_kms_gem_destroy_mmap(&bo_src[i]); + if (ret < 0) + break; + } +} + +void fimc_v2_wb_set_mode(struct connector *c, int count, int page_flip, + long int *usec) +{ + fprintf(stderr, "not supported.\n"); +} + +void fimc_v2_output_set_mode(struct connector *c, int count, int page_flip, + long int *usec) +{ + fprintf(stderr, "not supported.\n"); +} diff --git a/tests/ipptest/fimc.c b/tests/ipptest/fimc.c index 16b1d7a8..7bd315e0 100644 --- a/tests/ipptest/fimc.c +++ b/tests/ipptest/fimc.c @@ -332,7 +332,7 @@ struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe) return &dev->resources->crtcs[crtc_idx - 1]; } -static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe, +int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe, struct connector *c) { drmModeModeInfo *mode = NULL; diff --git a/tests/ipptest/fimc.h b/tests/ipptest/fimc.h index 85261958..b758d941 100644 --- a/tests/ipptest/fimc.h +++ b/tests/ipptest/fimc.h @@ -8,7 +8,19 @@ void fimc_wb_set_mode(struct connector *c, int count, int page_flip, long int *usec); void fimc_output_set_mode(struct connector *c, int count, int page_flip, long int *usec); + +void fimc_v2_m2m_set_mode(struct device *dev, struct connector *c, int count, + enum drm_exynos_degree degree, enum drm_exynos_ipp_cmd_m2m display, + long int *usec); +void fimc_v2_wb_set_mode(struct connector *c, int count, int page_flip, + long int *usec); +void fimc_v2_output_set_mode(struct connector *c, int count, int page_flip, + long int *usec); + struct resources *get_resources(struct device *dev); void free_resources(struct resources *res); +int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe, + struct connector *c); + #endif diff --git a/tests/ipptest/fimctest.c b/tests/ipptest/fimctest.c index f044bb54..f6981de1 100644 --- a/tests/ipptest/fimctest.c +++ b/tests/ipptest/fimctest.c @@ -383,6 +383,7 @@ static void usage(char *name) int main(int argc, char **argv) { + drmVersionPtr drm_version; struct device dev; int c; int operations = 0, encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; @@ -391,6 +392,7 @@ int main(int argc, char **argv) int test_vsync = 0; const char *module = "exynos"; int i, count = 0; + int use_ippv2 = 0; struct connector con_args[2]; memset(&dev, 0, sizeof(dev)); @@ -470,6 +472,17 @@ int main(int argc, char **argv) dev.fd = fd; + drm_version = drmGetVersion(fd); + if (!drm_version) { + fprintf(stderr, "no drm version: %m"); + return -1; + } else { + if (drm_version->version_major > 1 || + (drm_version->version_major == 1 && drm_version->version_minor >= 1)) + use_ippv2 = 1; + drmFreeVersion(drm_version); + } + dev.resources = get_resources(&dev); if (!dev.resources) { fprintf(stderr, "get_resources failed: %d\n", errno); @@ -503,15 +516,25 @@ int main(int argc, char **argv) break; } - fimc_m2m_set_mode(&dev, con_args, count, - degree, display, usec); + if (use_ippv2) + fimc_v2_m2m_set_mode(&dev, con_args, count, + degree, display, usec); + else + fimc_m2m_set_mode(&dev, con_args, count, + degree, display, usec); kms_destroy(&dev.kms); break; case 1: - fimc_wb_set_mode(con_args, count, test_vsync, usec); + if (use_ippv2) + fimc_v2_wb_set_mode(con_args, count, test_vsync, usec); + else + fimc_wb_set_mode(con_args, count, test_vsync, usec); break; case 2: - fimc_output_set_mode(con_args, count, test_vsync, usec); + if (use_ippv2) + fimc_v2_output_set_mode(con_args, count, test_vsync, usec); + else + fimc_output_set_mode(con_args, count, test_vsync, usec); break; default: break; |