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