diff options
author | Thierry Reding <treding@nvidia.com> | 2018-05-02 17:01:10 +0200 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2018-05-04 17:50:43 +0200 |
commit | 6c703c5a0e902ad7d7759cc91a4bbe36f00e7a31 (patch) | |
tree | 088d0fbc14caf357b20509b186307e50a418ed9e | |
parent | ad81efc85db6ad8c6bab279d58bf9ec5d37877a0 (diff) |
tests: tegra: Add VIC blit test
This test will attempt to use the VIC to blit from one surface to
another.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | tests/tegra/Makefile.am | 7 | ||||
-rw-r--r-- | tests/tegra/meson.build | 9 | ||||
-rw-r--r-- | tests/tegra/vic-blit.c | 361 |
3 files changed, 375 insertions, 2 deletions
diff --git a/tests/tegra/Makefile.am b/tests/tegra/Makefile.am index 74725416..ce7f1be3 100644 --- a/tests/tegra/Makefile.am +++ b/tests/tegra/Makefile.am @@ -31,16 +31,19 @@ bin_PROGRAMS = \ tegra-openclose \ tegra-gr2d-fill \ tegra-syncpt-wait \ - tegra-vic-clear + tegra-vic-clear \ + tegra-vic-blit else noinst_PROGRAMS = \ tegra-openclose \ tegra-gr2d-fill \ tegra-syncpt-wait \ - tegra-vic-clear + tegra-vic-clear \ + tegra-vic-blit endif tegra_openclose_SOURCES = openclose.c 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 diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build index 46c14a18..ce47ce78 100644 --- a/tests/tegra/meson.build +++ b/tests/tegra/meson.build @@ -76,3 +76,12 @@ vic_clear = executable( link_with : [libdrm, libdrm_tegra, libdrm_test, libdrm_test_tegra], install : with_install_tests, ) + +vic_blit = executable( + 'tegra-vic-blit', + files('vic-blit.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-blit.c b/tests/tegra/vic-blit.c new file mode 100644 index 00000000..dc583439 --- /dev/null +++ b/tests/tegra/vic-blit.c @@ -0,0 +1,361 @@ +/* + * 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: %s\n", + strerror(-err)); + return err; + } + + vic->ops->clear(ptr, output, 1023, 1023, 0, 0); + 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: %s\n", + strerror(-err)); + return err; + } + + vic->ops->fill(ptr, output, 0, output->height / 2, output->width - 1, + output->height -1, 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; +} + +/* blit image */ +static int blit(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->blit(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_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 = blit(vic, channel, config, hist, output, input); + if (err < 0) { + fprintf(stderr, "failed to blit 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; +} |