OSDN Git Service

minigbm: Add userspace reference counting
[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 <xf86drm.h>
13
14 #include "drv_priv.h"
15 #include "helpers.h"
16 #include "util.h"
17
18 size_t drv_num_planes_from_format(uint32_t format)
19 {
20         switch(format)
21         {
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         }
73
74         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
75         return 0;
76 }
77
78 int drv_bpp_from_format(uint32_t format)
79 {
80         switch(format)
81         {
82                 case DRV_FORMAT_C8:
83                 case DRV_FORMAT_R8:
84                 case DRV_FORMAT_RGB332:
85                 case DRV_FORMAT_BGR233:
86                         return 8;
87
88                 case DRV_FORMAT_NV12:
89                         return 12;
90
91                 case DRV_FORMAT_RG88:
92                 case DRV_FORMAT_GR88:
93                 case DRV_FORMAT_XRGB4444:
94                 case DRV_FORMAT_XBGR4444:
95                 case DRV_FORMAT_RGBX4444:
96                 case DRV_FORMAT_BGRX4444:
97                 case DRV_FORMAT_ARGB4444:
98                 case DRV_FORMAT_ABGR4444:
99                 case DRV_FORMAT_RGBA4444:
100                 case DRV_FORMAT_BGRA4444:
101                 case DRV_FORMAT_XRGB1555:
102                 case DRV_FORMAT_XBGR1555:
103                 case DRV_FORMAT_RGBX5551:
104                 case DRV_FORMAT_BGRX5551:
105                 case DRV_FORMAT_ARGB1555:
106                 case DRV_FORMAT_ABGR1555:
107                 case DRV_FORMAT_RGBA5551:
108                 case DRV_FORMAT_BGRA5551:
109                 case DRV_FORMAT_RGB565:
110                 case DRV_FORMAT_BGR565:
111                 case DRV_FORMAT_YUYV:
112                 case DRV_FORMAT_YVYU:
113                 case DRV_FORMAT_UYVY:
114                 case DRV_FORMAT_VYUY:
115                         return 16;
116
117                 case DRV_FORMAT_RGB888:
118                 case DRV_FORMAT_BGR888:
119                         return 24;
120
121                 case DRV_FORMAT_XRGB8888:
122                 case DRV_FORMAT_XBGR8888:
123                 case DRV_FORMAT_RGBX8888:
124                 case DRV_FORMAT_BGRX8888:
125                 case DRV_FORMAT_ARGB8888:
126                 case DRV_FORMAT_ABGR8888:
127                 case DRV_FORMAT_RGBA8888:
128                 case DRV_FORMAT_BGRA8888:
129                 case DRV_FORMAT_XRGB2101010:
130                 case DRV_FORMAT_XBGR2101010:
131                 case DRV_FORMAT_RGBX1010102:
132                 case DRV_FORMAT_BGRX1010102:
133                 case DRV_FORMAT_ARGB2101010:
134                 case DRV_FORMAT_ABGR2101010:
135                 case DRV_FORMAT_RGBA1010102:
136                 case DRV_FORMAT_BGRA1010102:
137                 case DRV_FORMAT_AYUV:
138                         return 32;
139         }
140
141         fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
142         return 0;
143 }
144
145 int drv_stride_from_format(uint32_t format, uint32_t width)
146 {
147         /* Only single-plane formats are supported */
148         assert(drv_num_planes_from_format(format) == 1);
149         return DIV_ROUND_UP(width * drv_bpp_from_format(format), 8);
150 }
151
152 int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height,
153                        uint32_t format, uint32_t flags)
154 {
155         struct drm_mode_create_dumb create_dumb;
156         int ret;
157
158         /* Only single-plane formats are supported */
159         assert(drv_num_planes_from_format(format) == 1);
160
161         memset(&create_dumb, 0, sizeof(create_dumb));
162         create_dumb.height = height;
163         create_dumb.width = width;
164         create_dumb.bpp = drv_bpp_from_format(format);
165         create_dumb.flags = 0;
166
167         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
168         if (ret) {
169                 fprintf(stderr, "drv: DRM_IOCTL_MODE_CREATE_DUMB failed\n");
170                 return ret;
171         }
172
173         bo->handles[0].u32 = create_dumb.handle;
174         bo->offsets[0] = 0;
175         bo->sizes[0] = create_dumb.size;
176         bo->strides[0] = create_dumb.pitch;
177
178         return 0;
179 }
180
181 int drv_dumb_bo_destroy(struct bo *bo)
182 {
183         struct drm_mode_destroy_dumb destroy_dumb;
184         int ret;
185
186         memset(&destroy_dumb, 0, sizeof(destroy_dumb));
187         destroy_dumb.handle = bo->handles[0].u32;
188
189         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
190         if (ret) {
191                 fprintf(stderr, "drv: DRM_IOCTL_MODE_DESTROY_DUMB failed "
192                                 "(handle=%x)\n", bo->handles[0].u32);
193                 return ret;
194         }
195
196         return 0;
197 }
198
199 int drv_gem_bo_destroy(struct bo *bo)
200 {
201         struct drm_gem_close gem_close;
202         int ret, error = 0;
203         size_t plane, i;
204
205         for (plane = 0; plane < bo->num_planes; plane++) {
206                 for (i = 0; i < plane; i++)
207                         if (bo->handles[i].u32 == bo->handles[plane].u32)
208                                 break;
209                 /* Make sure close hasn't already been called on this handle */
210                 if (i != plane)
211                         continue;
212
213                 memset(&gem_close, 0, sizeof(gem_close));
214                 gem_close.handle = bo->handles[plane].u32;
215
216                 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
217                 if (ret) {
218                         fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed "
219                                         "(handle=%x) error %d\n",
220                                         bo->handles[plane].u32, ret);
221                         error = ret;
222                 }
223         }
224
225         return error;
226 }
227
228 uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo,
229                                   size_t plane)
230 {
231         void *count;
232         uintptr_t num = 0;
233
234         if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count))
235                 num = (uintptr_t) (count);
236
237         return num;
238 }
239
240 void drv_increment_reference_count(struct driver *drv, struct bo *bo,
241                                    size_t plane)
242 {
243         uintptr_t num = drv_get_reference_count(drv, bo, plane);
244
245         /* If a value isn't in the table, drmHashDelete is a no-op */
246         drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
247         drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
248                       (void *) (num + 1));
249 }
250
251 void drv_decrement_reference_count(struct driver *drv, struct bo *bo,
252                                    size_t plane)
253 {
254         uintptr_t num = drv_get_reference_count(drv, bo, plane);
255
256         drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
257
258         if (num > 0)
259                 drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
260                               (void *) (num - 1));
261 }