xref: /aosp_15_r20/external/igt-gpu-tools/overlay/kms/kms-overlay.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2013 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  */
24*d83cc019SAndroid Build Coastguard Worker 
25*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
26*d83cc019SAndroid Build Coastguard Worker #include <sys/mman.h>
27*d83cc019SAndroid Build Coastguard Worker #include <cairo.h>
28*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
29*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
30*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
31*d83cc019SAndroid Build Coastguard Worker #include <string.h>
32*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
33*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
34*d83cc019SAndroid Build Coastguard Worker 
35*d83cc019SAndroid Build Coastguard Worker #include <drm.h>
36*d83cc019SAndroid Build Coastguard Worker #include <drm_fourcc.h>
37*d83cc019SAndroid Build Coastguard Worker #include <xf86drm.h>
38*d83cc019SAndroid Build Coastguard Worker #include <xf86drmMode.h>
39*d83cc019SAndroid Build Coastguard Worker #include <i915_drm.h>
40*d83cc019SAndroid Build Coastguard Worker #include "../overlay.h"
41*d83cc019SAndroid Build Coastguard Worker //#include "rgb2yuv.h"
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker #ifndef ALIGN
44*d83cc019SAndroid Build Coastguard Worker #define ALIGN(i,m)	(((i) + (m) - 1) & ~((m) - 1))
45*d83cc019SAndroid Build Coastguard Worker #endif
46*d83cc019SAndroid Build Coastguard Worker 
47*d83cc019SAndroid Build Coastguard Worker struct kms_image {
48*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle, name;
49*d83cc019SAndroid Build Coastguard Worker 	uint32_t format;
50*d83cc019SAndroid Build Coastguard Worker 	uint32_t width, height, stride;
51*d83cc019SAndroid Build Coastguard Worker 	uint32_t size;
52*d83cc019SAndroid Build Coastguard Worker 	void *map;
53*d83cc019SAndroid Build Coastguard Worker };
54*d83cc019SAndroid Build Coastguard Worker 
55*d83cc019SAndroid Build Coastguard Worker struct kms_overlay {
56*d83cc019SAndroid Build Coastguard Worker 	struct overlay base;
57*d83cc019SAndroid Build Coastguard Worker 	struct kms_image image;
58*d83cc019SAndroid Build Coastguard Worker 	int fd;
59*d83cc019SAndroid Build Coastguard Worker 	int crtc;
60*d83cc019SAndroid Build Coastguard Worker 
61*d83cc019SAndroid Build Coastguard Worker 	int x, y;
62*d83cc019SAndroid Build Coastguard Worker 	int visible;
63*d83cc019SAndroid Build Coastguard Worker 
64*d83cc019SAndroid Build Coastguard Worker 	void *mem;
65*d83cc019SAndroid Build Coastguard Worker 	int size;
66*d83cc019SAndroid Build Coastguard Worker };
67*d83cc019SAndroid Build Coastguard Worker 
to_kms_overlay(struct overlay * o)68*d83cc019SAndroid Build Coastguard Worker static inline struct kms_overlay *to_kms_overlay(struct overlay *o)
69*d83cc019SAndroid Build Coastguard Worker {
70*d83cc019SAndroid Build Coastguard Worker 	return (struct kms_overlay *)o;
71*d83cc019SAndroid Build Coastguard Worker }
72*d83cc019SAndroid Build Coastguard Worker 
kms_create_fb(int fd,struct kms_image * image)73*d83cc019SAndroid Build Coastguard Worker static int kms_create_fb(int fd, struct kms_image *image)
74*d83cc019SAndroid Build Coastguard Worker {
75*d83cc019SAndroid Build Coastguard Worker 	uint32_t offsets[4], pitches[4], handles[4];
76*d83cc019SAndroid Build Coastguard Worker 
77*d83cc019SAndroid Build Coastguard Worker 	handles[0] = image->handle;
78*d83cc019SAndroid Build Coastguard Worker 	pitches[0] = image->stride;
79*d83cc019SAndroid Build Coastguard Worker 	offsets[0] = 0;
80*d83cc019SAndroid Build Coastguard Worker 
81*d83cc019SAndroid Build Coastguard Worker 	return drmModeAddFB2(fd,
82*d83cc019SAndroid Build Coastguard Worker 			     image->width, image->height, image->format,
83*d83cc019SAndroid Build Coastguard Worker 			     handles, pitches, offsets,
84*d83cc019SAndroid Build Coastguard Worker 			     &image->name, 0) == 0;
85*d83cc019SAndroid Build Coastguard Worker }
86*d83cc019SAndroid Build Coastguard Worker 
attach_to_crtc(int fd,int crtc,int x,int y,struct kms_image * image)87*d83cc019SAndroid Build Coastguard Worker static int attach_to_crtc(int fd, int crtc, int x, int y, struct kms_image *image)
88*d83cc019SAndroid Build Coastguard Worker {
89*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_set_plane s;
90*d83cc019SAndroid Build Coastguard Worker 
91*d83cc019SAndroid Build Coastguard Worker 	s.crtc_id = crtc;
92*d83cc019SAndroid Build Coastguard Worker 	s.fb_id = image->name;
93*d83cc019SAndroid Build Coastguard Worker 	s.flags = 0;
94*d83cc019SAndroid Build Coastguard Worker 	s.crtc_x = x;
95*d83cc019SAndroid Build Coastguard Worker 	s.crtc_y = y;
96*d83cc019SAndroid Build Coastguard Worker 	s.crtc_w = image->width;
97*d83cc019SAndroid Build Coastguard Worker 	s.crtc_h = image->height;
98*d83cc019SAndroid Build Coastguard Worker 	s.src_x = 0;
99*d83cc019SAndroid Build Coastguard Worker 	s.src_y = 0;
100*d83cc019SAndroid Build Coastguard Worker 	s.src_w = image->width << 16;
101*d83cc019SAndroid Build Coastguard Worker 	s.src_h = image->height << 16;
102*d83cc019SAndroid Build Coastguard Worker 
103*d83cc019SAndroid Build Coastguard Worker 	return drmIoctl(fd, DRM_IOCTL_MODE_SETPLANE, &s) == 0;
104*d83cc019SAndroid Build Coastguard Worker }
105*d83cc019SAndroid Build Coastguard Worker 
detach_from_crtc(int fd,int crtc)106*d83cc019SAndroid Build Coastguard Worker static int detach_from_crtc(int fd, int crtc)
107*d83cc019SAndroid Build Coastguard Worker {
108*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_set_plane s;
109*d83cc019SAndroid Build Coastguard Worker 
110*d83cc019SAndroid Build Coastguard Worker 	memset(&s, 0, sizeof(s));
111*d83cc019SAndroid Build Coastguard Worker 	s.crtc_id = crtc;
112*d83cc019SAndroid Build Coastguard Worker 	return drmIoctl(fd, DRM_IOCTL_MODE_SETPLANE, &s) == 0;
113*d83cc019SAndroid Build Coastguard Worker }
114*d83cc019SAndroid Build Coastguard Worker 
kms_overlay_show(struct overlay * overlay)115*d83cc019SAndroid Build Coastguard Worker static void kms_overlay_show(struct overlay *overlay)
116*d83cc019SAndroid Build Coastguard Worker {
117*d83cc019SAndroid Build Coastguard Worker 	struct kms_overlay *priv = to_kms_overlay(overlay);
118*d83cc019SAndroid Build Coastguard Worker 
119*d83cc019SAndroid Build Coastguard Worker 	memcpy(priv->image.map, priv->mem, priv->size);
120*d83cc019SAndroid Build Coastguard Worker 
121*d83cc019SAndroid Build Coastguard Worker 	if (!priv->visible) {
122*d83cc019SAndroid Build Coastguard Worker 		attach_to_crtc(priv->fd, priv->crtc, priv->x, priv->y, &priv->image);
123*d83cc019SAndroid Build Coastguard Worker 		priv->visible = true;
124*d83cc019SAndroid Build Coastguard Worker 	}
125*d83cc019SAndroid Build Coastguard Worker }
126*d83cc019SAndroid Build Coastguard Worker 
kms_overlay_hide(struct overlay * overlay)127*d83cc019SAndroid Build Coastguard Worker static void kms_overlay_hide(struct overlay *overlay)
128*d83cc019SAndroid Build Coastguard Worker {
129*d83cc019SAndroid Build Coastguard Worker 	struct kms_overlay *priv = to_kms_overlay(overlay);
130*d83cc019SAndroid Build Coastguard Worker 
131*d83cc019SAndroid Build Coastguard Worker 	if (priv->visible) {
132*d83cc019SAndroid Build Coastguard Worker 		detach_from_crtc(priv->fd, priv->crtc);
133*d83cc019SAndroid Build Coastguard Worker 		priv->visible = false;
134*d83cc019SAndroid Build Coastguard Worker 	}
135*d83cc019SAndroid Build Coastguard Worker }
136*d83cc019SAndroid Build Coastguard Worker 
kms_overlay_destroy(void * data)137*d83cc019SAndroid Build Coastguard Worker static void kms_overlay_destroy(void *data)
138*d83cc019SAndroid Build Coastguard Worker {
139*d83cc019SAndroid Build Coastguard Worker 	struct kms_overlay *priv = data;
140*d83cc019SAndroid Build Coastguard Worker 	drmIoctl(priv->fd, DRM_IOCTL_MODE_RMFB, &priv->image.name);
141*d83cc019SAndroid Build Coastguard Worker 	munmap(priv->image.map, priv->image.size);
142*d83cc019SAndroid Build Coastguard Worker 	free(priv->mem);
143*d83cc019SAndroid Build Coastguard Worker 	close(priv->fd);
144*d83cc019SAndroid Build Coastguard Worker 	free(priv);
145*d83cc019SAndroid Build Coastguard Worker }
146*d83cc019SAndroid Build Coastguard Worker 
is_i915_device(int fd)147*d83cc019SAndroid Build Coastguard Worker static int is_i915_device(int fd)
148*d83cc019SAndroid Build Coastguard Worker {
149*d83cc019SAndroid Build Coastguard Worker 	drm_version_t version;
150*d83cc019SAndroid Build Coastguard Worker 	char name[5] = "";
151*d83cc019SAndroid Build Coastguard Worker 
152*d83cc019SAndroid Build Coastguard Worker 	memset(&version, 0, sizeof(version));
153*d83cc019SAndroid Build Coastguard Worker 	version.name_len = 4;
154*d83cc019SAndroid Build Coastguard Worker 	version.name = name;
155*d83cc019SAndroid Build Coastguard Worker 
156*d83cc019SAndroid Build Coastguard Worker 	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
157*d83cc019SAndroid Build Coastguard Worker 		return 0;
158*d83cc019SAndroid Build Coastguard Worker 
159*d83cc019SAndroid Build Coastguard Worker 	return strcmp("i915", name) == 0;
160*d83cc019SAndroid Build Coastguard Worker }
161*d83cc019SAndroid Build Coastguard Worker 
check_device(int fd)162*d83cc019SAndroid Build Coastguard Worker static int check_device(int fd)
163*d83cc019SAndroid Build Coastguard Worker {
164*d83cc019SAndroid Build Coastguard Worker 	int ret;
165*d83cc019SAndroid Build Coastguard Worker 
166*d83cc019SAndroid Build Coastguard Worker 	/* Confirm that this is a i915.ko device with GEM/KMS enabled */
167*d83cc019SAndroid Build Coastguard Worker 	ret = is_i915_device(fd);
168*d83cc019SAndroid Build Coastguard Worker 	if (ret) {
169*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_getparam gp;
170*d83cc019SAndroid Build Coastguard Worker 		gp.param = I915_PARAM_HAS_GEM;
171*d83cc019SAndroid Build Coastguard Worker 		gp.value = &ret;
172*d83cc019SAndroid Build Coastguard Worker 		if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
173*d83cc019SAndroid Build Coastguard Worker 			ret = 0;
174*d83cc019SAndroid Build Coastguard Worker 	}
175*d83cc019SAndroid Build Coastguard Worker 	if (ret) {
176*d83cc019SAndroid Build Coastguard Worker 		struct drm_mode_card_res res;
177*d83cc019SAndroid Build Coastguard Worker 
178*d83cc019SAndroid Build Coastguard Worker 		memset(&res, 0, sizeof(res));
179*d83cc019SAndroid Build Coastguard Worker 		if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
180*d83cc019SAndroid Build Coastguard Worker 			ret = 0;
181*d83cc019SAndroid Build Coastguard Worker 	}
182*d83cc019SAndroid Build Coastguard Worker 
183*d83cc019SAndroid Build Coastguard Worker 	return ret;
184*d83cc019SAndroid Build Coastguard Worker }
185*d83cc019SAndroid Build Coastguard Worker 
i915_open(void)186*d83cc019SAndroid Build Coastguard Worker static int i915_open(void)
187*d83cc019SAndroid Build Coastguard Worker {
188*d83cc019SAndroid Build Coastguard Worker 	char buf[80];
189*d83cc019SAndroid Build Coastguard Worker 	int fd, n;
190*d83cc019SAndroid Build Coastguard Worker 
191*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < 16; n++) {
192*d83cc019SAndroid Build Coastguard Worker 		sprintf(buf, "/dev/dri/card%d", n);
193*d83cc019SAndroid Build Coastguard Worker 		fd = open(buf, O_RDWR);
194*d83cc019SAndroid Build Coastguard Worker 		if (fd == -1)
195*d83cc019SAndroid Build Coastguard Worker 			continue;
196*d83cc019SAndroid Build Coastguard Worker 
197*d83cc019SAndroid Build Coastguard Worker 		if (!check_device(fd)) {
198*d83cc019SAndroid Build Coastguard Worker 			close(fd);
199*d83cc019SAndroid Build Coastguard Worker 			continue;
200*d83cc019SAndroid Build Coastguard Worker 		}
201*d83cc019SAndroid Build Coastguard Worker 		return fd;
202*d83cc019SAndroid Build Coastguard Worker 	}
203*d83cc019SAndroid Build Coastguard Worker 
204*d83cc019SAndroid Build Coastguard Worker 	return -1;
205*d83cc019SAndroid Build Coastguard Worker }
206*d83cc019SAndroid Build Coastguard Worker 
config_get_pipe(struct config * config)207*d83cc019SAndroid Build Coastguard Worker static int config_get_pipe(struct config *config)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker 	const char *str;
210*d83cc019SAndroid Build Coastguard Worker 
211*d83cc019SAndroid Build Coastguard Worker 	str = config_get_value(config, "kms", "pipe");
212*d83cc019SAndroid Build Coastguard Worker 	if (str == NULL)
213*d83cc019SAndroid Build Coastguard Worker 		return 0;
214*d83cc019SAndroid Build Coastguard Worker 
215*d83cc019SAndroid Build Coastguard Worker 	return atoi(str);
216*d83cc019SAndroid Build Coastguard Worker }
217*d83cc019SAndroid Build Coastguard Worker 
218*d83cc019SAndroid Build Coastguard Worker cairo_surface_t *
kms_overlay_create(struct config * config,int * width,int * height)219*d83cc019SAndroid Build Coastguard Worker kms_overlay_create(struct config *config, int *width, int *height)
220*d83cc019SAndroid Build Coastguard Worker {
221*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_create create;
222*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_mmap_gtt map;
223*d83cc019SAndroid Build Coastguard Worker 	struct kms_overlay *priv;
224*d83cc019SAndroid Build Coastguard Worker 	drmModeResPtr kmode;
225*d83cc019SAndroid Build Coastguard Worker 	int i, pipe;
226*d83cc019SAndroid Build Coastguard Worker 
227*d83cc019SAndroid Build Coastguard Worker 	priv = malloc(sizeof(*priv));
228*d83cc019SAndroid Build Coastguard Worker 	if (priv == NULL)
229*d83cc019SAndroid Build Coastguard Worker 		return NULL;
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 	priv->fd = i915_open();
232*d83cc019SAndroid Build Coastguard Worker 	if (priv->fd == -1)
233*d83cc019SAndroid Build Coastguard Worker 		goto err_priv;
234*d83cc019SAndroid Build Coastguard Worker 
235*d83cc019SAndroid Build Coastguard Worker 	kmode = drmModeGetResources(priv->fd);
236*d83cc019SAndroid Build Coastguard Worker 	if (kmode == 0)
237*d83cc019SAndroid Build Coastguard Worker 		goto err_fd;
238*d83cc019SAndroid Build Coastguard Worker 
239*d83cc019SAndroid Build Coastguard Worker 	pipe = config_get_pipe(config);
240*d83cc019SAndroid Build Coastguard Worker 	priv->crtc = 0;
241*d83cc019SAndroid Build Coastguard Worker 
242*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < kmode->count_crtcs; i++) {
243*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_get_pipe_from_crtc_id get_pipe;
244*d83cc019SAndroid Build Coastguard Worker 
245*d83cc019SAndroid Build Coastguard Worker 		get_pipe.pipe = 0;
246*d83cc019SAndroid Build Coastguard Worker 		get_pipe.crtc_id = kmode->crtcs[i];
247*d83cc019SAndroid Build Coastguard Worker 		if (drmIoctl(priv->fd,
248*d83cc019SAndroid Build Coastguard Worker 			     DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
249*d83cc019SAndroid Build Coastguard Worker 			     &get_pipe)) {
250*d83cc019SAndroid Build Coastguard Worker 			continue;
251*d83cc019SAndroid Build Coastguard Worker 		}
252*d83cc019SAndroid Build Coastguard Worker 
253*d83cc019SAndroid Build Coastguard Worker 		if (get_pipe.pipe != pipe)
254*d83cc019SAndroid Build Coastguard Worker 			continue;
255*d83cc019SAndroid Build Coastguard Worker 
256*d83cc019SAndroid Build Coastguard Worker 		priv->crtc = get_pipe.crtc_id;
257*d83cc019SAndroid Build Coastguard Worker 	}
258*d83cc019SAndroid Build Coastguard Worker 
259*d83cc019SAndroid Build Coastguard Worker 	if (priv->crtc == 0)
260*d83cc019SAndroid Build Coastguard Worker 		goto err_fd;
261*d83cc019SAndroid Build Coastguard Worker 
262*d83cc019SAndroid Build Coastguard Worker 	priv->image.format = DRM_FORMAT_XRGB8888;
263*d83cc019SAndroid Build Coastguard Worker 	priv->image.width = ALIGN(*width, 4);
264*d83cc019SAndroid Build Coastguard Worker 	priv->image.height = ALIGN(*height, 2);
265*d83cc019SAndroid Build Coastguard Worker 	priv->image.stride = ALIGN(4*priv->image.width, 64);
266*d83cc019SAndroid Build Coastguard Worker 	priv->image.size = ALIGN(priv->image.stride * priv->image.height, 4096);
267*d83cc019SAndroid Build Coastguard Worker 
268*d83cc019SAndroid Build Coastguard Worker 	create.handle = 0;
269*d83cc019SAndroid Build Coastguard Worker 	create.size = ALIGN(priv->image.size, 4096);
270*d83cc019SAndroid Build Coastguard Worker 	drmIoctl(priv->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
271*d83cc019SAndroid Build Coastguard Worker 	if (create.handle == 0)
272*d83cc019SAndroid Build Coastguard Worker 		goto err_fd;
273*d83cc019SAndroid Build Coastguard Worker 
274*d83cc019SAndroid Build Coastguard Worker 	priv->image.handle = create.handle;
275*d83cc019SAndroid Build Coastguard Worker 
276*d83cc019SAndroid Build Coastguard Worker 	if (!kms_create_fb(priv->fd, &priv->image))
277*d83cc019SAndroid Build Coastguard Worker 		goto err_create;
278*d83cc019SAndroid Build Coastguard Worker 
279*d83cc019SAndroid Build Coastguard Worker 	/* XXX set color keys */
280*d83cc019SAndroid Build Coastguard Worker 
281*d83cc019SAndroid Build Coastguard Worker 	if (!attach_to_crtc(priv->fd, priv->crtc, 0, 0, &priv->image))
282*d83cc019SAndroid Build Coastguard Worker 		goto err_fb;
283*d83cc019SAndroid Build Coastguard Worker 	detach_from_crtc(priv->fd, priv->crtc);
284*d83cc019SAndroid Build Coastguard Worker 
285*d83cc019SAndroid Build Coastguard Worker 	map.handle = create.handle;
286*d83cc019SAndroid Build Coastguard Worker 	if (drmIoctl(priv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &map))
287*d83cc019SAndroid Build Coastguard Worker 		goto err_fb;
288*d83cc019SAndroid Build Coastguard Worker 
289*d83cc019SAndroid Build Coastguard Worker 	priv->image.map = mmap(0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, priv->fd, map.offset);
290*d83cc019SAndroid Build Coastguard Worker 	if (priv->image.map == (void *)-1)
291*d83cc019SAndroid Build Coastguard Worker 		goto err_fb;
292*d83cc019SAndroid Build Coastguard Worker 
293*d83cc019SAndroid Build Coastguard Worker 	priv->mem = malloc(create.size);
294*d83cc019SAndroid Build Coastguard Worker 	if (priv->mem == NULL)
295*d83cc019SAndroid Build Coastguard Worker 		goto err_map;
296*d83cc019SAndroid Build Coastguard Worker 
297*d83cc019SAndroid Build Coastguard Worker 	priv->base.surface =
298*d83cc019SAndroid Build Coastguard Worker 		cairo_image_surface_create_for_data(priv->mem,
299*d83cc019SAndroid Build Coastguard Worker 						    CAIRO_FORMAT_RGB24,
300*d83cc019SAndroid Build Coastguard Worker 						    priv->image.width,
301*d83cc019SAndroid Build Coastguard Worker 						    priv->image.height,
302*d83cc019SAndroid Build Coastguard Worker 						    priv->image.stride);
303*d83cc019SAndroid Build Coastguard Worker 	if (cairo_surface_status(priv->base.surface))
304*d83cc019SAndroid Build Coastguard Worker 		goto err_mem;
305*d83cc019SAndroid Build Coastguard Worker 
306*d83cc019SAndroid Build Coastguard Worker 	priv->base.show = kms_overlay_show;
307*d83cc019SAndroid Build Coastguard Worker 	priv->base.hide = kms_overlay_hide;
308*d83cc019SAndroid Build Coastguard Worker 
309*d83cc019SAndroid Build Coastguard Worker 	priv->visible = false;
310*d83cc019SAndroid Build Coastguard Worker 	priv->x = 0;
311*d83cc019SAndroid Build Coastguard Worker 	priv->y = 0;
312*d83cc019SAndroid Build Coastguard Worker 
313*d83cc019SAndroid Build Coastguard Worker 	cairo_surface_set_user_data(priv->base.surface, &overlay_key, priv, kms_overlay_destroy);
314*d83cc019SAndroid Build Coastguard Worker 
315*d83cc019SAndroid Build Coastguard Worker 	*width = priv->image.width;
316*d83cc019SAndroid Build Coastguard Worker 	*height = priv->image.height;
317*d83cc019SAndroid Build Coastguard Worker 
318*d83cc019SAndroid Build Coastguard Worker 	drmIoctl(priv->fd, DRM_IOCTL_GEM_CLOSE, &create.handle);
319*d83cc019SAndroid Build Coastguard Worker 	return priv->base.surface;
320*d83cc019SAndroid Build Coastguard Worker 
321*d83cc019SAndroid Build Coastguard Worker err_mem:
322*d83cc019SAndroid Build Coastguard Worker 	free(priv->mem);
323*d83cc019SAndroid Build Coastguard Worker err_map:
324*d83cc019SAndroid Build Coastguard Worker 	munmap(priv->image.map, create.size);
325*d83cc019SAndroid Build Coastguard Worker err_fb:
326*d83cc019SAndroid Build Coastguard Worker 	drmIoctl(priv->fd, DRM_IOCTL_MODE_RMFB, &priv->image.name);
327*d83cc019SAndroid Build Coastguard Worker err_create:
328*d83cc019SAndroid Build Coastguard Worker 	drmIoctl(priv->fd, DRM_IOCTL_GEM_CLOSE, &create.handle);
329*d83cc019SAndroid Build Coastguard Worker err_fd:
330*d83cc019SAndroid Build Coastguard Worker 	close(priv->fd);
331*d83cc019SAndroid Build Coastguard Worker err_priv:
332*d83cc019SAndroid Build Coastguard Worker 	free(priv);
333*d83cc019SAndroid Build Coastguard Worker 	return NULL;
334*d83cc019SAndroid Build Coastguard Worker }
335