blob: 5c501af56935d5b35004541412003c8aa5709422 [file] [log] [blame]
Stéphane Marchesin25a26062014-09-12 16:18:59 -07001/*
2 * Copyright (c) 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
Yuly Novikov96c7a3b2015-12-08 22:48:29 -05007#include <assert.h>
Dominik Behrf7b33d72014-11-11 07:17:11 -08008#include <fcntl.h>
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -08009#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
Stéphane Marchesin25a26062014-09-12 16:18:59 -070013#include <xf86drm.h>
14
15#include "gbm_priv.h"
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -080016#include "helpers.h"
Stéphane Marchesin25a26062014-09-12 16:18:59 -070017#include "util.h"
18
Stéphane Marchesin25a26062014-09-12 16:18:59 -070019extern struct gbm_driver gbm_driver_cirrus;
Bartosz Bieleckie24f2ca2016-01-07 16:57:10 +010020extern struct gbm_driver gbm_driver_evdi;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070021#ifdef GBM_EXYNOS
22extern struct gbm_driver gbm_driver_exynos;
23#endif
24extern struct gbm_driver gbm_driver_gma500;
25#ifdef GBM_I915
26extern struct gbm_driver gbm_driver_i915;
27#endif
Daniel Blum080405c2015-12-01 22:46:09 -080028#ifdef GBM_MARVELL
29extern struct gbm_driver gbm_driver_marvell;
30#endif
JB Tsai0c16a0f2015-03-19 14:30:31 +080031#ifdef GBM_MEDIATEK
32extern struct gbm_driver gbm_driver_mediatek;
33#endif
Stéphane Marchesin25a26062014-09-12 16:18:59 -070034#ifdef GBM_ROCKCHIP
35extern struct gbm_driver gbm_driver_rockchip;
36#endif
37#ifdef GBM_TEGRA
38extern struct gbm_driver gbm_driver_tegra;
39#endif
40extern struct gbm_driver gbm_driver_udl;
Vincent Palatin5ecebea2016-03-11 14:05:45 -080041extern struct gbm_driver gbm_driver_virtio_gpu;
Stéphane Marchesin25a26062014-09-12 16:18:59 -070042
43static struct gbm_driver *gbm_get_driver(int fd)
44{
45 drmVersionPtr drm_version;
46 unsigned int i;
47
48 drm_version = drmGetVersion(fd);
49
50 if (!drm_version)
51 return NULL;
52
53 struct gbm_driver *driver_list[] = {
54 &gbm_driver_cirrus,
Bartosz Bieleckie24f2ca2016-01-07 16:57:10 +010055 &gbm_driver_evdi,
Stéphane Marchesin25a26062014-09-12 16:18:59 -070056#ifdef GBM_EXYNOS
57 &gbm_driver_exynos,
58#endif
59 &gbm_driver_gma500,
60#ifdef GBM_I915
61 &gbm_driver_i915,
62#endif
Daniel Blum080405c2015-12-01 22:46:09 -080063#ifdef GBM_MARVELL
64 &gbm_driver_marvell,
65#endif
JB Tsai0c16a0f2015-03-19 14:30:31 +080066#ifdef GBM_MEDIATEK
67 &gbm_driver_mediatek,
68#endif
Stéphane Marchesin25a26062014-09-12 16:18:59 -070069#ifdef GBM_ROCKCHIP
70 &gbm_driver_rockchip,
71#endif
72#ifdef GBM_TEGRA
73 &gbm_driver_tegra,
74#endif
75 &gbm_driver_udl,
Vincent Palatin5ecebea2016-03-11 14:05:45 -080076 &gbm_driver_virtio_gpu,
Stéphane Marchesin25a26062014-09-12 16:18:59 -070077 };
78
79 for(i = 0; i < ARRAY_SIZE(driver_list); i++)
80 if (!strcmp(drm_version->name, driver_list[i]->name))
81 {
82 drmFreeVersion(drm_version);
83 return driver_list[i];
84 }
85
86 drmFreeVersion(drm_version);
87 return NULL;
88}
89
90PUBLIC int
91gbm_device_get_fd(struct gbm_device *gbm)
92{
93 return gbm->fd;
94}
95
96PUBLIC const char *
97gbm_device_get_backend_name(struct gbm_device *gbm)
98{
99 return gbm->driver->name;
100}
101
102PUBLIC int
103gbm_device_is_format_supported(struct gbm_device *gbm,
Stéphane Marchesinec88e892015-11-03 16:14:59 -0800104 uint32_t format, uint32_t usage)
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700105{
106 unsigned i;
107
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700108 if (usage & GBM_BO_USE_CURSOR &&
109 usage & GBM_BO_USE_RENDERING)
110 return 0;
111
112 for(i = 0 ; i < ARRAY_SIZE(gbm->driver->format_list); i++)
113 {
114 if (!gbm->driver->format_list[i].format)
115 break;
116
117 if (gbm->driver->format_list[i].format == format &&
118 (gbm->driver->format_list[i].usage & usage) == usage)
119 return 1;
120 }
121
122 return 0;
123}
124
125PUBLIC struct gbm_device *gbm_create_device(int fd)
126{
127 struct gbm_device *gbm;
128 int ret;
129
130 gbm = (struct gbm_device*) malloc(sizeof(*gbm));
131 if (!gbm)
132 return NULL;
133
134 gbm->fd = fd;
135
136 gbm->driver = gbm_get_driver(fd);
137 if (!gbm->driver) {
138 free(gbm);
139 return NULL;
140 }
141
142 if (gbm->driver->init) {
143 ret = gbm->driver->init(gbm);
144 if (ret) {
145 free(gbm);
146 return NULL;
147 }
148 }
149
150 return gbm;
151}
152
153PUBLIC void gbm_device_destroy(struct gbm_device *gbm)
154{
155 if (gbm->driver->close)
156 gbm->driver->close(gbm);
157 free(gbm);
158}
159
Stéphane Marchesinec88e892015-11-03 16:14:59 -0800160PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm,
161 uint32_t width, uint32_t height,
162 uint32_t format, uint32_t flags)
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700163{
Stéphane Marchesinec88e892015-11-03 16:14:59 -0800164 struct gbm_surface *surface =
165 (struct gbm_surface*) malloc(sizeof(*surface));
166
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700167 if (!surface)
168 return NULL;
169
170 return surface;
171}
172
173PUBLIC void gbm_surface_destroy(struct gbm_surface *surface)
174{
175 free(surface);
176}
177
178PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface)
179{
180 return NULL;
181}
182
Stéphane Marchesinec88e892015-11-03 16:14:59 -0800183PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface,
184 struct gbm_bo *bo)
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700185{
186}
187
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800188static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm,
189 uint32_t width, uint32_t height,
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500190 uint32_t format)
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700191{
192 struct gbm_bo *bo;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700193
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500194 bo = (struct gbm_bo*) calloc(1, sizeof(*bo));
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700195 if (!bo)
196 return NULL;
197
198 bo->gbm = gbm;
199 bo->width = width;
200 bo->height = height;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700201 bo->format = format;
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500202 bo->num_planes = gbm_num_planes_from_format(format);
203 if (!bo->num_planes) {
204 free(bo);
205 return NULL;
206 }
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700207
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800208 return bo;
209}
210
211PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width,
212 uint32_t height, uint32_t format,
213 uint32_t flags)
214{
215 struct gbm_bo *bo;
216 int ret;
217
Zach Reizner4fcc3c72016-02-25 11:44:36 -0800218 if (!gbm_device_is_format_supported(gbm, format, flags))
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500219 return NULL;
220
221 bo = gbm_bo_new(gbm, width, height, format);
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800222 if (!bo)
223 return NULL;
224
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700225 ret = gbm->driver->bo_create(bo, width, height, format, flags);
226 if (ret) {
227 free(bo);
228 return NULL;
229 }
230
231 return bo;
232}
233
234PUBLIC void gbm_bo_destroy(struct gbm_bo *bo)
235{
236 if (bo->destroy_user_data) {
237 bo->destroy_user_data(bo, bo->user_data);
238 bo->destroy_user_data = NULL;
239 bo->user_data = NULL;
240 }
241
242 bo->gbm->driver->bo_destroy(bo);
243 free(bo);
244}
245
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800246PUBLIC struct gbm_bo *
247gbm_bo_import(struct gbm_device *gbm, uint32_t type,
248 void *buffer, uint32_t usage)
249{
250 struct gbm_import_fd_data *fd_data = buffer;
251 struct gbm_bo *bo;
252 struct drm_prime_handle prime_handle;
253 int ret;
254
255 if (type != GBM_BO_IMPORT_FD)
256 return NULL;
257
258 if (!gbm_device_is_format_supported(gbm, fd_data->format, usage))
259 return NULL;
260
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500261 /* This function can support only single plane formats. */
262 /* If multi-plane import is desired, new function should be added. */
263 if (gbm_num_planes_from_format(fd_data->format) != 1)
264 return NULL;
265
266 bo = gbm_bo_new(gbm, fd_data->width, fd_data->height, fd_data->format);
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800267 if (!bo)
268 return NULL;
269
Stéphane Marchesine04c9b52016-03-11 22:01:35 -0800270 bo->strides[0] = fd_data->stride;
271 bo->sizes[0] = fd_data->height * fd_data->stride;
272
Vincent Palatinab9e5e02016-04-08 10:03:52 -0700273 memset(&prime_handle, 0, sizeof(prime_handle));
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800274 prime_handle.fd = fd_data->fd;
275
276 ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
277 if (ret) {
278 fprintf(stderr, "minigbm: DRM_IOCTL_PRIME_FD_TO_HANDLE failed "
279 "(fd=%u)\n", prime_handle.fd);
280 free(bo);
281 return NULL;
282 }
283
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500284 bo->handles[0].u32 = prime_handle.handle;
Stéphane Marchesinf4bfdba2015-11-05 11:43:59 -0800285
286 return bo;
287}
288
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700289PUBLIC uint32_t
290gbm_bo_get_width(struct gbm_bo *bo)
291{
292 return bo->width;
293}
294
295PUBLIC uint32_t
296gbm_bo_get_height(struct gbm_bo *bo)
297{
298 return bo->height;
299}
300
301PUBLIC uint32_t
302gbm_bo_get_stride(struct gbm_bo *bo)
303{
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500304 return gbm_bo_get_plane_stride(bo, 0);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700305}
306
307PUBLIC uint32_t
Lauri Peltonen7842d8f2014-12-17 23:01:37 -0800308gbm_bo_get_stride_or_tiling(struct gbm_bo *bo)
309{
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500310 return bo->tiling ? bo->tiling : gbm_bo_get_stride(bo);
Lauri Peltonen7842d8f2014-12-17 23:01:37 -0800311}
312
313PUBLIC uint32_t
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700314gbm_bo_get_format(struct gbm_bo *bo)
315{
316 return bo->format;
317}
318
Vince Hsua6878fe2016-05-23 10:32:25 +0800319PUBLIC uint64_t
320gbm_bo_get_format_modifier(struct gbm_bo *bo)
321{
322 return gbm_bo_get_plane_format_modifier(bo, 0);
323}
324
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700325PUBLIC struct gbm_device *
326gbm_bo_get_device(struct gbm_bo *bo)
327{
328 return bo->gbm;
329}
330
331PUBLIC union gbm_bo_handle
332gbm_bo_get_handle(struct gbm_bo *bo)
333{
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500334 return gbm_bo_get_plane_handle(bo, 0);
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700335}
336
337PUBLIC int
338gbm_bo_get_fd(struct gbm_bo *bo)
339{
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500340 return gbm_bo_get_plane_fd(bo, 0);
341}
Stéphane Marchesin5bb6adc2014-11-05 20:21:25 -0800342
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500343PUBLIC size_t
344gbm_bo_get_num_planes(struct gbm_bo *bo)
345{
346 return bo->num_planes;
347}
348
349PUBLIC union gbm_bo_handle
350gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane)
351{
352 assert(plane < bo->num_planes);
353 return bo->handles[plane];
354}
355
Tiago Vignattib96ffe12016-01-26 10:32:27 -0200356#ifndef DRM_RDWR
357#define DRM_RDWR O_RDWR
358#endif
359
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500360PUBLIC int
361gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane)
362{
363 int fd;
364 assert(plane < bo->num_planes);
365
366 if (drmPrimeHandleToFD(
367 gbm_device_get_fd(bo->gbm),
368 gbm_bo_get_plane_handle(bo, plane).u32,
Tiago Vignattib96ffe12016-01-26 10:32:27 -0200369 DRM_CLOEXEC | DRM_RDWR,
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500370 &fd))
Dominik Behrf7b33d72014-11-11 07:17:11 -0800371 return -1;
Zach Reiznerd224eaa2015-01-09 11:25:02 -0800372 else
373 return fd;
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700374}
375
Yuly Novikov96c7a3b2015-12-08 22:48:29 -0500376PUBLIC uint32_t
377gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane)
378{
379 assert(plane < bo->num_planes);
380 return bo->offsets[plane];
381}
382
383PUBLIC uint32_t
384gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane)
385{
386 assert(plane < bo->num_planes);
387 return bo->sizes[plane];
388}
389
390PUBLIC uint32_t
391gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane)
392{
393 assert(plane < bo->num_planes);
394 return bo->strides[plane];
395}
396
Vince Hsua6878fe2016-05-23 10:32:25 +0800397PUBLIC uint64_t
398gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane)
399{
400 assert(plane < bo->num_planes);
401 return bo->format_modifiers[plane];
402}
403
Stéphane Marchesin25a26062014-09-12 16:18:59 -0700404PUBLIC void
405gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
406 void (*destroy_user_data)(struct gbm_bo *, void *))
407{
408 bo->user_data = data;
409 bo->destroy_user_data = destroy_user_data;
410}
411
412PUBLIC void *
413gbm_bo_get_user_data(struct gbm_bo *bo)
414{
415 return bo->user_data;
416}