OSDN Git Service

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