summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-12-20 21:09:40 +0100
committerThierry Reding <treding@nvidia.com>2018-05-02 17:29:39 +0200
commit7217010e438d52501ec154050cc0792f30b50161 (patch)
tree28cf85ba7093b7feb0f8a87514cd375cab74cee9
parent859e8aa396d808884e29f44fb2d761b042ef2a41 (diff)
tests: kms: Add planes blending test
Note that this is kind of Tegra specific right now since it assumes the existence of three planes and that the planes are in the Tegra Z-order, which means the first plane is lowest and the third plane is highest. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--tests/kms/Makefile.am5
-rw-r--r--tests/kms/kms-planes-blend.c342
2 files changed, 347 insertions, 0 deletions
diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am
index 6645af7a..beb679b2 100644
--- a/tests/kms/Makefile.am
+++ b/tests/kms/Makefile.am
@@ -21,14 +21,19 @@ libkms_test_la_LIBADD = \
if HAVE_INSTALL_TESTS
bin_PROGRAMS = \
+ kms-planes-blend \
kms-steal-crtc \
kms-universal-planes
else
noinst_PROGRAMS = \
+ kms-planes-blend \
kms-steal-crtc \
kms-universal-planes
endif
+kms_planes_blend_SOURCES = kms-planes-blend.c
+kms_planes_blend_LDADD = libkms-test.la $(CAIRO_LIBS)
+
kms_steal_crtc_SOURCES = kms-steal-crtc.c
kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS)
diff --git a/tests/kms/kms-planes-blend.c b/tests/kms/kms-planes-blend.c
new file mode 100644
index 00000000..c2cc232d
--- /dev/null
+++ b/tests/kms/kms-planes-blend.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright © 2017 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 (including the next
+ * paragraph) 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <drm_fourcc.h>
+#include "xf86drm.h"
+
+#include "util/common.h"
+#include "libkms-test.h"
+
+#define TEST_PER_PLANE_FORMAT 1
+
+#ifndef TEST_PER_PLANE_FORMAT
+static const uint32_t formats[] = {
+ //DRM_FORMAT_XRGB8888,
+ //DRM_FORMAT_RGB565,
+ //DRM_FORMAT_RGBA8888,
+ //DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_ARGB8888,
+ //DRM_FORMAT_ABGR8888,
+ //DRM_FORMAT_ARGB1555,
+ //DRM_FORMAT_BGRA5551,
+};
+
+static uint32_t choose_format(struct kms_plane *plane)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++)
+ if (kms_plane_supports_format(plane, formats[i]))
+ return formats[i];
+
+ return 0;
+}
+#endif
+
+struct kms_color {
+ uint64_t value;
+ size_t size;
+};
+
+static int kms_color_set(struct kms_color *color, uint32_t format,
+ uint16_t red, uint16_t green, uint16_t blue,
+ uint16_t alpha)
+{
+ switch (format) {
+ case DRM_FORMAT_ARGB1555:
+ color->value = ((alpha >> 15) & 0x1) << 15 | ((red >> 11) & 0x1f) << 10 | ((green >> 11) & 0x1f) << 5 | ((blue >> 11) & 0x1f);
+ color->size = 2;
+ return 0;
+
+ case DRM_FORMAT_BGRA5551:
+ color->value = ((blue >> 11) & 0x1f) << 11 | ((green >> 11) & 0x1f) << 6 | ((red >> 11) & 0x1f) << 1 | ((alpha >> 15) & 0x1);
+ color->size = 2;
+ return 0;
+
+ case DRM_FORMAT_RGB565:
+ color->value = ((red >> 11) & 0x1f) << 11 |
+ ((green >> 10) & 0x3f) << 5 |
+ ((blue >> 11) & 0x1f);
+ color->size = 2;
+ return 0;
+
+ case DRM_FORMAT_RGBA8888:
+ color->value = ((red >> 8) & 0xff) << 24 | ((green >> 8) & 0xff) << 16 |
+ ((blue >> 8) & 0xff) << 8 | ((alpha >> 8) & 0xff);
+ color->size = 4;
+ return 0;
+
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ color->value = ((alpha >> 8) & 0xff) << 24 | ((red >> 8) & 0xff) << 16 |
+ ((green >> 8) & 0xff) << 8 | ((blue >> 8) & 0xff);
+ color->size = 4;
+ return 0;
+
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ color->value = ((alpha >> 8) & 0xff) << 24 | ((blue >> 8) & 0xff) << 16 |
+ ((green >> 8) & 0xff) << 8 | ((red >> 8) & 0xff);
+ color->size = 4;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void kms_framebuffer_clear(struct kms_framebuffer *fb,
+ const struct kms_color *color)
+{
+ unsigned int i, j;
+ void *ptr;
+ int err;
+
+ err = kms_framebuffer_map(fb, &ptr);
+ if (err < 0) {
+ fprintf(stderr, "kms_framebuffer_map() failed: %s\n", strerror(-err));
+ return;
+ }
+
+ printf("clearing with %" PRIx64 "\n", color->value);
+
+ for (j = 0; j < fb->height; j++) {
+ for (i = 0; i < fb->width; i++) {
+ switch (color->size) {
+ case 4:
+ ((uint32_t *)ptr)[j * fb->width + i] = (uint32_t)color->value;
+ break;
+
+ case 2:
+ ((uint16_t *)ptr)[j * fb->width + i] = 0xffff;//(uint16_t)color->value;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ kms_framebuffer_unmap(fb);
+}
+
+int main(int argc, char *argv[])
+{
+ static const char opts[] = "chopv";
+ static struct option options[] = {
+ { "help", 0, 0, 'h' },
+ { "verbose", 0, 0, 'v' },
+ { 0, 0, 0, 0 },
+ };
+ struct kms_framebuffer *fbs[3];
+ struct kms_device *device;
+ bool verbose = false;
+ unsigned int size;
+ unsigned int i;
+ int opt, idx;
+ int fd, err;
+
+ while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) {
+ switch (opt) {
+ case 'h':
+ break;
+
+ case 'v':
+ verbose = true;
+ break;
+
+ default:
+ printf("unknown option \"%c\"\n", opt);
+ return 1;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(argv[optind], O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open() failed: %m\n");
+ return 1;
+ }
+
+ err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ if (err < 0) {
+ fprintf(stderr, "drmSetClientCap() failed: %d\n", err);
+ return 1;
+ }
+
+ device = kms_device_open(fd);
+ if (!device)
+ return 1;
+
+ if (verbose) {
+ printf("Screens: %u\n", device->num_screens);
+
+ for (i = 0; i < device->num_screens; i++) {
+ struct kms_screen *screen = device->screens[i];
+ const char *status = "disconnected";
+
+ if (screen->connected)
+ status = "connected";
+
+ printf(" %u: %x\n", i, screen->id);
+ printf(" Status: %s\n", status);
+ printf(" Name: %s\n", screen->name);
+ printf(" Resolution: %ux%u\n", screen->width,
+ screen->height);
+ }
+
+ printf("Planes: %u\n", device->num_planes);
+
+ for (i = 0; i < device->num_planes; i++) {
+ struct kms_plane *plane = device->planes[i];
+ const char *type = NULL;
+
+ switch (plane->type) {
+ case DRM_PLANE_TYPE_OVERLAY:
+ type = "overlay";
+ break;
+
+ case DRM_PLANE_TYPE_PRIMARY:
+ type = "primary";
+ break;
+
+ case DRM_PLANE_TYPE_CURSOR:
+ type = "cursor";
+ break;
+ }
+
+ printf(" %u: %p\n", i, plane);
+ printf(" ID: %x\n", plane->id);
+ printf(" CRTC: %x\n", plane->crtc->id);
+ printf(" Type: %x (%s)\n", plane->type, type);
+ }
+ }
+
+ size = device->screens[0]->height / 2;
+
+ for (i = 0; i < 3; i++) {
+#ifndef TEST_PER_PLANE_FORMAT
+ struct kms_plane *plane = device->planes[i];
+#endif
+ const struct {
+ uint32_t format;
+ uint16_t red;
+ uint16_t green;
+ uint16_t blue;
+ uint16_t alpha;
+ } colors[3] = {
+ { DRM_FORMAT_XRGB8888, 0xffff, 0x0000, 0x0000, 0x7fff },
+ { DRM_FORMAT_ARGB8888, 0x0000, 0xffff, 0x0000, 0x7fff },
+ { DRM_FORMAT_XRGB8888, 0x0000, 0x0000, 0xffff, 0x7fff },
+ };
+ struct kms_color color;
+ uint32_t format;
+
+#ifndef TEST_PER_PLANE_FORMAT
+ format = choose_format(plane);
+ if (!format) {
+ fprintf(stderr, "no matching format found\n");
+ return 1;
+ }
+#else
+ format = colors[i].format;
+#endif
+
+ fbs[i] = kms_framebuffer_create(device, size, size, format);
+ if (!fbs[i]) {
+ fprintf(stderr, "failed to create framebuffer\n");
+ return 1;
+ }
+
+ kms_color_set(&color, format, colors[i].red, colors[i].green,
+ colors[i].blue, colors[i].alpha);
+ kms_framebuffer_clear(fbs[i], &color);
+ }
+
+ for (i = 0; i < 3; i++) {
+ struct kms_plane *plane = device->planes[i];
+ const struct {
+ int x;
+ int y;
+ } position[3] = {
+ { -(size / 4), -(size / 4) },
+ { (size / 4), -(size / 4) },
+ { 0, (size / 4) },
+ };
+ unsigned int x, y;
+
+ x = ((device->screens[0]->width - size) / 2) + position[i].x;
+ y = ((device->screens[0]->height - size) / 2) + position[i].y;
+
+ kms_plane_set(plane, fbs[i], x, y);
+ }
+
+ while (1) {
+ struct timeval timeout = { 1, 0 };
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+
+ err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout);
+ if (err < 0) {
+ fprintf(stderr, "select() failed: %m\n");
+ break;
+ }
+
+ /* timeout */
+ if (err == 0)
+ continue;
+
+ if (FD_ISSET(STDIN_FILENO, &fds))
+ break;
+ }
+
+ for (i = 0; i < 3; i++)
+ kms_framebuffer_free(fbs[i]);
+
+ kms_device_close(device);
+ close(fd);
+
+ return 0;
+}