xref: /aosp_15_r20/external/minigbm/gbm.c (revision d95af8df99a05bcb8679a54dc3ab8e5cd312b38e)
1 /*
2  * Copyright 2014 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/mman.h>
14 #include <xf86drm.h>
15 
16 #include "drv.h"
17 #include "gbm_helpers.h"
18 #include "gbm_priv.h"
19 #include "util.h"
20 
gbm_device_get_fd(struct gbm_device * gbm)21 PUBLIC int gbm_device_get_fd(struct gbm_device *gbm)
22 {
23 
24 	return drv_get_fd(gbm->drv);
25 }
26 
gbm_device_get_backend_name(struct gbm_device * gbm)27 PUBLIC const char *gbm_device_get_backend_name(struct gbm_device *gbm)
28 {
29 	return drv_get_name(gbm->drv);
30 }
31 
gbm_device_is_format_supported(struct gbm_device * gbm,uint32_t format,uint32_t usage)32 PUBLIC int gbm_device_is_format_supported(struct gbm_device *gbm, uint32_t format, uint32_t usage)
33 {
34 	uint64_t use_flags;
35 
36 	if (usage & GBM_BO_USE_CURSOR && usage & GBM_BO_USE_RENDERING)
37 		return 0;
38 
39 	use_flags = gbm_convert_usage(usage);
40 
41 	return (drv_get_combination(gbm->drv, format, use_flags) != NULL);
42 }
43 
gbm_device_get_format_modifier_plane_count(struct gbm_device * gbm,uint32_t format,uint64_t modifier)44 PUBLIC int gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm, uint32_t format,
45 						      uint64_t modifier)
46 {
47 	return 0;
48 }
49 
gbm_create_device(int fd)50 PUBLIC struct gbm_device *gbm_create_device(int fd)
51 {
52 	struct gbm_device *gbm;
53 
54 	gbm = (struct gbm_device *)malloc(sizeof(*gbm));
55 
56 	if (!gbm)
57 		return NULL;
58 
59 	gbm->drv = drv_create(fd);
60 	if (!gbm->drv) {
61 		free(gbm);
62 		return NULL;
63 	}
64 
65 	return gbm;
66 }
67 
gbm_device_destroy(struct gbm_device * gbm)68 PUBLIC void gbm_device_destroy(struct gbm_device *gbm)
69 {
70 	drv_destroy(gbm->drv);
71 	free(gbm);
72 }
73 
gbm_surface_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)74 PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm, uint32_t width,
75 					      uint32_t height, uint32_t format, uint32_t usage)
76 {
77 	struct gbm_surface *surface = (struct gbm_surface *)malloc(sizeof(*surface));
78 
79 	if (!surface)
80 		return NULL;
81 
82 	return surface;
83 }
84 
gbm_surface_create_with_modifiers(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,const unsigned int count)85 PUBLIC struct gbm_surface *gbm_surface_create_with_modifiers(struct gbm_device *gbm, uint32_t width,
86 							     uint32_t height, uint32_t format,
87 							     const uint64_t *modifiers,
88 							     const unsigned int count)
89 {
90 	return gbm_surface_create_with_modifiers2(gbm, width, height, format, modifiers, count, 0);
91 }
92 
93 PUBLIC struct gbm_surface *
gbm_surface_create_with_modifiers2(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,const unsigned int count,uint32_t flags)94 gbm_surface_create_with_modifiers2(struct gbm_device *gbm, uint32_t width, uint32_t height,
95 				   uint32_t format, const uint64_t *modifiers,
96 				   const unsigned int count, uint32_t flags)
97 {
98 	if (count != 0 || modifiers != NULL)
99 		return NULL;
100 
101 	if (flags != 0)
102 		return NULL;
103 
104 	return gbm_surface_create(gbm, width, height, format, flags);
105 }
106 
gbm_surface_lock_front_buffer(struct gbm_surface * surface)107 PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface)
108 {
109 	return NULL;
110 }
111 
gbm_surface_release_buffer(struct gbm_surface * surface,struct gbm_bo * bo)112 PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo)
113 {
114 }
115 
gbm_surface_has_free_buffers(struct gbm_surface * surface)116 PUBLIC int gbm_surface_has_free_buffers(struct gbm_surface *surface)
117 {
118 	return 0;
119 }
120 
gbm_surface_destroy(struct gbm_surface * surface)121 PUBLIC void gbm_surface_destroy(struct gbm_surface *surface)
122 {
123 	free(surface);
124 }
125 
gbm_bo_new(struct gbm_device * gbm,uint32_t format)126 static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm, uint32_t format)
127 {
128 	struct gbm_bo *bo;
129 
130 	bo = (struct gbm_bo *)calloc(1, sizeof(*bo));
131 	if (!bo)
132 		return NULL;
133 
134 	bo->gbm = gbm;
135 	bo->gbm_format = format;
136 
137 	return bo;
138 }
139 
gbm_bo_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)140 PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height,
141 				    uint32_t format, uint32_t usage)
142 {
143 	struct gbm_bo *bo;
144 
145 	if (!gbm_device_is_format_supported(gbm, format, usage))
146 		return NULL;
147 
148 	bo = gbm_bo_new(gbm, format);
149 
150 	if (!bo)
151 		return NULL;
152 
153 	/*
154 	 * HACK: See b/132939420. This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None
155 	 * of our platforms can display YV12, so we can treat as a SW buffer. Remove once this can
156 	 * be intelligently resolved in the guest. Also see virgl_resolve_use_flags.
157 	 */
158 	if (format == GBM_FORMAT_YVU420 && (usage & GBM_BO_USE_LINEAR))
159 		format = DRM_FORMAT_YVU420_ANDROID;
160 
161 	bo->bo = drv_bo_create(gbm->drv, width, height, format, gbm_convert_usage(usage));
162 
163 	if (!bo->bo) {
164 		free(bo);
165 		return NULL;
166 	}
167 
168 	return bo;
169 }
170 
gbm_bo_create_with_modifiers(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,uint32_t count)171 PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t width,
172 						   uint32_t height, uint32_t format,
173 						   const uint64_t *modifiers, uint32_t count)
174 {
175 	return gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers, count, 0);
176 }
177 
gbm_bo_create_with_modifiers2(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,const unsigned int count,uint32_t flags)178 PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers2(struct gbm_device *gbm, uint32_t width,
179 						    uint32_t height, uint32_t format,
180 						    const uint64_t *modifiers,
181 						    const unsigned int count, uint32_t flags)
182 {
183 	struct gbm_bo *bo;
184 
185 	if (flags != 0)
186 		return NULL;
187 
188 	bo = gbm_bo_new(gbm, format);
189 
190 	if (!bo)
191 		return NULL;
192 
193 	bo->bo = drv_bo_create_with_modifiers(gbm->drv, width, height, format, modifiers, count);
194 
195 	if (!bo->bo) {
196 		free(bo);
197 		return NULL;
198 	}
199 
200 	return bo;
201 }
202 
gbm_bo_destroy(struct gbm_bo * bo)203 PUBLIC void gbm_bo_destroy(struct gbm_bo *bo)
204 {
205 	if (bo->destroy_user_data) {
206 		bo->destroy_user_data(bo, bo->user_data);
207 		bo->destroy_user_data = NULL;
208 		bo->user_data = NULL;
209 	}
210 
211 	drv_bo_destroy(bo->bo);
212 	free(bo);
213 }
214 
gbm_bo_import(struct gbm_device * gbm,uint32_t type,void * buffer,uint32_t usage)215 PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer,
216 				    uint32_t usage)
217 {
218 	struct gbm_bo *bo;
219 	struct drv_import_fd_data drv_data = { 0 };
220 	struct gbm_import_fd_data *fd_data = buffer;
221 	struct gbm_import_fd_modifier_data *fd_modifier_data = buffer;
222 	uint32_t gbm_format;
223 	size_t num_planes, i, num_fds;
224 
225 	drv_data.use_flags = gbm_convert_usage(usage);
226 	switch (type) {
227 	case GBM_BO_IMPORT_FD:
228 		gbm_format = fd_data->format;
229 		drv_data.width = fd_data->width;
230 		drv_data.height = fd_data->height;
231 		drv_data.format = fd_data->format;
232 		drv_data.fds[0] = fd_data->fd;
233 		drv_data.strides[0] = fd_data->stride;
234 		drv_data.format_modifier = DRM_FORMAT_MOD_INVALID;
235 
236 		break;
237 	case GBM_BO_IMPORT_FD_MODIFIER:
238 		gbm_format = fd_modifier_data->format;
239 		drv_data.width = fd_modifier_data->width;
240 		drv_data.height = fd_modifier_data->height;
241 		drv_data.format = fd_modifier_data->format;
242 		num_planes = drv_num_planes_from_modifier(gbm->drv, drv_data.format,
243 							  fd_modifier_data->modifier);
244 		assert(num_planes);
245 
246 		num_fds = fd_modifier_data->num_fds;
247 		if (!num_fds || num_fds > num_planes)
248 			return NULL;
249 
250 		drv_data.format_modifier = fd_modifier_data->modifier;
251 		for (i = 0; i < num_planes; i++) {
252 			if (num_fds != num_planes)
253 				drv_data.fds[i] = fd_modifier_data->fds[0];
254 			else
255 				drv_data.fds[i] = fd_modifier_data->fds[i];
256 			drv_data.offsets[i] = fd_modifier_data->offsets[i];
257 			drv_data.strides[i] = fd_modifier_data->strides[i];
258 		}
259 
260 		for (i = num_planes; i < GBM_MAX_PLANES; i++)
261 			drv_data.fds[i] = -1;
262 
263 		break;
264 	default:
265 		return NULL;
266 	}
267 
268 	if (!gbm_device_is_format_supported(gbm, gbm_format, usage))
269 		return NULL;
270 
271 	bo = gbm_bo_new(gbm, gbm_format);
272 
273 	if (!bo)
274 		return NULL;
275 
276 	bo->bo = drv_bo_import(gbm->drv, &drv_data);
277 
278 	if (!bo->bo) {
279 		free(bo);
280 		return NULL;
281 	}
282 
283 	return bo;
284 }
285 
gbm_bo_map(struct gbm_bo * bo,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t transfer_flags,uint32_t * stride,void ** map_data)286 PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
287 			uint32_t transfer_flags, uint32_t *stride, void **map_data)
288 {
289 	return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, 0);
290 }
291 
gbm_bo_get_map_info(struct gbm_bo * bo)292 PUBLIC enum gbm_bo_map_cache_mode gbm_bo_get_map_info(struct gbm_bo *bo)
293 {
294 	if (drv_bo_cached(bo->bo))
295 		return GBM_BO_MAP_CACHE_CACHED;
296 	return GBM_BO_MAP_CACHE_WC;
297 }
298 
gbm_bo_unmap(struct gbm_bo * bo,void * map_data)299 PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
300 {
301 	assert(bo);
302 	drv_bo_flush_or_unmap(bo->bo, map_data);
303 }
304 
gbm_bo_get_width(struct gbm_bo * bo)305 PUBLIC uint32_t gbm_bo_get_width(struct gbm_bo *bo)
306 {
307 	return drv_bo_get_width(bo->bo);
308 }
309 
gbm_bo_get_height(struct gbm_bo * bo)310 PUBLIC uint32_t gbm_bo_get_height(struct gbm_bo *bo)
311 {
312 	return drv_bo_get_height(bo->bo);
313 }
314 
gbm_bo_get_stride(struct gbm_bo * bo)315 PUBLIC uint32_t gbm_bo_get_stride(struct gbm_bo *bo)
316 {
317 	return gbm_bo_get_stride_for_plane(bo, 0);
318 }
319 
gbm_bo_get_format(struct gbm_bo * bo)320 PUBLIC uint32_t gbm_bo_get_format(struct gbm_bo *bo)
321 {
322 	return bo->gbm_format;
323 }
324 
gbm_bo_get_bpp(struct gbm_bo * bo)325 PUBLIC uint32_t gbm_bo_get_bpp(struct gbm_bo *bo)
326 {
327 	return drv_bytes_per_pixel_from_format(drv_bo_get_format(bo->bo), 0);
328 }
329 
gbm_bo_get_modifier(struct gbm_bo * bo)330 PUBLIC uint64_t gbm_bo_get_modifier(struct gbm_bo *bo)
331 {
332 	return drv_bo_get_format_modifier(bo->bo);
333 }
334 
gbm_bo_get_device(struct gbm_bo * bo)335 PUBLIC struct gbm_device *gbm_bo_get_device(struct gbm_bo *bo)
336 {
337 	return bo->gbm;
338 }
339 
gbm_bo_get_handle(struct gbm_bo * bo)340 PUBLIC union gbm_bo_handle gbm_bo_get_handle(struct gbm_bo *bo)
341 {
342 	return gbm_bo_get_handle_for_plane(bo, 0);
343 }
344 
gbm_bo_get_fd(struct gbm_bo * bo)345 PUBLIC int gbm_bo_get_fd(struct gbm_bo *bo)
346 {
347 	return gbm_bo_get_plane_fd(bo, 0);
348 }
349 
gbm_bo_get_plane_count(struct gbm_bo * bo)350 PUBLIC int gbm_bo_get_plane_count(struct gbm_bo *bo)
351 {
352 	return drv_bo_get_num_planes(bo->bo);
353 }
354 
gbm_bo_get_handle_for_plane(struct gbm_bo * bo,int plane)355 PUBLIC union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane)
356 {
357 	return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, (size_t)plane).u64;
358 }
359 
gbm_bo_get_fd_for_plane(struct gbm_bo * bo,int plane)360 PUBLIC int gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane)
361 {
362 	return drv_bo_get_plane_fd(bo->bo, plane);
363 }
364 
gbm_bo_get_offset(struct gbm_bo * bo,int plane)365 PUBLIC uint32_t gbm_bo_get_offset(struct gbm_bo *bo, int plane)
366 {
367 	return drv_bo_get_plane_offset(bo->bo, (size_t)plane);
368 }
369 
gbm_bo_get_stride_for_plane(struct gbm_bo * bo,int plane)370 PUBLIC uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane)
371 {
372 	return drv_bo_get_plane_stride(bo->bo, (size_t)plane);
373 }
374 
gbm_bo_set_user_data(struct gbm_bo * bo,void * data,void (* destroy_user_data)(struct gbm_bo *,void *))375 PUBLIC void gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
376 				 void (*destroy_user_data)(struct gbm_bo *, void *))
377 {
378 	bo->user_data = data;
379 	bo->destroy_user_data = destroy_user_data;
380 }
381 
gbm_bo_get_user_data(struct gbm_bo * bo)382 PUBLIC void *gbm_bo_get_user_data(struct gbm_bo *bo)
383 {
384 	return bo->user_data;
385 }
386 
387 /* The two GBM_BO_FORMAT_[XA]RGB8888 formats alias the GBM_FORMAT_*
388  * formats of the same name. We want to accept them whenever someone
389  * has a GBM format, but never return them to the user.
390  */
gbm_format_canonicalize(uint32_t gbm_format)391 static uint32_t gbm_format_canonicalize(uint32_t gbm_format)
392 {
393 	switch (gbm_format) {
394 	case GBM_BO_FORMAT_XRGB8888:
395 		return GBM_FORMAT_XRGB8888;
396 	case GBM_BO_FORMAT_ARGB8888:
397 		return GBM_FORMAT_ARGB8888;
398 	default:
399 		return gbm_format;
400 	}
401 }
402 
403 /**
404  * Returns a string representing the fourcc format name.
405  */
gbm_format_get_name(uint32_t gbm_format,struct gbm_format_name_desc * desc)406 PUBLIC char *gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc)
407 {
408 	gbm_format = gbm_format_canonicalize(gbm_format);
409 
410 	desc->name[0] = gbm_format;
411 	desc->name[1] = gbm_format >> 8;
412 	desc->name[2] = gbm_format >> 16;
413 	desc->name[3] = gbm_format >> 24;
414 	desc->name[4] = 0;
415 
416 	return desc->name;
417 }
418 
419 /*
420  * The following functions are not deprecated, but not in the Mesa the gbm
421  * header. The main difference is minigbm allows for the possibility of
422  * disjoint YUV images, while Mesa GBM does not.
423  */
gbm_bo_get_plane_size(struct gbm_bo * bo,size_t plane)424 PUBLIC uint32_t gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane)
425 {
426 	return drv_bo_get_plane_size(bo->bo, plane);
427 }
428 
gbm_bo_get_plane_fd(struct gbm_bo * bo,size_t plane)429 PUBLIC int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane)
430 {
431 	return drv_bo_get_plane_fd(bo->bo, plane);
432 }
433 
gbm_bo_map2(struct gbm_bo * bo,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t transfer_flags,uint32_t * stride,void ** map_data,int plane)434 PUBLIC void *gbm_bo_map2(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
435 			 uint32_t transfer_flags, uint32_t *stride, void **map_data, int plane)
436 {
437 	void *addr;
438 	off_t offset;
439 	uint32_t map_flags;
440 	plane = (size_t)plane;
441 	struct rectangle rect = { .x = x, .y = y, .width = width, .height = height };
442 	if (!bo || width == 0 || height == 0 || !stride || !map_data)
443 		return NULL;
444 
445 	map_flags = (transfer_flags & GBM_BO_TRANSFER_READ) ? BO_MAP_READ : BO_MAP_NONE;
446 	map_flags |= (transfer_flags & GBM_BO_TRANSFER_WRITE) ? BO_MAP_WRITE : BO_MAP_NONE;
447 
448 	addr = drv_bo_map(bo->bo, &rect, map_flags, (struct mapping **)map_data, plane);
449 	if (addr == MAP_FAILED)
450 		return MAP_FAILED;
451 
452 	*stride = ((struct mapping *)*map_data)->vma->map_strides[plane];
453 
454 	offset = *stride * rect.y;
455 	offset += rect.x * drv_bytes_per_pixel_from_format(bo->gbm_format, plane);
456 	return (void *)((uint8_t *)addr + offset);
457 }
458