OSDN Git Service

minigbm: Add AMDGPU minigbm driver
[android-x86/external-minigbm.git] / helpers.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 <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/mman.h>
13 #include <xf86drm.h>
14
15 #include "drv_priv.h"
16 #include "helpers.h"
17 #include "util.h"
18
19 size_t drv_num_planes_from_format(uint32_t format)
20 {
21         switch (format) {
22         case DRV_FORMAT_C8:
23         case DRV_FORMAT_R8:
24         case DRV_FORMAT_RG88:
25         case DRV_FORMAT_GR88:
26         case DRV_FORMAT_RGB332:
27         case DRV_FORMAT_BGR233:
28         case DRV_FORMAT_XRGB4444:
29         case DRV_FORMAT_XBGR4444:
30         case DRV_FORMAT_RGBX4444:
31         case DRV_FORMAT_BGRX4444:
32         case DRV_FORMAT_ARGB4444:
33         case DRV_FORMAT_ABGR4444:
34         case DRV_FORMAT_RGBA4444:
35         case DRV_FORMAT_BGRA4444:
36         case DRV_FORMAT_XRGB1555:
37         case DRV_FORMAT_XBGR1555:
38         case DRV_FORMAT_RGBX5551:
39         case DRV_FORMAT_BGRX5551:
40         case DRV_FORMAT_ARGB1555:
41         case DRV_FORMAT_ABGR1555:
42         case DRV_FORMAT_RGBA5551:
43         case DRV_FORMAT_BGRA5551:
44         case DRV_FORMAT_RGB565:
45         case DRV_FORMAT_BGR565:
46         case DRV_FORMAT_YUYV:
47         case DRV_FORMAT_YVYU:
48         case DRV_FORMAT_UYVY:
49         case DRV_FORMAT_VYUY:
50         case DRV_FORMAT_RGB888:
51         case DRV_FORMAT_BGR888:
52         case DRV_FORMAT_XRGB8888:
53         case DRV_FORMAT_XBGR8888:
54         case DRV_FORMAT_RGBX8888:
55         case DRV_FORMAT_BGRX8888:
56         case DRV_FORMAT_ARGB8888:
57         case DRV_FORMAT_ABGR8888:
58         case DRV_FORMAT_RGBA8888:
59         case DRV_FORMAT_BGRA8888:
60         case DRV_FORMAT_XRGB2101010:
61         case DRV_FORMAT_XBGR2101010:
62         case DRV_FORMAT_RGBX1010102:
63         case DRV_FORMAT_BGRX1010102:
64         case DRV_FORMAT_ARGB2101010:
65         case DRV_FORMAT_ABGR2101010:
66         case DRV_FORMAT_RGBA1010102:
67         case DRV_FORMAT_BGRA1010102:
68         case DRV_FORMAT_AYUV:
69                 return 1;
70         case DRV_FORMAT_NV12:
71                 return 2;
72         case DRV_FORMAT_YVU420:
73                 return 3;
74         }
75
76         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
77         return 0;
78 }
79
80 int drv_bpp_from_format(uint32_t format, size_t plane)
81 {
82         assert(plane < drv_num_planes_from_format(format));
83
84         switch (format) {
85         case DRV_FORMAT_C8:
86         case DRV_FORMAT_R8:
87         case DRV_FORMAT_RGB332:
88         case DRV_FORMAT_BGR233:
89                 return 8;
90
91         case DRV_FORMAT_NV12:
92                 return (plane == 0) ? 8 : 4;
93         case DRV_FORMAT_YVU420:
94                 return (plane == 0) ? 8 : 2;
95
96         case DRV_FORMAT_RG88:
97         case DRV_FORMAT_GR88:
98         case DRV_FORMAT_XRGB4444:
99         case DRV_FORMAT_XBGR4444:
100         case DRV_FORMAT_RGBX4444:
101         case DRV_FORMAT_BGRX4444:
102         case DRV_FORMAT_ARGB4444:
103         case DRV_FORMAT_ABGR4444:
104         case DRV_FORMAT_RGBA4444:
105         case DRV_FORMAT_BGRA4444:
106         case DRV_FORMAT_XRGB1555:
107         case DRV_FORMAT_XBGR1555:
108         case DRV_FORMAT_RGBX5551:
109         case DRV_FORMAT_BGRX5551:
110         case DRV_FORMAT_ARGB1555:
111         case DRV_FORMAT_ABGR1555:
112         case DRV_FORMAT_RGBA5551:
113         case DRV_FORMAT_BGRA5551:
114         case DRV_FORMAT_RGB565:
115         case DRV_FORMAT_BGR565:
116         case DRV_FORMAT_YUYV:
117         case DRV_FORMAT_YVYU:
118         case DRV_FORMAT_UYVY:
119         case DRV_FORMAT_VYUY:
120                 return 16;
121
122         case DRV_FORMAT_RGB888:
123         case DRV_FORMAT_BGR888:
124                 return 24;
125
126         case DRV_FORMAT_XRGB8888:
127         case DRV_FORMAT_XBGR8888:
128         case DRV_FORMAT_RGBX8888:
129         case DRV_FORMAT_BGRX8888:
130         case DRV_FORMAT_ARGB8888:
131         case DRV_FORMAT_ABGR8888:
132         case DRV_FORMAT_RGBA8888:
133         case DRV_FORMAT_BGRA8888:
134         case DRV_FORMAT_XRGB2101010:
135         case DRV_FORMAT_XBGR2101010:
136         case DRV_FORMAT_RGBX1010102:
137         case DRV_FORMAT_BGRX1010102:
138         case DRV_FORMAT_ARGB2101010:
139         case DRV_FORMAT_ABGR2101010:
140         case DRV_FORMAT_RGBA1010102:
141         case DRV_FORMAT_BGRA1010102:
142         case DRV_FORMAT_AYUV:
143                 return 32;
144         }
145
146         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
147         return 0;
148 }
149
150 /*
151  * This function returns the stride for a given format, width and plane.
152  */
153 int drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
154 {
155         /* Get stride of the first plane */
156         int stride = width * DIV_ROUND_UP(drv_bpp_from_format(format, 0), 8);
157
158         /*
159          * Only downsample for certain multiplanar formats which are not
160          * interleaved and have horizontal subsampling.  Only formats supported
161          * by our drivers are listed here -- add more as needed.
162          */
163         if (plane != 0) {
164                 switch (format) {
165                 case DRV_FORMAT_YVU420:
166                         stride = stride / 2;
167                 }
168         }
169
170         return stride;
171 }
172
173 /*
174  * This function fills in the buffer object given driver aligned dimensions
175  * and a format.  This function assumes there is just one kernel buffer per
176  * buffer object.
177  */
178 int drv_bo_from_format(struct bo *bo, uint32_t width, uint32_t height,
179                        drv_format_t format)
180 {
181
182         switch (format) {
183         case DRV_FORMAT_YVU420:
184                 bo->strides[0] = drv_stride_from_format(format, width, 0);
185                 bo->strides[1] = drv_stride_from_format(format, width, 1);
186                 bo->strides[2] = drv_stride_from_format(format, width, 2);
187                 bo->sizes[0] = height * bo->strides[0];
188                 bo->sizes[1] = bo->sizes[2] = (height / 2) * bo->strides[1];
189                 bo->offsets[0] = 0;
190                 bo->offsets[1] = bo->sizes[0];
191                 bo->offsets[2] = bo->offsets[1] + bo->sizes[1];
192                 break;
193         case DRV_FORMAT_NV12:
194                 bo->strides[0] = drv_stride_from_format(format, width, 0);
195                 bo->strides[1] = drv_stride_from_format(format, width, 1);
196                 bo->sizes[0] = height * bo->strides[0];
197                 bo->sizes[1] = height * bo->strides[1] / 2;
198                 bo->offsets[0] = 0;
199                 bo->offsets[1] = height * bo->strides[0];
200                 break;
201         default:
202                 bo->strides[0] = drv_stride_from_format(format, width, 0);
203                 bo->sizes[0] = height * bo->strides[0];
204                 bo->offsets[0] = 0;
205         }
206
207         bo->total_size = bo->offsets[bo->num_planes - 1] +
208                          bo->sizes[bo->num_planes - 1];
209
210         return 0;
211 }
212
213 int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height,
214                        uint32_t format, uint32_t flags)
215 {
216         struct drm_mode_create_dumb create_dumb;
217         int ret;
218
219         /* Only single-plane formats are supported */
220         assert(drv_num_planes_from_format(format) == 1);
221
222         memset(&create_dumb, 0, sizeof(create_dumb));
223         create_dumb.height = height;
224         create_dumb.width = width;
225         create_dumb.bpp = drv_bpp_from_format(format, 0);
226         create_dumb.flags = 0;
227
228         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
229         if (ret) {
230                 fprintf(stderr, "drv: DRM_IOCTL_MODE_CREATE_DUMB failed\n");
231                 return ret;
232         }
233
234         bo->handles[0].u32 = create_dumb.handle;
235         bo->offsets[0] = 0;
236         bo->total_size = bo->sizes[0] = create_dumb.size;
237         bo->strides[0] = create_dumb.pitch;
238
239         return 0;
240 }
241
242 int drv_dumb_bo_destroy(struct bo *bo)
243 {
244         struct drm_mode_destroy_dumb destroy_dumb;
245         int ret;
246
247         memset(&destroy_dumb, 0, sizeof(destroy_dumb));
248         destroy_dumb.handle = bo->handles[0].u32;
249
250         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
251         if (ret) {
252                 fprintf(stderr, "drv: DRM_IOCTL_MODE_DESTROY_DUMB failed "
253                                 "(handle=%x)\n", bo->handles[0].u32);
254                 return ret;
255         }
256
257         return 0;
258 }
259
260 int drv_gem_bo_destroy(struct bo *bo)
261 {
262         struct drm_gem_close gem_close;
263         int ret, error = 0;
264         size_t plane, i;
265
266         for (plane = 0; plane < bo->num_planes; plane++) {
267                 for (i = 0; i < plane; i++)
268                         if (bo->handles[i].u32 == bo->handles[plane].u32)
269                                 break;
270                 /* Make sure close hasn't already been called on this handle */
271                 if (i != plane)
272                         continue;
273
274                 memset(&gem_close, 0, sizeof(gem_close));
275                 gem_close.handle = bo->handles[plane].u32;
276
277                 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
278                 if (ret) {
279                         fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed "
280                                         "(handle=%x) error %d\n",
281                                         bo->handles[plane].u32, ret);
282                         error = ret;
283                 }
284         }
285
286         return error;
287 }
288
289 void *drv_dumb_bo_map(struct bo *bo)
290 {
291         int ret;
292         struct drm_mode_map_dumb map_dumb;
293
294         memset(&map_dumb, 0, sizeof(map_dumb));
295         map_dumb.handle = bo->handles[0].u32;
296
297         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
298         if (ret) {
299                 fprintf(stderr, "drv: DRM_IOCTL_MODE_MAP_DUMB failed \n");
300                 return MAP_FAILED;
301         }
302
303         return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED,
304                     bo->drv->fd, map_dumb.offset);
305 }
306
307 uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo,
308                                   size_t plane)
309 {
310         void *count;
311         uintptr_t num = 0;
312
313         if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count))
314                 num = (uintptr_t) (count);
315
316         return num;
317 }
318
319 void drv_increment_reference_count(struct driver *drv, struct bo *bo,
320                                    size_t plane)
321 {
322         uintptr_t num = drv_get_reference_count(drv, bo, plane);
323
324         /* If a value isn't in the table, drmHashDelete is a no-op */
325         drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
326         drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
327                       (void *) (num + 1));
328 }
329
330 void drv_decrement_reference_count(struct driver *drv, struct bo *bo,
331                                    size_t plane)
332 {
333         uintptr_t num = drv_get_reference_count(drv, bo, plane);
334
335         drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
336
337         if (num > 0)
338                 drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
339                               (void *) (num - 1));
340 }
341
342 uint32_t drv_num_buffers_per_bo(struct bo *bo)
343 {
344         uint32_t count = 0;
345         size_t plane, p;
346
347         for (plane = 0; plane < bo->num_planes; plane++) {
348                 for (p = 0; p < plane; p++) {
349                         if (bo->handles[p].u32 == bo->handles[plane].u32)
350                                 break;
351                 }
352
353                 if (p == plane)
354                         count++;
355         }
356
357         return count;
358 }
359
360 uint32_t drv_log_base2(uint32_t value)
361 {
362         int ret = 0;
363
364         while (value >>= 1)
365                 ++ret;
366
367         return ret;
368 }
369