OSDN Git Service

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