Blame tests/kms/kms-universal-planes.c

Packit 631bab
/*
Packit 631bab
 * Copyright © 2014 NVIDIA Corporation
Packit 631bab
 *
Packit 631bab
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit 631bab
 * copy of this software and associated documentation files (the "Software"),
Packit 631bab
 * to deal in the Software without restriction, including without limitation
Packit 631bab
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Packit 631bab
 * and/or sell copies of the Software, and to permit persons to whom the
Packit 631bab
 * Software is furnished to do so, subject to the following conditions:
Packit 631bab
 *
Packit 631bab
 * The above copyright notice and this permission notice (including the next
Packit 631bab
 * paragraph) shall be included in all copies or substantial portions of the
Packit 631bab
 * Software.
Packit 631bab
 *
Packit 631bab
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 631bab
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 631bab
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
Packit 631bab
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit 631bab
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit 631bab
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit 631bab
 * IN THE SOFTWARE.
Packit 631bab
 */
Packit 631bab
Packit 631bab
#include <fcntl.h>
Packit 631bab
#include <getopt.h>
Packit 631bab
#include <stdbool.h>
Packit 631bab
#include <stdint.h>
Packit 631bab
#include <stdio.h>
Packit 631bab
#include <string.h>
Packit 631bab
#include <unistd.h>
Packit 631bab
#ifdef HAVE_SYS_SELECT_H
Packit 631bab
#include <sys/select.h>
Packit 631bab
#endif
Packit 631bab
Packit 631bab
#include <drm_fourcc.h>
Packit 631bab
#include "xf86drm.h"
Packit 631bab
Packit 631bab
#include "util/common.h"
Packit 631bab
#include "libkms-test.h"
Packit 631bab
Packit 631bab
static const uint32_t formats[] = {
Packit 631bab
	DRM_FORMAT_XRGB8888,
Packit 631bab
	DRM_FORMAT_XBGR8888,
Packit 631bab
	DRM_FORMAT_RGBA8888,
Packit 631bab
};
Packit 631bab
Packit 631bab
static uint32_t choose_format(struct kms_plane *plane)
Packit 631bab
{
Packit 631bab
	unsigned int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < ARRAY_SIZE(formats); i++)
Packit 631bab
		if (kms_plane_supports_format(plane, formats[i]))
Packit 631bab
			return formats[i];
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void prepare_framebuffer(struct kms_framebuffer *fb, bool invert)
Packit 631bab
{
Packit 631bab
	const unsigned int block_size = 16;
Packit 631bab
	uint32_t colors[2];
Packit 631bab
	unsigned int i, j;
Packit 631bab
	uint32_t *buf;
Packit 631bab
	void *ptr;
Packit 631bab
	int err;
Packit 631bab
Packit 631bab
	switch (fb->format) {
Packit 631bab
	case DRM_FORMAT_XRGB8888:
Packit 631bab
		printf("using XRGB8888 format\n");
Packit 631bab
		           /* XXRRGGBB */
Packit 631bab
		colors[0] = 0xffff0000;
Packit 631bab
		colors[1] = 0xff0000ff;
Packit 631bab
		break;
Packit 631bab
Packit 631bab
	case DRM_FORMAT_XBGR8888:
Packit 631bab
		printf("using XBGR8888 format\n");
Packit 631bab
		           /* XXBBGGRR */
Packit 631bab
		colors[0] = 0xff0000ff;
Packit 631bab
		colors[1] = 0xffff0000;
Packit 631bab
		break;
Packit 631bab
Packit 631bab
	case DRM_FORMAT_RGBA8888:
Packit 631bab
		printf("using RGBA8888 format\n");
Packit 631bab
		           /* RRGGBBAA */
Packit 631bab
		colors[0] = 0xff0000ff;
Packit 631bab
		colors[1] = 0x0000ffff;
Packit 631bab
		break;
Packit 631bab
Packit 631bab
	default:
Packit 631bab
		colors[0] = 0xffffffff;
Packit 631bab
		colors[1] = 0xffffffff;
Packit 631bab
		break;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	err = kms_framebuffer_map(fb, &ptr);
Packit 631bab
	if (err < 0) {
Packit 631bab
		fprintf(stderr, "kms_framebuffer_map() failed: %s\n",
Packit 631bab
			strerror(-err));
Packit 631bab
		return;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	buf = ptr;
Packit 631bab
Packit 631bab
	for (j = 0; j < fb->height; j++) {
Packit 631bab
		for (i = 0; i < fb->width; i++) {
Packit 631bab
			unsigned int color = (j / block_size) ^
Packit 631bab
					     (i / block_size);
Packit 631bab
Packit 631bab
			if (invert)
Packit 631bab
				color ^= color;
Packit 631bab
Packit 631bab
			*buf++ = colors[color & 1];
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	kms_framebuffer_unmap(fb);
Packit 631bab
}
Packit 631bab
Packit 631bab
int main(int argc, char *argv[])
Packit 631bab
{
Packit 631bab
	static const char opts[] = "chopv";
Packit 631bab
	static struct option options[] = {
Packit 631bab
		{ "cursor", 0, 0, 'c' },
Packit 631bab
		{ "help", 0, 0, 'h' },
Packit 631bab
		{ "overlay", 0, 0, 'o' },
Packit 631bab
		{ "primary", 0, 0, 'p' },
Packit 631bab
		{ "verbose", 0, 0, 'v' },
Packit 631bab
		{ 0, 0, 0, 0 },
Packit 631bab
	};
Packit 631bab
	struct kms_framebuffer *cursor = NULL;
Packit 631bab
	struct kms_framebuffer *root = NULL;
Packit 631bab
	struct kms_framebuffer *fb = NULL;
Packit 631bab
	struct kms_device *device;
Packit 631bab
	bool use_overlay = false;
Packit 631bab
	bool use_primary = false;
Packit 631bab
	struct kms_plane *plane;
Packit 631bab
	bool use_cursor = false;
Packit 631bab
	bool verbose = false;
Packit 631bab
	unsigned int i;
Packit 631bab
	int opt, idx;
Packit 631bab
	int fd, err;
Packit 631bab
Packit 631bab
	while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) {
Packit 631bab
		switch (opt) {
Packit 631bab
		case 'c':
Packit 631bab
			use_cursor = true;
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		case 'h':
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		case 'o':
Packit 631bab
			use_overlay = true;
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		case 'p':
Packit 631bab
			use_primary = true;
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		case 'v':
Packit 631bab
			verbose = true;
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		default:
Packit 631bab
			printf("unknown option \"%c\"\n", opt);
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (optind >= argc) {
Packit 631bab
		fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]);
Packit 631bab
		return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	fd = open(argv[optind], O_RDWR);
Packit 631bab
	if (fd < 0) {
Packit 631bab
		fprintf(stderr, "open() failed: %m\n");
Packit 631bab
		return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
Packit 631bab
	if (err < 0) {
Packit 631bab
		fprintf(stderr, "drmSetClientCap() failed: %d\n", err);
Packit 631bab
		return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	device = kms_device_open(fd);
Packit 631bab
	if (!device)
Packit 631bab
		return 1;
Packit 631bab
Packit 631bab
	if (verbose) {
Packit 631bab
		printf("Screens: %u\n", device->num_screens);
Packit 631bab
Packit 631bab
		for (i = 0; i < device->num_screens; i++) {
Packit 631bab
			struct kms_screen *screen = device->screens[i];
Packit 631bab
			const char *status = "disconnected";
Packit 631bab
Packit 631bab
			if (screen->connected)
Packit 631bab
				status = "connected";
Packit 631bab
Packit 631bab
			printf("  %u: %x\n", i, screen->id);
Packit 631bab
			printf("    Status: %s\n", status);
Packit 631bab
			printf("    Name: %s\n", screen->name);
Packit 631bab
			printf("    Resolution: %ux%u\n", screen->width,
Packit 631bab
			       screen->height);
Packit 631bab
		}
Packit 631bab
Packit 631bab
		printf("Planes: %u\n", device->num_planes);
Packit 631bab
Packit 631bab
		for (i = 0; i < device->num_planes; i++) {
Packit 631bab
			const char *type = NULL;
Packit 631bab
Packit 631bab
			plane = device->planes[i];
Packit 631bab
			switch (plane->type) {
Packit 631bab
			case DRM_PLANE_TYPE_OVERLAY:
Packit 631bab
				type = "overlay";
Packit 631bab
				break;
Packit 631bab
Packit 631bab
			case DRM_PLANE_TYPE_PRIMARY:
Packit 631bab
				type = "primary";
Packit 631bab
				break;
Packit 631bab
Packit 631bab
			case DRM_PLANE_TYPE_CURSOR:
Packit 631bab
				type = "cursor";
Packit 631bab
				break;
Packit 631bab
			}
Packit 631bab
Packit 631bab
			printf("  %u: %p\n", i, plane);
Packit 631bab
			printf("    ID: %x\n", plane->id);
Packit 631bab
			printf("    CRTC: %x\n", plane->crtc->id);
Packit 631bab
			printf("    Type: %x (%s)\n", plane->type, type);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (use_cursor) {
Packit 631bab
		unsigned int x, y;
Packit 631bab
		uint32_t format;
Packit 631bab
Packit 631bab
		plane = kms_device_find_plane_by_type(device,
Packit 631bab
						      DRM_PLANE_TYPE_CURSOR,
Packit 631bab
						      0);
Packit 631bab
		if (!plane) {
Packit 631bab
			fprintf(stderr, "no cursor plane found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		format = choose_format(plane);
Packit 631bab
		if (!format) {
Packit 631bab
			fprintf(stderr, "no matching format found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		cursor = kms_framebuffer_create(device, 32, 32, format);
Packit 631bab
		if (!cursor) {
Packit 631bab
			fprintf(stderr, "failed to create cursor buffer\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		prepare_framebuffer(cursor, false);
Packit 631bab
Packit 631bab
		x = (device->screens[0]->width - cursor->width) / 2;
Packit 631bab
		y = (device->screens[0]->height - cursor->height) / 2;
Packit 631bab
Packit 631bab
		kms_plane_set(plane, cursor, x, y);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (use_overlay) {
Packit 631bab
		uint32_t format;
Packit 631bab
Packit 631bab
		plane = kms_device_find_plane_by_type(device,
Packit 631bab
						      DRM_PLANE_TYPE_OVERLAY,
Packit 631bab
						      0);
Packit 631bab
		if (!plane) {
Packit 631bab
			fprintf(stderr, "no overlay plane found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		format = choose_format(plane);
Packit 631bab
		if (!format) {
Packit 631bab
			fprintf(stderr, "no matching format found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		fb = kms_framebuffer_create(device, 320, 240, format);
Packit 631bab
		if (!fb)
Packit 631bab
			return 1;
Packit 631bab
Packit 631bab
		prepare_framebuffer(fb, false);
Packit 631bab
Packit 631bab
		kms_plane_set(plane, fb, 0, 0);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (use_primary) {
Packit 631bab
		unsigned int x, y;
Packit 631bab
		uint32_t format;
Packit 631bab
Packit 631bab
		plane = kms_device_find_plane_by_type(device,
Packit 631bab
						      DRM_PLANE_TYPE_PRIMARY,
Packit 631bab
						      0);
Packit 631bab
		if (!plane) {
Packit 631bab
			fprintf(stderr, "no primary plane found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		format = choose_format(plane);
Packit 631bab
		if (!format) {
Packit 631bab
			fprintf(stderr, "no matching format found\n");
Packit 631bab
			return 1;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		root = kms_framebuffer_create(device, 640, 480, format);
Packit 631bab
		if (!root)
Packit 631bab
			return 1;
Packit 631bab
Packit 631bab
		prepare_framebuffer(root, true);
Packit 631bab
Packit 631bab
		x = (device->screens[0]->width - root->width) / 2;
Packit 631bab
		y = (device->screens[0]->height - root->height) / 2;
Packit 631bab
Packit 631bab
		kms_plane_set(plane, root, x, y);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	while (1) {
Packit 631bab
		struct timeval timeout = { 1, 0 };
Packit 631bab
		fd_set fds;
Packit 631bab
Packit 631bab
		FD_ZERO(&fds);
Packit 631bab
		FD_SET(STDIN_FILENO, &fds);
Packit 631bab
Packit 631bab
		err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout);
Packit 631bab
		if (err < 0) {
Packit 631bab
			fprintf(stderr, "select() failed: %m\n");
Packit 631bab
			break;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		/* timeout */
Packit 631bab
		if (err == 0)
Packit 631bab
			continue;
Packit 631bab
Packit 631bab
		if (FD_ISSET(STDIN_FILENO, &fds))
Packit 631bab
			break;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (cursor)
Packit 631bab
		kms_framebuffer_free(cursor);
Packit 631bab
Packit 631bab
	if (root)
Packit 631bab
		kms_framebuffer_free(root);
Packit 631bab
Packit 631bab
	if (fb)
Packit 631bab
		kms_framebuffer_free(fb);
Packit 631bab
Packit 631bab
	kms_device_close(device);
Packit 631bab
	close(fd);
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}