OSDN Git Service

Support multi-plane buffers.
[android-x86/external-minigbm.git] / gbm.c
1 /*
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
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 <xf86drm.h>
14
15 #include "gbm_priv.h"
16 #include "helpers.h"
17 #include "util.h"
18
19 extern struct gbm_driver gbm_driver_cirrus;
20 extern struct gbm_driver gbm_driver_evdi;
21 #ifdef GBM_EXYNOS
22 extern struct gbm_driver gbm_driver_exynos;
23 #endif
24 extern struct gbm_driver gbm_driver_gma500;
25 #ifdef GBM_I915
26 extern struct gbm_driver gbm_driver_i915;
27 #endif
28 #ifdef GBM_MARVELL
29 extern struct gbm_driver gbm_driver_marvell;
30 #endif
31 #ifdef GBM_MEDIATEK
32 extern struct gbm_driver gbm_driver_mediatek;
33 #endif
34 #ifdef GBM_ROCKCHIP
35 extern struct gbm_driver gbm_driver_rockchip;
36 #endif
37 #ifdef GBM_TEGRA
38 extern struct gbm_driver gbm_driver_tegra;
39 #endif
40 extern struct gbm_driver gbm_driver_udl;
41
42 static struct gbm_driver *gbm_get_driver(int fd)
43 {
44         drmVersionPtr drm_version;
45         unsigned int i;
46
47         drm_version = drmGetVersion(fd);
48
49         if (!drm_version)
50                 return NULL;
51
52         struct gbm_driver *driver_list[] = {
53                 &gbm_driver_cirrus,
54                 &gbm_driver_evdi,
55 #ifdef GBM_EXYNOS
56                 &gbm_driver_exynos,
57 #endif
58                 &gbm_driver_gma500,
59 #ifdef GBM_I915
60                 &gbm_driver_i915,
61 #endif
62 #ifdef GBM_MARVELL
63                 &gbm_driver_marvell,
64 #endif
65 #ifdef GBM_MEDIATEK
66                 &gbm_driver_mediatek,
67 #endif
68 #ifdef GBM_ROCKCHIP
69                 &gbm_driver_rockchip,
70 #endif
71 #ifdef GBM_TEGRA
72                 &gbm_driver_tegra,
73 #endif
74                 &gbm_driver_udl,
75         };
76
77         for(i = 0; i < ARRAY_SIZE(driver_list); i++)
78                 if (!strcmp(drm_version->name, driver_list[i]->name))
79                 {
80                         drmFreeVersion(drm_version);
81                         return driver_list[i];
82                 }
83
84         drmFreeVersion(drm_version);
85         return NULL;
86 }
87
88 PUBLIC int
89 gbm_device_get_fd(struct gbm_device *gbm)
90 {
91         return gbm->fd;
92 }
93
94 PUBLIC const char *
95 gbm_device_get_backend_name(struct gbm_device *gbm)
96 {
97         return gbm->driver->name;
98 }
99
100 PUBLIC int
101 gbm_device_is_format_supported(struct gbm_device *gbm,
102                                uint32_t format, uint32_t usage)
103 {
104         unsigned i;
105
106         if (format == GBM_BO_FORMAT_XRGB8888)
107                 format = GBM_FORMAT_XRGB8888;
108         if (format == GBM_BO_FORMAT_ARGB8888)
109                 format = GBM_FORMAT_ARGB8888;
110
111         if (usage & GBM_BO_USE_CURSOR &&
112                 usage & GBM_BO_USE_RENDERING)
113                 return 0;
114
115         for(i = 0 ; i < ARRAY_SIZE(gbm->driver->format_list); i++)
116         {
117                 if (!gbm->driver->format_list[i].format)
118                         break;
119
120                 if (gbm->driver->format_list[i].format == format &&
121                         (gbm->driver->format_list[i].usage & usage) == usage)
122                         return 1;
123         }
124
125         return 0;
126 }
127
128 PUBLIC struct gbm_device *gbm_create_device(int fd)
129 {
130         struct gbm_device *gbm;
131         int ret;
132
133         gbm = (struct gbm_device*) malloc(sizeof(*gbm));
134         if (!gbm)
135                 return NULL;
136
137         gbm->fd = fd;
138
139         gbm->driver = gbm_get_driver(fd);
140         if (!gbm->driver) {
141                 free(gbm);
142                 return NULL;
143         }
144
145         if (gbm->driver->init) {
146                 ret = gbm->driver->init(gbm);
147                 if (ret) {
148                         free(gbm);
149                         return NULL;
150                 }
151         }
152
153         return gbm;
154 }
155
156 PUBLIC void gbm_device_destroy(struct gbm_device *gbm)
157 {
158         if (gbm->driver->close)
159                 gbm->driver->close(gbm);
160         free(gbm);
161 }
162
163 PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm,
164                                               uint32_t width, uint32_t height,
165                                               uint32_t format, uint32_t flags)
166 {
167         struct gbm_surface *surface =
168                 (struct gbm_surface*) malloc(sizeof(*surface));
169
170         if (!surface)
171                 return NULL;
172
173         return surface;
174 }
175
176 PUBLIC void gbm_surface_destroy(struct gbm_surface *surface)
177 {
178         free(surface);
179 }
180
181 PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface)
182 {
183         return NULL;
184 }
185
186 PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface,
187                                        struct gbm_bo *bo)
188 {
189 }
190
191 static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm,
192                                  uint32_t width, uint32_t height,
193                                  uint32_t format)
194 {
195         struct gbm_bo *bo;
196
197         bo = (struct gbm_bo*) calloc(1, sizeof(*bo));
198         if (!bo)
199                 return NULL;
200
201         bo->gbm = gbm;
202         bo->width = width;
203         bo->height = height;
204         bo->format = format;
205         bo->num_planes = gbm_num_planes_from_format(format);
206         if (!bo->num_planes) {
207                 free(bo);
208                 return NULL;
209         }
210
211         return bo;
212 }
213
214 PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width,
215                                     uint32_t height, uint32_t format,
216                                     uint32_t flags)
217 {
218         struct gbm_bo *bo;
219         int ret;
220
221         if (!gbm_device_is_format_supported(gbm, format, 0))
222                 return NULL;
223
224         bo = gbm_bo_new(gbm, width, height, format);
225         if (!bo)
226                 return NULL;
227
228         ret = gbm->driver->bo_create(bo, width, height, format, flags);
229         if (ret) {
230                 free(bo);
231                 return NULL;
232         }
233
234         return bo;
235 }
236
237 PUBLIC void gbm_bo_destroy(struct gbm_bo *bo)
238 {
239         if (bo->destroy_user_data) {
240                 bo->destroy_user_data(bo, bo->user_data);
241                 bo->destroy_user_data = NULL;
242                 bo->user_data = NULL;
243         }
244
245         bo->gbm->driver->bo_destroy(bo);
246         free(bo);
247 }
248
249 PUBLIC struct gbm_bo *
250 gbm_bo_import(struct gbm_device *gbm, uint32_t type,
251               void *buffer, uint32_t usage)
252 {
253         struct gbm_import_fd_data *fd_data = buffer;
254         struct gbm_bo *bo;
255         struct drm_prime_handle prime_handle;
256         int ret;
257
258         if (type != GBM_BO_IMPORT_FD)
259                 return NULL;
260
261         if (!gbm_device_is_format_supported(gbm, fd_data->format, usage))
262                 return NULL;
263
264         /* This function can support only single plane formats. */
265         /* If multi-plane import is desired, new function should be added. */
266         if (gbm_num_planes_from_format(fd_data->format) != 1)
267                 return NULL;
268
269         bo = gbm_bo_new(gbm, fd_data->width, fd_data->height, fd_data->format);
270         bo->strides[0] = fd_data->stride;
271
272         if (!bo)
273                 return NULL;
274
275         prime_handle.fd = fd_data->fd;
276
277         ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
278         if (ret) {
279                 fprintf(stderr, "minigbm: DRM_IOCTL_PRIME_FD_TO_HANDLE failed "
280                                 "(fd=%u)\n", prime_handle.fd);
281                 free(bo);
282                 return NULL;
283         }
284
285         bo->handles[0].u32 = prime_handle.handle;
286
287         return bo;
288 }
289
290 PUBLIC uint32_t
291 gbm_bo_get_width(struct gbm_bo *bo)
292 {
293         return bo->width;
294 }
295
296 PUBLIC uint32_t
297 gbm_bo_get_height(struct gbm_bo *bo)
298 {
299         return bo->height;
300 }
301
302 PUBLIC uint32_t
303 gbm_bo_get_stride(struct gbm_bo *bo)
304 {
305         return gbm_bo_get_plane_stride(bo, 0);
306 }
307
308 PUBLIC uint32_t
309 gbm_bo_get_stride_or_tiling(struct gbm_bo *bo)
310 {
311         return bo->tiling ? bo->tiling : gbm_bo_get_stride(bo);
312 }
313
314 PUBLIC uint32_t
315 gbm_bo_get_format(struct gbm_bo *bo)
316 {
317         return bo->format;
318 }
319
320 PUBLIC struct gbm_device *
321 gbm_bo_get_device(struct gbm_bo *bo)
322 {
323         return bo->gbm;
324 }
325
326 PUBLIC union gbm_bo_handle
327 gbm_bo_get_handle(struct gbm_bo *bo)
328 {
329         return gbm_bo_get_plane_handle(bo, 0);
330 }
331
332 PUBLIC int
333 gbm_bo_get_fd(struct gbm_bo *bo)
334 {
335         return gbm_bo_get_plane_fd(bo, 0);
336 }
337
338 PUBLIC size_t
339 gbm_bo_get_num_planes(struct gbm_bo *bo)
340 {
341         return bo->num_planes;
342 }
343
344 PUBLIC union gbm_bo_handle
345 gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane)
346 {
347         assert(plane < bo->num_planes);
348         return bo->handles[plane];
349 }
350
351 PUBLIC int
352 gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane)
353 {
354         int fd;
355         assert(plane < bo->num_planes);
356
357         if (drmPrimeHandleToFD(
358                         gbm_device_get_fd(bo->gbm),
359                         gbm_bo_get_plane_handle(bo, plane).u32,
360                         DRM_CLOEXEC,
361                         &fd))
362                 return -1;
363         else
364                 return fd;
365 }
366
367 PUBLIC uint32_t
368 gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane)
369 {
370         assert(plane < bo->num_planes);
371         return bo->offsets[plane];
372 }
373
374 PUBLIC uint32_t
375 gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane)
376 {
377         assert(plane < bo->num_planes);
378         return bo->sizes[plane];
379 }
380
381 PUBLIC uint32_t
382 gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane)
383 {
384         assert(plane < bo->num_planes);
385         return bo->strides[plane];
386 }
387
388 PUBLIC void
389 gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
390                      void (*destroy_user_data)(struct gbm_bo *, void *))
391 {
392         bo->user_data = data;
393         bo->destroy_user_data = destroy_user_data;
394 }
395
396 PUBLIC void *
397 gbm_bo_get_user_data(struct gbm_bo *bo)
398 {
399         return bo->user_data;
400 }