OSDN Git Service

tests: Add libkms-test library
authorThierry Reding <treding@nvidia.com>
Wed, 9 Dec 2015 17:37:42 +0000 (18:37 +0100)
committerEmil Velikov <emil.l.velikov@gmail.com>
Fri, 18 Dec 2015 17:44:05 +0000 (17:44 +0000)
This library contains abstractions for KMS that help remove the need for
a lot of boilerplate in KMS test programs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
configure.ac
tests/Makefile.am
tests/kms/Makefile.am [new file with mode: 0644]
tests/kms/libkms-test-crtc.c [new file with mode: 0644]
tests/kms/libkms-test-device.c [new file with mode: 0644]
tests/kms/libkms-test-framebuffer.c [new file with mode: 0644]
tests/kms/libkms-test-plane.c [new file with mode: 0644]
tests/kms/libkms-test-screen.c [new file with mode: 0644]
tests/kms/libkms-test.h [new file with mode: 0644]

index ca6cbf4..0c66dfc 100644 (file)
@@ -499,6 +499,7 @@ AC_CONFIG_FILES([
        tests/Makefile
        tests/modeprint/Makefile
        tests/modetest/Makefile
+       tests/kms/Makefile
        tests/kmstest/Makefile
        tests/proptest/Makefile
        tests/radeon/Makefile
index 7ffc076..58feb12 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = util modeprint proptest modetest vbltest
+SUBDIRS = util kms modeprint proptest modetest vbltest
 
 if HAVE_LIBKMS
 SUBDIRS += kmstest
diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am
new file mode 100644 (file)
index 0000000..da46421
--- /dev/null
@@ -0,0 +1,20 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/include/drm \
+       -I$(top_srcdir)/tests \
+       -I$(top_srcdir)
+
+AM_CFLAGS = \
+       $(WARN_CFLAGS)
+
+noinst_LTLIBRARIES = libkms-test.la
+
+libkms_test_la_SOURCES = \
+       libkms-test.h \
+       libkms-test-crtc.c \
+       libkms-test-device.c \
+       libkms-test-framebuffer.c \
+       libkms-test-plane.c \
+       libkms-test-screen.c
+
+libkms_test_la_LIBADD = \
+       $(top_builddir)/libdrm.la
diff --git a/tests/kms/libkms-test-crtc.c b/tests/kms/libkms-test-crtc.c
new file mode 100644 (file)
index 0000000..3adb490
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2014 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 "libkms-test.h"
+
+struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id)
+{
+       struct kms_crtc *crtc;
+
+       crtc = calloc(1, sizeof(*crtc));
+       if (!crtc)
+               return NULL;
+
+       crtc->device = device;
+       crtc->id = id;
+
+       return crtc;
+}
+
+void kms_crtc_free(struct kms_crtc *crtc)
+{
+       free(crtc);
+}
diff --git a/tests/kms/libkms-test-device.c b/tests/kms/libkms-test-device.c
new file mode 100644 (file)
index 0000000..53c7349
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright © 2014 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util/common.h"
+#include "libkms-test.h"
+
+static const char *const connector_names[] = {
+       "Unknown",
+       "VGA",
+       "DVI-I",
+       "DVI-D",
+       "DVI-A",
+       "Composite",
+       "SVIDEO",
+       "LVDS",
+       "Component",
+       "9PinDIN",
+       "DisplayPort",
+       "HDMI-A",
+       "HDMI-B",
+       "TV",
+       "eDP",
+       "Virtual",
+       "DSI",
+};
+
+static void kms_device_probe_screens(struct kms_device *device)
+{
+       unsigned int counts[ARRAY_SIZE(connector_names)];
+       struct kms_screen *screen;
+       drmModeRes *res;
+       int i;
+
+       memset(counts, 0, sizeof(counts));
+
+       res = drmModeGetResources(device->fd);
+       if (!res)
+               return;
+
+       device->screens = calloc(res->count_connectors, sizeof(screen));
+       if (!device->screens)
+               return;
+
+       for (i = 0; i < res->count_connectors; i++) {
+               unsigned int *count;
+               const char *type;
+               int len;
+
+               screen = kms_screen_create(device, res->connectors[i]);
+               if (!screen)
+                       continue;
+
+               /* assign a unique name to this screen */
+               type = connector_names[screen->type];
+               count = &counts[screen->type];
+
+               len = snprintf(NULL, 0, "%s-%u", type, *count);
+
+               screen->name = malloc(len + 1);
+               if (!screen->name) {
+                       free(screen);
+                       continue;
+               }
+
+               snprintf(screen->name, len + 1, "%s-%u", type, *count);
+               (*count)++;
+
+               device->screens[i] = screen;
+               device->num_screens++;
+       }
+
+       drmModeFreeResources(res);
+}
+
+static void kms_device_probe_crtcs(struct kms_device *device)
+{
+       struct kms_crtc *crtc;
+       drmModeRes *res;
+       int i;
+
+       res = drmModeGetResources(device->fd);
+       if (!res)
+               return;
+
+       device->crtcs = calloc(res->count_crtcs, sizeof(crtc));
+       if (!device->crtcs)
+               return;
+
+       for (i = 0; i < res->count_crtcs; i++) {
+               crtc = kms_crtc_create(device, res->crtcs[i]);
+               if (!crtc)
+                       continue;
+
+               device->crtcs[i] = crtc;
+               device->num_crtcs++;
+       }
+
+       drmModeFreeResources(res);
+}
+
+static void kms_device_probe_planes(struct kms_device *device)
+{
+       struct kms_plane *plane;
+       drmModePlaneRes *res;
+       unsigned int i;
+
+       res = drmModeGetPlaneResources(device->fd);
+       if (!res)
+               return;
+
+       device->planes = calloc(res->count_planes, sizeof(plane));
+       if (!device->planes)
+               return;
+
+       for (i = 0; i < res->count_planes; i++) {
+               plane = kms_plane_create(device, res->planes[i]);
+               if (!plane)
+                       continue;
+
+               device->planes[i] = plane;
+               device->num_planes++;
+       }
+
+       drmModeFreePlaneResources(res);
+}
+
+static void kms_device_probe(struct kms_device *device)
+{
+       kms_device_probe_screens(device);
+       kms_device_probe_crtcs(device);
+       kms_device_probe_planes(device);
+}
+
+struct kms_device *kms_device_open(int fd)
+{
+       struct kms_device *device;
+
+       device = calloc(1, sizeof(*device));
+       if (!device)
+               return NULL;
+
+       device->fd = fd;
+
+       kms_device_probe(device);
+
+       return device;
+}
+
+void kms_device_close(struct kms_device *device)
+{
+       unsigned int i;
+
+       for (i = 0; i < device->num_planes; i++)
+               kms_plane_free(device->planes[i]);
+
+       free(device->planes);
+
+       for (i = 0; i < device->num_crtcs; i++)
+               kms_crtc_free(device->crtcs[i]);
+
+       free(device->crtcs);
+
+       for (i = 0; i < device->num_screens; i++)
+               kms_screen_free(device->screens[i]);
+
+       free(device->screens);
+
+       if (device->fd >= 0)
+               close(device->fd);
+
+       free(device);
+}
+
+struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device,
+                                               uint32_t type,
+                                               unsigned int index)
+{
+       unsigned int i;
+
+       for (i = 0; i < device->num_planes; i++) {
+               if (device->planes[i]->type == type) {
+                       if (index == 0)
+                               return device->planes[i];
+
+                       index--;
+               }
+       }
+
+       return NULL;
+}
diff --git a/tests/kms/libkms-test-framebuffer.c b/tests/kms/libkms-test-framebuffer.c
new file mode 100644 (file)
index 0000000..c9e5ad3
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2014 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 <string.h>
+
+#include <sys/mman.h>
+
+#include <drm_fourcc.h>
+
+#include "xf86drm.h"
+
+#include "libkms-test.h"
+
+struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
+                                              unsigned int width,
+                                              unsigned int height,
+                                              uint32_t format)
+{
+       uint32_t handles[4], pitches[4], offsets[4];
+       struct drm_mode_create_dumb args;
+       struct kms_framebuffer *fb;
+       int err;
+
+       fb = calloc(1, sizeof(*fb));
+       if (!fb)
+               return NULL;
+
+       fb->device = device;
+       fb->width = width;
+       fb->height = height;
+       fb->format = format;
+
+       memset(&args, 0, sizeof(args));
+       args.width = width;
+       args.height = height;
+
+       switch (format) {
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_XBGR8888:
+       case DRM_FORMAT_RGBA8888:
+               args.bpp = 32;
+               break;
+
+       default:
+               free(fb);
+               return NULL;
+       }
+
+       err = drmIoctl(device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &args);
+       if (err < 0) {
+               free(fb);
+               return NULL;
+       }
+
+       fb->handle = args.handle;
+       fb->pitch = args.pitch;
+       fb->size = args.size;
+
+       handles[0] = fb->handle;
+       pitches[0] = fb->pitch;
+       offsets[0] = 0;
+
+       err = drmModeAddFB2(device->fd, width, height, format, handles,
+                           pitches, offsets, &fb->id, 0);
+       if (err < 0) {
+               kms_framebuffer_free(fb);
+               return NULL;
+       }
+
+       return fb;
+}
+
+void kms_framebuffer_free(struct kms_framebuffer *fb)
+{
+       struct kms_device *device = fb->device;
+       struct drm_mode_destroy_dumb args;
+       int err;
+
+       if (fb->id) {
+               err = drmModeRmFB(device->fd, fb->id);
+               if (err < 0) {
+                       /* not much we can do now */
+               }
+       }
+
+       memset(&args, 0, sizeof(args));
+       args.handle = fb->handle;
+
+       err = drmIoctl(device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args);
+       if (err < 0) {
+               /* not much we can do now */
+       }
+
+       free(fb);
+}
+
+int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp)
+{
+       struct kms_device *device = fb->device;
+       struct drm_mode_map_dumb args;
+       void *ptr;
+       int err;
+
+       if (fb->ptr) {
+               *ptrp = fb->ptr;
+               return 0;
+       }
+
+       memset(&args, 0, sizeof(args));
+       args.handle = fb->handle;
+
+       err = drmIoctl(device->fd, DRM_IOCTL_MODE_MAP_DUMB, &args);
+       if (err < 0)
+               return -errno;
+
+       ptr = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                  device->fd, args.offset);
+       if (ptr == MAP_FAILED)
+               return -errno;
+
+       *ptrp = fb->ptr = ptr;
+
+       return 0;
+}
+
+void kms_framebuffer_unmap(struct kms_framebuffer *fb)
+{
+       if (fb->ptr) {
+               munmap(fb->ptr, fb->size);
+               fb->ptr = NULL;
+       }
+}
diff --git a/tests/kms/libkms-test-plane.c b/tests/kms/libkms-test-plane.c
new file mode 100644 (file)
index 0000000..8eb78af
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2014 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 <string.h>
+
+#include "libkms-test.h"
+
+static int kms_plane_probe(struct kms_plane *plane)
+{
+       struct kms_device *device = plane->device;
+       drmModeObjectPropertiesPtr props;
+       drmModePlane *p;
+       unsigned int i;
+
+       p = drmModeGetPlane(device->fd, plane->id);
+       if (!p)
+               return -ENODEV;
+
+       /* TODO: allow dynamic assignment to CRTCs */
+       if (p->crtc_id == 0) {
+               for (i = 0; i < device->num_crtcs; i++) {
+                       if (p->possible_crtcs & (1 << i)) {
+                               p->crtc_id = device->crtcs[i]->id;
+                               break;
+                       }
+               }
+       }
+
+       for (i = 0; i < device->num_crtcs; i++) {
+               if (device->crtcs[i]->id == p->crtc_id) {
+                       plane->crtc = device->crtcs[i];
+                       break;
+               }
+       }
+
+       plane->formats = calloc(p->count_formats, sizeof(uint32_t));
+       if (!plane->formats)
+               return -ENOMEM;
+
+       for (i = 0; i < p->count_formats; i++)
+               plane->formats[i] = p->formats[i];
+
+       plane->num_formats = p->count_formats;
+
+       drmModeFreePlane(p);
+
+       props = drmModeObjectGetProperties(device->fd, plane->id,
+                                          DRM_MODE_OBJECT_PLANE);
+       if (!props)
+               return -ENODEV;
+
+       for (i = 0; i < props->count_props; i++) {
+               drmModePropertyPtr prop;
+
+               prop = drmModeGetProperty(device->fd, props->props[i]);
+               if (prop) {
+                       if (strcmp(prop->name, "type") == 0)
+                               plane->type = props->prop_values[i];
+
+                       drmModeFreeProperty(prop);
+               }
+       }
+
+       drmModeFreeObjectProperties(props);
+
+       return 0;
+}
+
+struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id)
+{
+       struct kms_plane *plane;
+
+       plane = calloc(1, sizeof(*plane));
+       if (!plane)
+               return NULL;
+
+       plane->device = device;
+       plane->id = id;
+
+       kms_plane_probe(plane);
+
+       return plane;
+}
+
+void kms_plane_free(struct kms_plane *plane)
+{
+       free(plane);
+}
+
+int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb,
+                 unsigned int x, unsigned int y)
+{
+       struct kms_device *device = plane->device;
+       int err;
+
+       err = drmModeSetPlane(device->fd, plane->id, plane->crtc->id, fb->id,
+                             0, x, y, fb->width, fb->height, 0 << 16,
+                             0 << 16, fb->width << 16, fb->height << 16);
+       if (err < 0)
+               return -errno;
+
+       return 0;
+}
+
+bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format)
+{
+       unsigned int i;
+
+       for (i = 0; i < plane->num_formats; i++)
+               if (plane->formats[i] == format)
+                       return true;
+
+       return false;
+}
diff --git a/tests/kms/libkms-test-screen.c b/tests/kms/libkms-test-screen.c
new file mode 100644 (file)
index 0000000..3369022
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2014 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 <string.h>
+
+#include "libkms-test.h"
+
+static void kms_screen_probe(struct kms_screen *screen)
+{
+       struct kms_device *device = screen->device;
+       drmModeConnector *con;
+
+       con = drmModeGetConnector(device->fd, screen->id);
+       if (!con)
+               return;
+
+       screen->type = con->connector_type;
+
+       if (con->connection == DRM_MODE_CONNECTED)
+               screen->connected = true;
+       else
+               screen->connected = false;
+
+       memcpy(&screen->mode, &con->modes[0], sizeof(drmModeModeInfo));
+       screen->width = screen->mode.hdisplay;
+       screen->height = screen->mode.vdisplay;
+
+       drmModeFreeConnector(con);
+}
+
+struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id)
+{
+       struct kms_screen *screen;
+
+       screen = calloc(1, sizeof(*screen));
+       if (!screen)
+               return NULL;
+
+       screen->device = device;
+       screen->id = id;
+
+       kms_screen_probe(screen);
+
+       return screen;
+}
+
+void kms_screen_free(struct kms_screen *screen)
+{
+       if (screen)
+               free(screen->name);
+
+       free(screen);
+}
+
+int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc,
+                  struct kms_framebuffer *fb)
+{
+       struct kms_device *device = screen->device;
+       int err;
+
+       err = drmModeSetCrtc(device->fd, crtc->id, fb->id, 0, 0, &screen->id,
+                            1, &screen->mode);
+       if (err < 0)
+               return -errno;
+
+       return 0;
+}
diff --git a/tests/kms/libkms-test.h b/tests/kms/libkms-test.h
new file mode 100644 (file)
index 0000000..7b1d02e
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#ifndef LIBKMS_TEST_H
+#define LIBKMS_TEST_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <xf86drmMode.h>
+
+struct kms_device {
+       int fd;
+
+       struct kms_screen **screens;
+       unsigned int num_screens;
+
+       struct kms_crtc **crtcs;
+       unsigned int num_crtcs;
+
+       struct kms_plane **planes;
+       unsigned int num_planes;
+};
+
+struct kms_device *kms_device_open(int fd);
+void kms_device_close(struct kms_device *device);
+
+struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device,
+                                               uint32_t type,
+                                               unsigned int index);
+
+struct kms_crtc {
+       struct kms_device *device;
+       uint32_t id;
+};
+
+struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id);
+void kms_crtc_free(struct kms_crtc *crtc);
+
+struct kms_framebuffer {
+       struct kms_device *device;
+
+       unsigned int width;
+       unsigned int height;
+       unsigned int pitch;
+       uint32_t format;
+       size_t size;
+
+       uint32_t handle;
+       uint32_t id;
+
+       void *ptr;
+};
+
+struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
+                                              unsigned int width,
+                                              unsigned int height,
+                                              uint32_t format);
+void kms_framebuffer_free(struct kms_framebuffer *fb);
+int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp);
+void kms_framebuffer_unmap(struct kms_framebuffer *fb);
+
+struct kms_screen {
+       struct kms_device *device;
+       bool connected;
+       uint32_t type;
+       uint32_t id;
+
+       unsigned int width;
+       unsigned int height;
+       char *name;
+
+       drmModeModeInfo mode;
+};
+
+struct kms_screen *kms_screen_create(struct kms_device *device, uint32_t id);
+void kms_screen_free(struct kms_screen *screen);
+
+int kms_screen_set(struct kms_screen *screen, struct kms_crtc *crtc,
+                  struct kms_framebuffer *fb);
+
+struct kms_plane {
+       struct kms_device *device;
+       struct kms_crtc *crtc;
+       unsigned int type;
+       uint32_t id;
+
+       uint32_t *formats;
+       unsigned int num_formats;
+};
+
+struct kms_plane *kms_plane_create(struct kms_device *device, uint32_t id);
+void kms_plane_free(struct kms_plane *plane);
+
+int kms_plane_set(struct kms_plane *plane, struct kms_framebuffer *fb,
+                 unsigned int x, unsigned int y);
+bool kms_plane_supports_format(struct kms_plane *plane, uint32_t format);
+
+#endif