xref: /aosp_15_r20/external/libdrm/tests/kms/kms-universal-planes.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker  * Copyright © 2014 NVIDIA Corporation
3*7688df22SAndroid Build Coastguard Worker  *
4*7688df22SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*7688df22SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*7688df22SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*7688df22SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*7688df22SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*7688df22SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*7688df22SAndroid Build Coastguard Worker  *
11*7688df22SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*7688df22SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*7688df22SAndroid Build Coastguard Worker  * Software.
14*7688df22SAndroid Build Coastguard Worker  *
15*7688df22SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*7688df22SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*7688df22SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*7688df22SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*7688df22SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*7688df22SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*7688df22SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*7688df22SAndroid Build Coastguard Worker  */
23*7688df22SAndroid Build Coastguard Worker 
24*7688df22SAndroid Build Coastguard Worker #include <fcntl.h>
25*7688df22SAndroid Build Coastguard Worker #include <getopt.h>
26*7688df22SAndroid Build Coastguard Worker #include <stdbool.h>
27*7688df22SAndroid Build Coastguard Worker #include <stdint.h>
28*7688df22SAndroid Build Coastguard Worker #include <stdio.h>
29*7688df22SAndroid Build Coastguard Worker #include <string.h>
30*7688df22SAndroid Build Coastguard Worker #include <unistd.h>
31*7688df22SAndroid Build Coastguard Worker #if HAVE_SYS_SELECT_H
32*7688df22SAndroid Build Coastguard Worker #include <sys/select.h>
33*7688df22SAndroid Build Coastguard Worker #endif
34*7688df22SAndroid Build Coastguard Worker 
35*7688df22SAndroid Build Coastguard Worker #include <drm_fourcc.h>
36*7688df22SAndroid Build Coastguard Worker #include "xf86drm.h"
37*7688df22SAndroid Build Coastguard Worker 
38*7688df22SAndroid Build Coastguard Worker #include "util/common.h"
39*7688df22SAndroid Build Coastguard Worker #include "libkms-test.h"
40*7688df22SAndroid Build Coastguard Worker 
41*7688df22SAndroid Build Coastguard Worker static const uint32_t formats[] = {
42*7688df22SAndroid Build Coastguard Worker 	DRM_FORMAT_XRGB8888,
43*7688df22SAndroid Build Coastguard Worker 	DRM_FORMAT_XBGR8888,
44*7688df22SAndroid Build Coastguard Worker 	DRM_FORMAT_RGBA8888,
45*7688df22SAndroid Build Coastguard Worker };
46*7688df22SAndroid Build Coastguard Worker 
choose_format(struct kms_plane * plane)47*7688df22SAndroid Build Coastguard Worker static uint32_t choose_format(struct kms_plane *plane)
48*7688df22SAndroid Build Coastguard Worker {
49*7688df22SAndroid Build Coastguard Worker 	unsigned int i;
50*7688df22SAndroid Build Coastguard Worker 
51*7688df22SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(formats); i++)
52*7688df22SAndroid Build Coastguard Worker 		if (kms_plane_supports_format(plane, formats[i]))
53*7688df22SAndroid Build Coastguard Worker 			return formats[i];
54*7688df22SAndroid Build Coastguard Worker 
55*7688df22SAndroid Build Coastguard Worker 	return 0;
56*7688df22SAndroid Build Coastguard Worker }
57*7688df22SAndroid Build Coastguard Worker 
prepare_framebuffer(struct kms_framebuffer * fb,bool invert)58*7688df22SAndroid Build Coastguard Worker static void prepare_framebuffer(struct kms_framebuffer *fb, bool invert)
59*7688df22SAndroid Build Coastguard Worker {
60*7688df22SAndroid Build Coastguard Worker 	const unsigned int block_size = 16;
61*7688df22SAndroid Build Coastguard Worker 	uint32_t colors[2];
62*7688df22SAndroid Build Coastguard Worker 	unsigned int i, j;
63*7688df22SAndroid Build Coastguard Worker 	uint32_t *buf;
64*7688df22SAndroid Build Coastguard Worker 	void *ptr;
65*7688df22SAndroid Build Coastguard Worker 	int err;
66*7688df22SAndroid Build Coastguard Worker 
67*7688df22SAndroid Build Coastguard Worker 	switch (fb->format) {
68*7688df22SAndroid Build Coastguard Worker 	case DRM_FORMAT_XRGB8888:
69*7688df22SAndroid Build Coastguard Worker 		printf("using XRGB8888 format\n");
70*7688df22SAndroid Build Coastguard Worker 		           /* XXRRGGBB */
71*7688df22SAndroid Build Coastguard Worker 		colors[0] = 0xffff0000;
72*7688df22SAndroid Build Coastguard Worker 		colors[1] = 0xff0000ff;
73*7688df22SAndroid Build Coastguard Worker 		break;
74*7688df22SAndroid Build Coastguard Worker 
75*7688df22SAndroid Build Coastguard Worker 	case DRM_FORMAT_XBGR8888:
76*7688df22SAndroid Build Coastguard Worker 		printf("using XBGR8888 format\n");
77*7688df22SAndroid Build Coastguard Worker 		           /* XXBBGGRR */
78*7688df22SAndroid Build Coastguard Worker 		colors[0] = 0xff0000ff;
79*7688df22SAndroid Build Coastguard Worker 		colors[1] = 0xffff0000;
80*7688df22SAndroid Build Coastguard Worker 		break;
81*7688df22SAndroid Build Coastguard Worker 
82*7688df22SAndroid Build Coastguard Worker 	case DRM_FORMAT_RGBA8888:
83*7688df22SAndroid Build Coastguard Worker 		printf("using RGBA8888 format\n");
84*7688df22SAndroid Build Coastguard Worker 		           /* RRGGBBAA */
85*7688df22SAndroid Build Coastguard Worker 		colors[0] = 0xff0000ff;
86*7688df22SAndroid Build Coastguard Worker 		colors[1] = 0x0000ffff;
87*7688df22SAndroid Build Coastguard Worker 		break;
88*7688df22SAndroid Build Coastguard Worker 
89*7688df22SAndroid Build Coastguard Worker 	default:
90*7688df22SAndroid Build Coastguard Worker 		colors[0] = 0xffffffff;
91*7688df22SAndroid Build Coastguard Worker 		colors[1] = 0xffffffff;
92*7688df22SAndroid Build Coastguard Worker 		break;
93*7688df22SAndroid Build Coastguard Worker 	}
94*7688df22SAndroid Build Coastguard Worker 
95*7688df22SAndroid Build Coastguard Worker 	err = kms_framebuffer_map(fb, &ptr);
96*7688df22SAndroid Build Coastguard Worker 	if (err < 0) {
97*7688df22SAndroid Build Coastguard Worker 		fprintf(stderr, "kms_framebuffer_map() failed: %s\n",
98*7688df22SAndroid Build Coastguard Worker 			strerror(-err));
99*7688df22SAndroid Build Coastguard Worker 		return;
100*7688df22SAndroid Build Coastguard Worker 	}
101*7688df22SAndroid Build Coastguard Worker 
102*7688df22SAndroid Build Coastguard Worker 	buf = ptr;
103*7688df22SAndroid Build Coastguard Worker 
104*7688df22SAndroid Build Coastguard Worker 	for (j = 0; j < fb->height; j++) {
105*7688df22SAndroid Build Coastguard Worker 		for (i = 0; i < fb->width; i++) {
106*7688df22SAndroid Build Coastguard Worker 			unsigned int color = (j / block_size) ^
107*7688df22SAndroid Build Coastguard Worker 					     (i / block_size);
108*7688df22SAndroid Build Coastguard Worker 
109*7688df22SAndroid Build Coastguard Worker 			if (invert)
110*7688df22SAndroid Build Coastguard Worker 				color ^= color;
111*7688df22SAndroid Build Coastguard Worker 
112*7688df22SAndroid Build Coastguard Worker 			*buf++ = colors[color & 1];
113*7688df22SAndroid Build Coastguard Worker 		}
114*7688df22SAndroid Build Coastguard Worker 	}
115*7688df22SAndroid Build Coastguard Worker 
116*7688df22SAndroid Build Coastguard Worker 	kms_framebuffer_unmap(fb);
117*7688df22SAndroid Build Coastguard Worker }
118*7688df22SAndroid Build Coastguard Worker 
main(int argc,char * argv[])119*7688df22SAndroid Build Coastguard Worker int main(int argc, char *argv[])
120*7688df22SAndroid Build Coastguard Worker {
121*7688df22SAndroid Build Coastguard Worker 	static const char opts[] = "chopv";
122*7688df22SAndroid Build Coastguard Worker 	static struct option options[] = {
123*7688df22SAndroid Build Coastguard Worker 		{ "cursor", 0, 0, 'c' },
124*7688df22SAndroid Build Coastguard Worker 		{ "help", 0, 0, 'h' },
125*7688df22SAndroid Build Coastguard Worker 		{ "overlay", 0, 0, 'o' },
126*7688df22SAndroid Build Coastguard Worker 		{ "primary", 0, 0, 'p' },
127*7688df22SAndroid Build Coastguard Worker 		{ "verbose", 0, 0, 'v' },
128*7688df22SAndroid Build Coastguard Worker 		{ 0, 0, 0, 0 },
129*7688df22SAndroid Build Coastguard Worker 	};
130*7688df22SAndroid Build Coastguard Worker 	struct kms_framebuffer *cursor = NULL;
131*7688df22SAndroid Build Coastguard Worker 	struct kms_framebuffer *root = NULL;
132*7688df22SAndroid Build Coastguard Worker 	struct kms_framebuffer *fb = NULL;
133*7688df22SAndroid Build Coastguard Worker 	struct kms_device *device;
134*7688df22SAndroid Build Coastguard Worker 	bool use_overlay = false;
135*7688df22SAndroid Build Coastguard Worker 	bool use_primary = false;
136*7688df22SAndroid Build Coastguard Worker 	struct kms_plane *plane;
137*7688df22SAndroid Build Coastguard Worker 	bool use_cursor = false;
138*7688df22SAndroid Build Coastguard Worker 	bool verbose = false;
139*7688df22SAndroid Build Coastguard Worker 	unsigned int i;
140*7688df22SAndroid Build Coastguard Worker 	int opt, idx;
141*7688df22SAndroid Build Coastguard Worker 	int fd, err;
142*7688df22SAndroid Build Coastguard Worker 
143*7688df22SAndroid Build Coastguard Worker 	while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) {
144*7688df22SAndroid Build Coastguard Worker 		switch (opt) {
145*7688df22SAndroid Build Coastguard Worker 		case 'c':
146*7688df22SAndroid Build Coastguard Worker 			use_cursor = true;
147*7688df22SAndroid Build Coastguard Worker 			break;
148*7688df22SAndroid Build Coastguard Worker 
149*7688df22SAndroid Build Coastguard Worker 		case 'h':
150*7688df22SAndroid Build Coastguard Worker 			break;
151*7688df22SAndroid Build Coastguard Worker 
152*7688df22SAndroid Build Coastguard Worker 		case 'o':
153*7688df22SAndroid Build Coastguard Worker 			use_overlay = true;
154*7688df22SAndroid Build Coastguard Worker 			break;
155*7688df22SAndroid Build Coastguard Worker 
156*7688df22SAndroid Build Coastguard Worker 		case 'p':
157*7688df22SAndroid Build Coastguard Worker 			use_primary = true;
158*7688df22SAndroid Build Coastguard Worker 			break;
159*7688df22SAndroid Build Coastguard Worker 
160*7688df22SAndroid Build Coastguard Worker 		case 'v':
161*7688df22SAndroid Build Coastguard Worker 			verbose = true;
162*7688df22SAndroid Build Coastguard Worker 			break;
163*7688df22SAndroid Build Coastguard Worker 
164*7688df22SAndroid Build Coastguard Worker 		default:
165*7688df22SAndroid Build Coastguard Worker 			printf("unknown option \"%c\"\n", opt);
166*7688df22SAndroid Build Coastguard Worker 			return 1;
167*7688df22SAndroid Build Coastguard Worker 		}
168*7688df22SAndroid Build Coastguard Worker 	}
169*7688df22SAndroid Build Coastguard Worker 
170*7688df22SAndroid Build Coastguard Worker 	if (optind >= argc) {
171*7688df22SAndroid Build Coastguard Worker 		fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]);
172*7688df22SAndroid Build Coastguard Worker 		return 1;
173*7688df22SAndroid Build Coastguard Worker 	}
174*7688df22SAndroid Build Coastguard Worker 
175*7688df22SAndroid Build Coastguard Worker 	fd = open(argv[optind], O_RDWR);
176*7688df22SAndroid Build Coastguard Worker 	if (fd < 0) {
177*7688df22SAndroid Build Coastguard Worker 		fprintf(stderr, "open() failed: %m\n");
178*7688df22SAndroid Build Coastguard Worker 		return 1;
179*7688df22SAndroid Build Coastguard Worker 	}
180*7688df22SAndroid Build Coastguard Worker 
181*7688df22SAndroid Build Coastguard Worker 	err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
182*7688df22SAndroid Build Coastguard Worker 	if (err < 0) {
183*7688df22SAndroid Build Coastguard Worker 		fprintf(stderr, "drmSetClientCap() failed: %d\n", err);
184*7688df22SAndroid Build Coastguard Worker 		return 1;
185*7688df22SAndroid Build Coastguard Worker 	}
186*7688df22SAndroid Build Coastguard Worker 
187*7688df22SAndroid Build Coastguard Worker 	device = kms_device_open(fd);
188*7688df22SAndroid Build Coastguard Worker 	if (!device)
189*7688df22SAndroid Build Coastguard Worker 		return 1;
190*7688df22SAndroid Build Coastguard Worker 
191*7688df22SAndroid Build Coastguard Worker 	if (verbose) {
192*7688df22SAndroid Build Coastguard Worker 		printf("Screens: %u\n", device->num_screens);
193*7688df22SAndroid Build Coastguard Worker 
194*7688df22SAndroid Build Coastguard Worker 		for (i = 0; i < device->num_screens; i++) {
195*7688df22SAndroid Build Coastguard Worker 			struct kms_screen *screen = device->screens[i];
196*7688df22SAndroid Build Coastguard Worker 			const char *status = "disconnected";
197*7688df22SAndroid Build Coastguard Worker 
198*7688df22SAndroid Build Coastguard Worker 			if (screen->connected)
199*7688df22SAndroid Build Coastguard Worker 				status = "connected";
200*7688df22SAndroid Build Coastguard Worker 
201*7688df22SAndroid Build Coastguard Worker 			printf("  %u: %x\n", i, screen->id);
202*7688df22SAndroid Build Coastguard Worker 			printf("    Status: %s\n", status);
203*7688df22SAndroid Build Coastguard Worker 			printf("    Name: %s\n", screen->name);
204*7688df22SAndroid Build Coastguard Worker 			printf("    Resolution: %ux%u\n", screen->width,
205*7688df22SAndroid Build Coastguard Worker 			       screen->height);
206*7688df22SAndroid Build Coastguard Worker 		}
207*7688df22SAndroid Build Coastguard Worker 
208*7688df22SAndroid Build Coastguard Worker 		printf("Planes: %u\n", device->num_planes);
209*7688df22SAndroid Build Coastguard Worker 
210*7688df22SAndroid Build Coastguard Worker 		for (i = 0; i < device->num_planes; i++) {
211*7688df22SAndroid Build Coastguard Worker 			const char *type = NULL;
212*7688df22SAndroid Build Coastguard Worker 
213*7688df22SAndroid Build Coastguard Worker 			plane = device->planes[i];
214*7688df22SAndroid Build Coastguard Worker 			switch (plane->type) {
215*7688df22SAndroid Build Coastguard Worker 			case DRM_PLANE_TYPE_OVERLAY:
216*7688df22SAndroid Build Coastguard Worker 				type = "overlay";
217*7688df22SAndroid Build Coastguard Worker 				break;
218*7688df22SAndroid Build Coastguard Worker 
219*7688df22SAndroid Build Coastguard Worker 			case DRM_PLANE_TYPE_PRIMARY:
220*7688df22SAndroid Build Coastguard Worker 				type = "primary";
221*7688df22SAndroid Build Coastguard Worker 				break;
222*7688df22SAndroid Build Coastguard Worker 
223*7688df22SAndroid Build Coastguard Worker 			case DRM_PLANE_TYPE_CURSOR:
224*7688df22SAndroid Build Coastguard Worker 				type = "cursor";
225*7688df22SAndroid Build Coastguard Worker 				break;
226*7688df22SAndroid Build Coastguard Worker 			}
227*7688df22SAndroid Build Coastguard Worker 
228*7688df22SAndroid Build Coastguard Worker 			printf("  %u: %p\n", i, plane);
229*7688df22SAndroid Build Coastguard Worker 			printf("    ID: %x\n", plane->id);
230*7688df22SAndroid Build Coastguard Worker 			printf("    CRTC: %x\n", plane->crtc->id);
231*7688df22SAndroid Build Coastguard Worker 			printf("    Type: %x (%s)\n", plane->type, type);
232*7688df22SAndroid Build Coastguard Worker 		}
233*7688df22SAndroid Build Coastguard Worker 	}
234*7688df22SAndroid Build Coastguard Worker 
235*7688df22SAndroid Build Coastguard Worker 	if (use_cursor) {
236*7688df22SAndroid Build Coastguard Worker 		unsigned int x, y;
237*7688df22SAndroid Build Coastguard Worker 		uint32_t format;
238*7688df22SAndroid Build Coastguard Worker 
239*7688df22SAndroid Build Coastguard Worker 		plane = kms_device_find_plane_by_type(device,
240*7688df22SAndroid Build Coastguard Worker 						      DRM_PLANE_TYPE_CURSOR,
241*7688df22SAndroid Build Coastguard Worker 						      0);
242*7688df22SAndroid Build Coastguard Worker 		if (!plane) {
243*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no cursor plane found\n");
244*7688df22SAndroid Build Coastguard Worker 			return 1;
245*7688df22SAndroid Build Coastguard Worker 		}
246*7688df22SAndroid Build Coastguard Worker 
247*7688df22SAndroid Build Coastguard Worker 		format = choose_format(plane);
248*7688df22SAndroid Build Coastguard Worker 		if (!format) {
249*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no matching format found\n");
250*7688df22SAndroid Build Coastguard Worker 			return 1;
251*7688df22SAndroid Build Coastguard Worker 		}
252*7688df22SAndroid Build Coastguard Worker 
253*7688df22SAndroid Build Coastguard Worker 		cursor = kms_framebuffer_create(device, 32, 32, format);
254*7688df22SAndroid Build Coastguard Worker 		if (!cursor) {
255*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "failed to create cursor buffer\n");
256*7688df22SAndroid Build Coastguard Worker 			return 1;
257*7688df22SAndroid Build Coastguard Worker 		}
258*7688df22SAndroid Build Coastguard Worker 
259*7688df22SAndroid Build Coastguard Worker 		prepare_framebuffer(cursor, false);
260*7688df22SAndroid Build Coastguard Worker 
261*7688df22SAndroid Build Coastguard Worker 		x = (device->screens[0]->width - cursor->width) / 2;
262*7688df22SAndroid Build Coastguard Worker 		y = (device->screens[0]->height - cursor->height) / 2;
263*7688df22SAndroid Build Coastguard Worker 
264*7688df22SAndroid Build Coastguard Worker 		kms_plane_set(plane, cursor, x, y);
265*7688df22SAndroid Build Coastguard Worker 	}
266*7688df22SAndroid Build Coastguard Worker 
267*7688df22SAndroid Build Coastguard Worker 	if (use_overlay) {
268*7688df22SAndroid Build Coastguard Worker 		uint32_t format;
269*7688df22SAndroid Build Coastguard Worker 
270*7688df22SAndroid Build Coastguard Worker 		plane = kms_device_find_plane_by_type(device,
271*7688df22SAndroid Build Coastguard Worker 						      DRM_PLANE_TYPE_OVERLAY,
272*7688df22SAndroid Build Coastguard Worker 						      0);
273*7688df22SAndroid Build Coastguard Worker 		if (!plane) {
274*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no overlay plane found\n");
275*7688df22SAndroid Build Coastguard Worker 			return 1;
276*7688df22SAndroid Build Coastguard Worker 		}
277*7688df22SAndroid Build Coastguard Worker 
278*7688df22SAndroid Build Coastguard Worker 		format = choose_format(plane);
279*7688df22SAndroid Build Coastguard Worker 		if (!format) {
280*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no matching format found\n");
281*7688df22SAndroid Build Coastguard Worker 			return 1;
282*7688df22SAndroid Build Coastguard Worker 		}
283*7688df22SAndroid Build Coastguard Worker 
284*7688df22SAndroid Build Coastguard Worker 		fb = kms_framebuffer_create(device, 320, 240, format);
285*7688df22SAndroid Build Coastguard Worker 		if (!fb)
286*7688df22SAndroid Build Coastguard Worker 			return 1;
287*7688df22SAndroid Build Coastguard Worker 
288*7688df22SAndroid Build Coastguard Worker 		prepare_framebuffer(fb, false);
289*7688df22SAndroid Build Coastguard Worker 
290*7688df22SAndroid Build Coastguard Worker 		kms_plane_set(plane, fb, 0, 0);
291*7688df22SAndroid Build Coastguard Worker 	}
292*7688df22SAndroid Build Coastguard Worker 
293*7688df22SAndroid Build Coastguard Worker 	if (use_primary) {
294*7688df22SAndroid Build Coastguard Worker 		unsigned int x, y;
295*7688df22SAndroid Build Coastguard Worker 		uint32_t format;
296*7688df22SAndroid Build Coastguard Worker 
297*7688df22SAndroid Build Coastguard Worker 		plane = kms_device_find_plane_by_type(device,
298*7688df22SAndroid Build Coastguard Worker 						      DRM_PLANE_TYPE_PRIMARY,
299*7688df22SAndroid Build Coastguard Worker 						      0);
300*7688df22SAndroid Build Coastguard Worker 		if (!plane) {
301*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no primary plane found\n");
302*7688df22SAndroid Build Coastguard Worker 			return 1;
303*7688df22SAndroid Build Coastguard Worker 		}
304*7688df22SAndroid Build Coastguard Worker 
305*7688df22SAndroid Build Coastguard Worker 		format = choose_format(plane);
306*7688df22SAndroid Build Coastguard Worker 		if (!format) {
307*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "no matching format found\n");
308*7688df22SAndroid Build Coastguard Worker 			return 1;
309*7688df22SAndroid Build Coastguard Worker 		}
310*7688df22SAndroid Build Coastguard Worker 
311*7688df22SAndroid Build Coastguard Worker 		root = kms_framebuffer_create(device, 640, 480, format);
312*7688df22SAndroid Build Coastguard Worker 		if (!root)
313*7688df22SAndroid Build Coastguard Worker 			return 1;
314*7688df22SAndroid Build Coastguard Worker 
315*7688df22SAndroid Build Coastguard Worker 		prepare_framebuffer(root, true);
316*7688df22SAndroid Build Coastguard Worker 
317*7688df22SAndroid Build Coastguard Worker 		x = (device->screens[0]->width - root->width) / 2;
318*7688df22SAndroid Build Coastguard Worker 		y = (device->screens[0]->height - root->height) / 2;
319*7688df22SAndroid Build Coastguard Worker 
320*7688df22SAndroid Build Coastguard Worker 		kms_plane_set(plane, root, x, y);
321*7688df22SAndroid Build Coastguard Worker 	}
322*7688df22SAndroid Build Coastguard Worker 
323*7688df22SAndroid Build Coastguard Worker 	while (1) {
324*7688df22SAndroid Build Coastguard Worker 		struct timeval timeout = { 1, 0 };
325*7688df22SAndroid Build Coastguard Worker 		fd_set fds;
326*7688df22SAndroid Build Coastguard Worker 
327*7688df22SAndroid Build Coastguard Worker 		FD_ZERO(&fds);
328*7688df22SAndroid Build Coastguard Worker 		FD_SET(STDIN_FILENO, &fds);
329*7688df22SAndroid Build Coastguard Worker 
330*7688df22SAndroid Build Coastguard Worker 		err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout);
331*7688df22SAndroid Build Coastguard Worker 		if (err < 0) {
332*7688df22SAndroid Build Coastguard Worker 			fprintf(stderr, "select() failed: %m\n");
333*7688df22SAndroid Build Coastguard Worker 			break;
334*7688df22SAndroid Build Coastguard Worker 		}
335*7688df22SAndroid Build Coastguard Worker 
336*7688df22SAndroid Build Coastguard Worker 		/* timeout */
337*7688df22SAndroid Build Coastguard Worker 		if (err == 0)
338*7688df22SAndroid Build Coastguard Worker 			continue;
339*7688df22SAndroid Build Coastguard Worker 
340*7688df22SAndroid Build Coastguard Worker 		if (FD_ISSET(STDIN_FILENO, &fds))
341*7688df22SAndroid Build Coastguard Worker 			break;
342*7688df22SAndroid Build Coastguard Worker 	}
343*7688df22SAndroid Build Coastguard Worker 
344*7688df22SAndroid Build Coastguard Worker 	if (cursor)
345*7688df22SAndroid Build Coastguard Worker 		kms_framebuffer_free(cursor);
346*7688df22SAndroid Build Coastguard Worker 
347*7688df22SAndroid Build Coastguard Worker 	if (root)
348*7688df22SAndroid Build Coastguard Worker 		kms_framebuffer_free(root);
349*7688df22SAndroid Build Coastguard Worker 
350*7688df22SAndroid Build Coastguard Worker 	if (fb)
351*7688df22SAndroid Build Coastguard Worker 		kms_framebuffer_free(fb);
352*7688df22SAndroid Build Coastguard Worker 
353*7688df22SAndroid Build Coastguard Worker 	kms_device_close(device);
354*7688df22SAndroid Build Coastguard Worker 	close(fd);
355*7688df22SAndroid Build Coastguard Worker 
356*7688df22SAndroid Build Coastguard Worker 	return 0;
357*7688df22SAndroid Build Coastguard Worker }
358