1 /*
2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3 * Copyright (C) 2010-2011 LunarG Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #define LOG_TAG "GRALLOC-MOD"
25
26 #include <cutils/log.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <pthread.h>
30 #include <errno.h>
31
32 #include "gralloc_drm.h"
33 #include "gralloc_drm_priv.h"
34
35 /*
36 * Initialize the DRM device object
37 */
drm_init(struct drm_module_t * dmod)38 static int drm_init(struct drm_module_t *dmod)
39 {
40 int err = 0;
41
42 pthread_mutex_lock(&dmod->mutex);
43 if (!dmod->drm) {
44 dmod->drm = gralloc_drm_create();
45 if (!dmod->drm)
46 err = -EINVAL;
47 }
48 pthread_mutex_unlock(&dmod->mutex);
49
50 return err;
51 }
52
drm_mod_perform(const struct gralloc_module_t * mod,int op,...)53 static int drm_mod_perform(const struct gralloc_module_t *mod, int op, ...)
54 {
55 struct drm_module_t *dmod = (struct drm_module_t *) mod;
56 va_list args;
57 int err;
58
59 err = drm_init(dmod);
60 if (err)
61 return err;
62
63 va_start(args, op);
64 switch (op) {
65 case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_DRM_FD):
66 {
67 int *fd = va_arg(args, int *);
68 *fd = gralloc_drm_get_fd(dmod->drm);
69 err = 0;
70 }
71 break;
72 default:
73 err = -EINVAL;
74 break;
75 }
76 va_end(args);
77
78 return err;
79 }
80
drm_mod_register_buffer(const gralloc_module_t * mod,buffer_handle_t handle)81 static int drm_mod_register_buffer(const gralloc_module_t *mod,
82 buffer_handle_t handle)
83 {
84 struct drm_module_t *dmod = (struct drm_module_t *) mod;
85 int err;
86
87 err = drm_init(dmod);
88 if (err)
89 return err;
90
91 return gralloc_drm_handle_register(handle, dmod->drm);
92 }
93
drm_mod_unregister_buffer(const gralloc_module_t * mod,buffer_handle_t handle)94 static int drm_mod_unregister_buffer(const gralloc_module_t *mod,
95 buffer_handle_t handle)
96 {
97 return gralloc_drm_handle_unregister(handle);
98 }
99
drm_mod_lock(const gralloc_module_t * mod,buffer_handle_t handle,int usage,int x,int y,int w,int h,void ** ptr)100 static int drm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle,
101 int usage, int x, int y, int w, int h, void **ptr)
102 {
103 struct gralloc_drm_bo_t *bo;
104 int err;
105
106 bo = gralloc_drm_bo_from_handle(handle);
107 if (!bo)
108 return -EINVAL;
109
110 return gralloc_drm_bo_lock(bo, usage, x, y, w, h, ptr);
111 }
112
drm_mod_lock_ycbcr(const gralloc_module_t * mod,buffer_handle_t bhandle,int usage,int x,int y,int w,int h,struct android_ycbcr * ycbcr)113 static int drm_mod_lock_ycbcr(const gralloc_module_t *mod, buffer_handle_t bhandle,
114 int usage, int x, int y, int w, int h, struct android_ycbcr *ycbcr)
115 {
116 struct gralloc_drm_handle_t *handle;
117 struct gralloc_drm_bo_t *bo;
118 void *ptr;
119 int err;
120
121 bo = gralloc_drm_bo_from_handle(bhandle);
122 if (!bo)
123 return -EINVAL;
124 handle = bo->handle;
125
126 switch(handle->format) {
127 case HAL_PIXEL_FORMAT_YCbCr_420_888:
128 break;
129 default:
130 return -EINVAL;
131 }
132
133 err = gralloc_drm_bo_lock(bo, usage, x, y, w, h, &ptr);
134 if (err)
135 return err;
136
137 switch(handle->format) {
138 case HAL_PIXEL_FORMAT_YCbCr_420_888:
139 ycbcr->y = ptr;
140 ycbcr->cb = (uint8_t *)ptr + handle->stride * handle->height;
141 ycbcr->cr = (uint8_t *)ycbcr->cb + 1;
142 ycbcr->ystride = handle->stride;
143 ycbcr->cstride = handle->stride;
144 ycbcr->chroma_step = 2;
145 break;
146 default:
147 break;
148 }
149
150 return 0;
151 }
152
drm_mod_unlock(const gralloc_module_t * mod,buffer_handle_t handle)153 static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle)
154 {
155 struct drm_module_t *dmod = (struct drm_module_t *) mod;
156 struct gralloc_drm_bo_t *bo;
157
158 bo = gralloc_drm_bo_from_handle(handle);
159 if (!bo)
160 return -EINVAL;
161
162 gralloc_drm_bo_unlock(bo);
163
164 return 0;
165 }
166
drm_mod_close_gpu0(struct hw_device_t * dev)167 static int drm_mod_close_gpu0(struct hw_device_t *dev)
168 {
169 struct drm_module_t *dmod = (struct drm_module_t *)dev->module;
170 struct alloc_device_t *alloc = (struct alloc_device_t *) dev;
171
172 gralloc_drm_destroy(dmod->drm);
173 delete alloc;
174
175 return 0;
176 }
177
drm_mod_free_gpu0(alloc_device_t * dev,buffer_handle_t handle)178 static int drm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle)
179 {
180 struct drm_module_t *dmod = (struct drm_module_t *) dev->common.module;
181 struct gralloc_drm_bo_t *bo;
182
183 bo = gralloc_drm_bo_from_handle(handle);
184 if (!bo)
185 return -EINVAL;
186
187 gralloc_drm_bo_decref(bo);
188
189 return 0;
190 }
191
drm_mod_alloc_gpu0(alloc_device_t * dev,int w,int h,int format,int usage,buffer_handle_t * handle,int * stride)192 static int drm_mod_alloc_gpu0(alloc_device_t *dev,
193 int w, int h, int format, int usage,
194 buffer_handle_t *handle, int *stride)
195 {
196 struct drm_module_t *dmod = (struct drm_module_t *) dev->common.module;
197 struct gralloc_drm_bo_t *bo;
198 int size, bpp, err;
199
200 bpp = gralloc_drm_get_bpp(format);
201 if (!bpp)
202 return -EINVAL;
203
204 bo = gralloc_drm_bo_create(dmod->drm, w, h, format, usage);
205 if (!bo)
206 return -ENOMEM;
207
208 *handle = gralloc_drm_bo_get_handle(bo, stride);
209 /* in pixels */
210 *stride /= bpp;
211
212 return 0;
213 }
214
drm_mod_open_gpu0(struct drm_module_t * dmod,hw_device_t ** dev)215 static int drm_mod_open_gpu0(struct drm_module_t *dmod, hw_device_t **dev)
216 {
217 struct alloc_device_t *alloc;
218 int err;
219
220 err = drm_init(dmod);
221 if (err)
222 return err;
223
224 alloc = new alloc_device_t;
225 if (!alloc)
226 return -EINVAL;
227
228 alloc->common.tag = HARDWARE_DEVICE_TAG;
229 alloc->common.version = 0;
230 alloc->common.module = &dmod->base.common;
231 alloc->common.close = drm_mod_close_gpu0;
232
233 alloc->alloc = drm_mod_alloc_gpu0;
234 alloc->free = drm_mod_free_gpu0;
235
236 *dev = &alloc->common;
237
238 return 0;
239 }
240
drm_mod_open(const struct hw_module_t * mod,const char * name,struct hw_device_t ** dev)241 static int drm_mod_open(const struct hw_module_t *mod,
242 const char *name, struct hw_device_t **dev)
243 {
244 struct drm_module_t *dmod = (struct drm_module_t *) mod;
245 int err;
246
247 if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0)
248 err = drm_mod_open_gpu0(dmod, dev);
249 else
250 err = -EINVAL;
251
252 return err;
253 }
254
255 static struct hw_module_methods_t drm_mod_methods = {
256 .open = drm_mod_open
257 };
258
259 struct drm_module_t HAL_MODULE_INFO_SYM = {
260 .base = {
261 .common = {
262 .tag = HARDWARE_MODULE_TAG,
263 .version_major = 1,
264 .version_minor = 0,
265 .id = GRALLOC_HARDWARE_MODULE_ID,
266 .name = "DRM Memory Allocator",
267 .author = "Chia-I Wu",
268 .methods = &drm_mod_methods
269 },
270 .registerBuffer = drm_mod_register_buffer,
271 .unregisterBuffer = drm_mod_unregister_buffer,
272 .lock = drm_mod_lock,
273 .unlock = drm_mod_unlock,
274 .perform = drm_mod_perform,
275 .lock_ycbcr = drm_mod_lock_ycbcr,
276 },
277
278 .mutex = PTHREAD_MUTEX_INITIALIZER,
279 .drm = NULL
280 };
281