diff options
-rw-r--r-- | tests/tegra/Makefile.am | 7 | ||||
-rw-r--r-- | tests/tegra/meson.build | 9 | ||||
-rw-r--r-- | tests/tegra/vic-flip.c | 353 |
3 files changed, 367 insertions, 2 deletions
diff --git a/tests/tegra/Makefile.am b/tests/tegra/Makefile.am index ce7f1be3..99ad39fd 100644 --- a/tests/tegra/Makefile.am +++ b/tests/tegra/Makefile.am @@ -32,14 +32,16 @@ bin_PROGRAMS = \ tegra-gr2d-fill \ tegra-syncpt-wait \ tegra-vic-clear \ - tegra-vic-blit + tegra-vic-blit \ + tegra-vic-flip else noinst_PROGRAMS = \ tegra-openclose \ tegra-gr2d-fill \ tegra-syncpt-wait \ tegra-vic-clear \ - tegra-vic-blit + tegra-vic-blit \ + tegra-vic-flip endif tegra_openclose_SOURCES = openclose.c @@ -47,3 +49,4 @@ tegra_gr2d_fill_SOURCES = gr2d-fill.c tegra_syncpt_wait_SOURCES = syncpt-wait.c tegra_vic_clear_SOURCES = vic-clear.c tegra_vic_blit_SOURCES = vic-blit.c +tegra_vic_flip_SOURCES = vic-flip.c diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build index ce47ce78..a0bd7652 100644 --- a/tests/tegra/meson.build +++ b/tests/tegra/meson.build @@ -85,3 +85,12 @@ vic_blit = executable( link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], install : with_install_tests, ) + +vic_flip = executable( + 'tegra-vic-flip', + files('vic-flip.c'), + include_directories : [inc_root, inc_drm, inc_tegra], + c_args : warn_c_args, + link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], + install : with_install_tests, +) diff --git a/tests/tegra/vic-flip.c b/tests/tegra/vic-flip.c new file mode 100644 index 00000000..57453b3b --- /dev/null +++ b/tests/tegra/vic-flip.c @@ -0,0 +1,353 @@ +/* + * Copyright © 2018 NVIDIA Corporation + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "tegra.h" + +#include "host1x.h" +#include "vic.h" + +/* clear output image to red */ +static int clear(struct vic *vic, struct drm_tegra_channel *channel, + struct drm_tegra_bo *config, struct drm_tegra_bo *hist, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + void *ptr; + int err; + + err = drm_tegra_job_new(&job, channel); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_new(&pushbuf, job); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_prepare(pushbuf, 32); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(config, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %d\n", err); + return err; + } + + vic->ops->clear(ptr, output, 1023, 0, 0, 1023); + drm_tegra_bo_unmap(config); + + err = vic->ops->execute(pushbuf, config, hist, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync(pushbuf, 0, 1, DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, 1000); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_pushbuf_free(pushbuf); + drm_tegra_job_free(job); + + return 0; +} + +/* fill bottom half of image to blue */ +static int fill(struct vic *vic, struct drm_tegra_channel *channel, + struct drm_tegra_bo *config, struct drm_tegra_bo *hist, + struct vic_image *output) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + void *ptr; + int err; + + err = drm_tegra_job_new(&job, channel); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_new(&pushbuf, job); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_prepare(pushbuf, 32); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(config, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %d\n", err); + return err; + } + + vic->ops->fill(ptr, output, 0, output->height / 2, output->width - 1, + output->height -1, 0, 0, 1023, 1023); + drm_tegra_bo_unmap(config); + + err = vic->ops->execute(pushbuf, config, hist, output, NULL, 0); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync(pushbuf, 0, 1, DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, 1000); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_pushbuf_free(pushbuf); + drm_tegra_job_free(job); + + return 0; +} + +/* flip image vertically */ +static int flip(struct vic *vic, struct drm_tegra_channel *channel, + struct drm_tegra_bo *config, struct drm_tegra_bo *hist, + struct vic_image *output, struct vic_image *input) +{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_job *job; + void *ptr; + int err; + + err = drm_tegra_job_new(&job, channel); + if (err < 0) { + fprintf(stderr, "failed to create job: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_new(&pushbuf, job); + if (err < 0) { + fprintf(stderr, "failed to create push buffer: %s\n", strerror(-err)); + return 1; + } + + err = drm_tegra_pushbuf_prepare(pushbuf, 32); + if (err < 0) { + fprintf(stderr, "failed to prepare push buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(config, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map configuration structure: %d\n", err); + return err; + } + + vic->ops->flip(ptr, output, input); + drm_tegra_bo_unmap(config); + + err = vic->ops->execute(pushbuf, config, hist, output, &input, 1); + if (err < 0) { + fprintf(stderr, "failed to execute operation: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_pushbuf_sync(pushbuf, 0, 1, DRM_TEGRA_SYNC_COND_OP_DONE); + if (err < 0) { + fprintf(stderr, "failed to push syncpoint: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_submit(job, 1000); + if (err < 0) { + fprintf(stderr, "failed to submit job: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_job_wait(job); + if (err < 0) { + fprintf(stderr, "failed to wait for job: %s\n", strerror(-err)); + return err; + } + + drm_tegra_pushbuf_free(pushbuf); + drm_tegra_job_free(job); + + return 0; +} + +int main(int argc, char *argv[]) +{ + const unsigned int format = VIC_PIXEL_FORMAT_A8R8G8B8; + const unsigned int kind = VIC_BLK_KIND_PITCH; + const unsigned int width = 16, height = 16; + const char *device = "/dev/dri/renderD128"; + struct drm_tegra_bo *config, *hist; + struct drm_tegra_channel *channel; + struct vic_image *input, *output; + unsigned int num_syncpoints; + struct drm_tegra *drm; + unsigned int version; + struct vic *vic; + int fd, err; + void *ptr; + + if (argc > 1) + device = argv[1]; + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr, "open() failed: %s\n", strerror(errno)); + return 1; + } + + err = drm_tegra_new(&drm, fd); + if (err < 0) { + fprintf(stderr, "failed to open Tegra device: %s\n", strerror(-err)); + close(fd); + return 1; + } + + err = vic_image_new(&input, drm, width, height, format, kind); + if (err < 0) { + fprintf(stderr, "failed to create input image: %d\n", err); + return 1; + } + + err = vic_image_new(&output, drm, width, height, format, kind); + if (err < 0) { + fprintf(stderr, "failed to create output image: %d\n", err); + return 1; + } + + err = drm_tegra_bo_new(&config, drm, 0, 16384); + if (err < 0) { + fprintf(stderr, "failed to create configuration structure: %d\n", err); + return 1; + } + + err = drm_tegra_bo_new(&hist, drm, 0, 4096); + if (err < 0) { + fprintf(stderr, "failed to allocate history buffer: %s\n", strerror(-err)); + return err; + } + + err = drm_tegra_bo_map(hist, &ptr); + if (err < 0) { + fprintf(stderr, "failed to map history buffer: %s\n", strerror(-err)); + return err; + } + + memset(ptr, 0, 4096); + drm_tegra_bo_unmap(hist); + + err = drm_tegra_channel_open(&channel, drm, DRM_TEGRA_VIC); + if (err < 0) { + fprintf(stderr, "failed to open channel to VIC: %s\n", strerror(-err)); + return 1; + } + + num_syncpoints = drm_tegra_channel_get_syncpoints(channel); + version = drm_tegra_channel_get_version(channel); + printf("channel opened: %u syncpoints\n", num_syncpoints); + printf("version: %08x\n", version); + + err = vic_new(&vic, version); + if (err < 0) { + fprintf(stderr, "failed to create VIC: %s\n", strerror(-err)); + return 1; + } + + err = clear(vic, channel, config, hist, input); + if (err < 0) { + fprintf(stderr, "failed to clear image: %s\n", strerror(-err)); + return 1; + } + + err = fill(vic, channel, config, hist, input); + if (err < 0) { + fprintf(stderr, "failed to fill rectangle: %s\n", strerror(-err)); + return 1; + } + + err = flip(vic, channel, config, hist, output, input); + if (err < 0) { + fprintf(stderr, "failed to flip image: %s\n", strerror(-err)); + return 1; + } + + printf("input: %ux%u\n", input->width, input->height); + vic_image_dump(input, stdout); + + printf("output: %ux%u\n", output->width, output->height); + vic_image_dump(output, stdout); + + drm_tegra_bo_unref(hist); + drm_tegra_bo_unref(config); + vic_image_free(output); + vic_image_free(input); + + vic_free(vic); + drm_tegra_channel_close(channel); + drm_tegra_close(drm); + close(fd); + + return 0; +} |