blob: 3d7af284610bf1b223481e35fdf73b03b7a5dd46
1 | /* |
2 | * Copyright (C) 2010 ARM Limited. All rights reserved. |
3 | * |
4 | * Copyright (C) 2008 The Android Open Source Project |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * You may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | */ |
18 | #define LOG_NDEBUG 0 |
19 | #define LOG_TAG "Gralloc" |
20 | |
21 | #include <errno.h> |
22 | #include <pthread.h> |
23 | |
24 | #include <cutils/log.h> |
25 | #include <cutils/atomic.h> |
26 | #include <hardware/hardware.h> |
27 | #include <hardware/gralloc.h> |
28 | |
29 | #include <hardware/hwcomposer_defs.h> |
30 | |
31 | #include "gralloc_priv.h" |
32 | #include "alloc_device.h" |
33 | #include "framebuffer_device.h" |
34 | |
35 | #include "gralloc_module_allocator_specific.h" |
36 | |
37 | #if MALI_AFBC_GRALLOC == 1 |
38 | #include "gralloc_buffer_priv.h" |
39 | #endif |
40 | |
41 | #include "format_chooser.h" |
42 | |
43 | static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER; |
44 | |
45 | static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) |
46 | { |
47 | int status = -EINVAL; |
48 | |
49 | if (!strncmp(name, GRALLOC_HARDWARE_GPU0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN)) |
50 | { |
51 | status = alloc_device_open(module, name, device); |
52 | } |
53 | else if (!strncmp(name, GRALLOC_HARDWARE_FB0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN)) |
54 | { |
55 | status = framebuffer_device_open(module, name, device); |
56 | } |
57 | |
58 | return status; |
59 | } |
60 | |
61 | static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle) |
62 | { |
63 | if (private_handle_t::validate(handle) < 0) |
64 | { |
65 | AERR("Registering invalid buffer %p, returning error", handle); |
66 | return -EINVAL; |
67 | } |
68 | |
69 | // if this handle was created in this process, then we keep it as is. |
70 | private_handle_t* hnd = (private_handle_t*)handle; |
71 | |
72 | if (hnd->pid == getpid()) |
73 | { |
74 | // If the handle is created and registered in the same process this is valid, |
75 | // but it could also be that application is registering twice which is illegal. |
76 | AWAR("Registering handle %p coming from the same process: %d.", hnd, hnd->pid); |
77 | } |
78 | |
79 | int retval = -EINVAL; |
80 | |
81 | pthread_mutex_lock(&s_map_lock); |
82 | |
83 | hnd->pid = getpid(); |
84 | |
85 | if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) |
86 | { |
87 | ALOGD("gralloc_register_buffer register framebuffer"); |
88 | hw_module_t * pmodule = NULL; |
89 | private_module_t *m = NULL; |
90 | if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0) |
91 | { |
92 | m = reinterpret_cast<private_module_t *>(pmodule); |
93 | } |
94 | else |
95 | { |
96 | AERR("Could not get gralloc module for handle: 0x%p", hnd); |
97 | retval = -errno; |
98 | goto cleanup; |
99 | } |
100 | |
101 | framebuffer_mapper_t* fbMaper = &(m->fb_primary); |
102 | if (hnd->usage & GRALLOC_USAGE_EXTERNAL_DISP) |
103 | { |
104 | ALOGD("register external display"); |
105 | fbMaper = &(m->fb_external); |
106 | } |
107 | if (!fbMaper->framebuffer) |
108 | { |
109 | fbMaper->framebuffer = new private_handle_t(hnd->flags, hnd->usage, hnd->size, hnd->base, 0, dup(hnd->fd), 0, 0); |
110 | fbMaper->bufferSize = hnd->offset; |
111 | fbMaper->numBuffers = fbMaper->framebuffer->size / fbMaper->bufferSize; |
112 | fbMaper->bufferMask = 0; |
113 | //ALOGE("fbMaper->bufferSize: 0x%08x, fbMaper->numBuffers: %d, fbMaper->framebuffer->size: 0x%08x", fbMaper->bufferSize, fbMaper->numBuffers, fbMaper->framebuffer->size); |
114 | |
115 | /* |
116 | * map the framebuffer |
117 | */ |
118 | #if MALI_AFBC_GRALLOC == 1 |
119 | void* vaddr = mmap(0, fbMaper->bufferSize, PROT_READ|PROT_WRITE, MAP_SHARED, fbMaper->framebuffer->fd, 0); |
120 | #else |
121 | void* vaddr = mmap(0, fbMaper->framebuffer->size, PROT_READ|PROT_WRITE, MAP_SHARED, fbMaper->framebuffer->fd, 0); |
122 | #endif |
123 | if (vaddr == MAP_FAILED) |
124 | { |
125 | AERR( "Error mapping the framebuffer (%s)", strerror(errno) ); |
126 | return -errno; |
127 | } |
128 | #if MALI_AFBC_GRALLOC == 1 |
129 | memset(vaddr, 0, fbMaper->bufferSize); |
130 | #else |
131 | memset(vaddr, 0, fbMaper->framebuffer->size); |
132 | #endif |
133 | fbMaper->framebuffer->base = vaddr; |
134 | |
135 | #if GRALLOC_ARM_UMP_MODULE |
136 | #ifdef IOCTL_GET_FB_UMP_SECURE_ID |
137 | ioctl(fbMaper->framebuffer->fd, IOCTL_GET_FB_UMP_SECURE_ID, &fbMaper->framebuffer->ump_id); |
138 | #endif |
139 | if ( (int)UMP_INVALID_SECURE_ID != fbMaper->framebuffer->ump_id ) |
140 | { |
141 | AINF("framebuffer accessed with UMP secure ID %i\n", fbMaper->framebuffer->ump_id); |
142 | } |
143 | #endif |
144 | ALOGD("register frame buffer count %d ",fbMaper->numBuffers ); |
145 | } else { |
146 | ALOGE("ERROR::register frambuffer again!!!"); |
147 | } |
148 | } |
149 | else if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | |
150 | private_handle_t::PRIV_FLAGS_USES_ION)) |
151 | { |
152 | retval = gralloc_backend_register(hnd); |
153 | } |
154 | else |
155 | { |
156 | AERR("registering non-UMP buffer not supported. flags = %d", hnd->flags ); |
157 | } |
158 | |
159 | cleanup: |
160 | pthread_mutex_unlock(&s_map_lock); |
161 | return retval; |
162 | } |
163 | |
164 | static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle) |
165 | { |
166 | if (private_handle_t::validate(handle) < 0) |
167 | { |
168 | AERR("unregistering invalid buffer %p, returning error", handle); |
169 | return -EINVAL; |
170 | } |
171 | |
172 | private_handle_t* hnd = (private_handle_t*)handle; |
173 | |
174 | AERR_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); |
175 | |
176 | if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) |
177 | { |
178 | pthread_mutex_lock(&s_map_lock); |
179 | |
180 | ALOGD("unregister framebuffer "); |
181 | //AERR( "Can't unregister buffer 0x%x as it is a framebuffer", (unsigned int)handle ); |
182 | hw_module_t * pmodule = NULL; |
183 | private_module_t *m = NULL; |
184 | if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0) |
185 | { |
186 | m = reinterpret_cast<private_module_t *>(pmodule); |
187 | framebuffer_mapper_t* fbMaper = &(m->fb_primary); |
188 | if (hnd->usage & GRALLOC_USAGE_EXTERNAL_DISP) |
189 | { |
190 | ALOGD("unregister external display"); |
191 | fbMaper = &(m->fb_external); |
192 | } |
193 | |
194 | if (fbMaper->framebuffer) |
195 | { |
196 | #if MALI_AFBC_GRALLOC == 1 |
197 | munmap((void*)fbMaper->framebuffer->base,fbMaper->bufferSize); |
198 | #else |
199 | munmap((void*)fbMaper->framebuffer->base,fbMaper->framebuffer->size); |
200 | #endif |
201 | close(fbMaper->framebuffer->fd); |
202 | //reset framebuffer info |
203 | delete fbMaper->framebuffer; |
204 | fbMaper->framebuffer = 0; |
205 | fbMaper->bufferMask = 0; |
206 | fbMaper->numBuffers = 0; |
207 | } else { |
208 | AERR("Can't unregister a not exist buffers: 0x%p", hnd); |
209 | } |
210 | } else { |
211 | AERR("Could not get gralloc module for handle: 0x%p", hnd); |
212 | } |
213 | // never unmap buffers that were not created in this process |
214 | } else if (hnd->pid == getpid()) { |
215 | pthread_mutex_lock(&s_map_lock); |
216 | |
217 | if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | |
218 | private_handle_t::PRIV_FLAGS_USES_ION)) |
219 | { |
220 | gralloc_backend_unregister(hnd); |
221 | } |
222 | else |
223 | { |
224 | AERR("Unregistering unknown buffer is not supported. Flags = %d", hnd->flags); |
225 | } |
226 | |
227 | #if MALI_AFBC_GRALLOC |
228 | /* |
229 | * Close shared attribute region file descriptor. It might seem strange to "free" |
230 | * this here since this can happen in a client process, but free here is nothing |
231 | * but unmapping and closing the duplicated file descriptor. The original ashmem |
232 | * fd instance is still open until alloc_device_free() is called. Even sharing |
233 | * of gralloc buffers within the same process should have fds dup:ed. |
234 | */ |
235 | gralloc_buffer_attr_free( hnd ); |
236 | |
237 | #endif |
238 | hnd->base = 0; |
239 | hnd->lockState = 0; |
240 | hnd->writeOwner = 0; |
241 | |
242 | pthread_mutex_unlock(&s_map_lock); |
243 | } |
244 | else |
245 | { |
246 | AERR( "Trying to unregister buffer %p from process %d that was not created in current process: %d", hnd, hnd->pid, getpid()); |
247 | } |
248 | |
249 | return 0; |
250 | } |
251 | |
252 | static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void** vaddr) |
253 | { |
254 | private_handle_t* hnd = (private_handle_t*)handle; |
255 | if (private_handle_t::validate(handle) < 0) |
256 | { |
257 | AERR("Locking invalid buffer %p, returning error", handle ); |
258 | return -EINVAL; |
259 | } |
260 | if (hnd->internal_format != hnd->format) |
261 | { |
262 | AERR("failed, this buffer may be compressed!!\n"); |
263 | } |
264 | |
265 | if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP || hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) |
266 | { |
267 | hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; |
268 | } |
269 | if ((usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) |
270 | || (usage & GRALLOC_USAGE_HW_CAMERA_MASK) |
271 | || (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) |
272 | { |
273 | *vaddr = (void*)hnd->base; |
274 | } |
275 | return 0; |
276 | } |
277 | |
278 | static int gralloc_lock_ycbcr(gralloc_module_t const* module, |
279 | buffer_handle_t handle, int usage, |
280 | int l, int t, int w, int h, |
281 | android_ycbcr *ycbcr) |
282 | { |
283 | private_module_t *gr = (private_module_t *)module; |
284 | private_handle_t *hnd = (private_handle_t *)handle; |
285 | |
286 | if (!ycbcr) { |
287 | AERR("gralloc_lock_ycbcr got NULL ycbcr struct"); |
288 | return -EINVAL; |
289 | } |
290 | if (hnd->internal_format != hnd->format) |
291 | { |
292 | AERR("failed, this buffer may be compressed!!\n"); |
293 | } |
294 | |
295 | if (!gr || (private_handle_t::validate(hnd) < 0)) { |
296 | AERR("gralloc_lock_ycbcr bad handle\n"); |
297 | return -EINVAL; |
298 | } |
299 | |
300 | // Validate usage |
301 | // For now, only allow camera write, software read. |
302 | bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK)); |
303 | bool hw_cam_write = (usage & GRALLOC_USAGE_HW_CAMERA_WRITE); |
304 | bool sw_read_allowed = (0 != (hnd->usage & GRALLOC_USAGE_SW_READ_MASK)); |
305 | |
306 | #if 0 |
307 | if ( (!hw_cam_write && !sw_read) || |
308 | (sw_read && !sw_read_allowed) ) { |
309 | AERR("gralloc_lock_ycbcr usage mismatch usage:0x%x cb->usage:0x%x\n", |
310 | usage, hnd->usage); |
311 | return -EINVAL; |
312 | } |
313 | #endif |
314 | |
315 | uint8_t *cpu_addr = NULL; |
316 | cpu_addr = (uint8_t *)hnd->base; |
317 | |
318 | // Calculate offsets to underlying YUV data |
319 | size_t yStride; |
320 | size_t cStride; |
321 | size_t yOffset; |
322 | size_t uOffset; |
323 | size_t vOffset; |
324 | size_t cStep; |
325 | switch (hnd->format) { |
326 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: //this is NV21 |
327 | case HAL_PIXEL_FORMAT_YCbCr_420_SP: |
328 | case HAL_PIXEL_FORMAT_YCbCr_420_888: |
329 | yStride = GRALLOC_ALIGN(hnd->width, YUV_MALI_PLANE_ALIGN); |
330 | cStride = GRALLOC_ALIGN(hnd->width, YUV_MALI_PLANE_ALIGN); |
331 | yOffset = 0; |
332 | vOffset = yStride * hnd->height; |
333 | uOffset = vOffset + 1; |
334 | cStep = 2; |
335 | break; |
336 | case HAL_PIXEL_FORMAT_YV12: |
337 | yStride = GRALLOC_ALIGN(hnd->width, YUV_ANDROID_PLANE_ALIGN); |
338 | cStride = GRALLOC_ALIGN(yStride / 2, YUV_ANDROID_PLANE_ALIGN); |
339 | yOffset = 0; |
340 | vOffset = yStride * hnd->height; |
341 | uOffset = vOffset + cStride * hnd->height / 2; |
342 | cStep = 1; |
343 | break; |
344 | default: |
345 | AERR("gralloc_lock_ycbcr unexpected internal format %x", |
346 | hnd->format); |
347 | return -EINVAL; |
348 | } |
349 | |
350 | ycbcr->y = cpu_addr + yOffset; |
351 | ycbcr->cb = cpu_addr + uOffset; |
352 | ycbcr->cr = cpu_addr + vOffset; |
353 | ycbcr->ystride = yStride; |
354 | ycbcr->cstride = cStride; |
355 | ycbcr->chroma_step = cStep; |
356 | |
357 | // Zero out reserved fields |
358 | memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved)); |
359 | |
360 | #if 0 |
361 | ALOGV("gralloc_lock_ycbcr success. usage: %x, ycbcr.y: %p, .cb: %p, .cr: %p, " |
362 | ".ystride: %d , .cstride: %d, .chroma_step: %d", usage, |
363 | ycbcr->y, ycbcr->cb, ycbcr->cr, ycbcr->ystride, ycbcr->cstride, |
364 | ycbcr->chroma_step); |
365 | #endif |
366 | |
367 | return 0; |
368 | } |
369 | |
370 | #if 0 |
371 | static int gralloc_lock_ycbcr(gralloc_module_t const* module, buffer_handle_t handle, int usage, |
372 | int l, int t, int w, int h, |
373 | android_ycbcr *ycbcr) |
374 | { |
375 | if (private_handle_t::validate(handle) < 0) |
376 | { |
377 | AERR("Locking invalid buffer %p, returning error", handle ); |
378 | return -EINVAL; |
379 | } |
380 | |
381 | private_handle_t* hnd = (private_handle_t*)handle; |
382 | |
383 | if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP || hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) |
384 | { |
385 | hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; |
386 | } |
387 | if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) |
388 | { |
389 | char* base = (char*)hnd->base; |
390 | int y_stride = hnd->byte_stride; |
391 | int y_size = y_stride * hnd->height; |
392 | |
393 | int u_offset = 0; |
394 | int v_offset = 0; |
395 | int c_stride = 0; |
396 | int step = 0; |
397 | |
398 | switch (hnd->internal_format & GRALLOC_ARM_INTFMT_FMT_MASK) |
399 | { |
400 | case HAL_PIXEL_FORMAT_YCbCr_420_888: /* Internally interpreted as NV12 */ |
401 | c_stride = y_stride; |
402 | /* Y plane, UV plane */ |
403 | u_offset = y_size; |
404 | v_offset = y_size + 1; |
405 | step = 2; |
406 | break; |
407 | |
408 | case HAL_PIXEL_FORMAT_YV12: |
409 | case GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12: |
410 | { |
411 | int c_size; |
412 | |
413 | /* Stride alignment set to 16 as the SW access flags were set */ |
414 | c_stride = GRALLOC_ALIGN(hnd->byte_stride / 2, 16); |
415 | c_size = c_stride * (hnd->height / 2); |
416 | /* Y plane, V plane, U plane */ |
417 | v_offset = y_size; |
418 | u_offset = y_size + c_size; |
419 | step = 1; |
420 | break; |
421 | } |
422 | |
423 | default: |
424 | AERR("Can't lock buffer %p: wrong format %llx", hnd, hnd->internal_format); |
425 | return -EINVAL; |
426 | } |
427 | |
428 | ycbcr->y = base; |
429 | ycbcr->cb = base + u_offset; |
430 | ycbcr->cr = base + v_offset; |
431 | ycbcr->ystride = y_stride; |
432 | ycbcr->cstride = c_stride; |
433 | ycbcr->chroma_step = step; |
434 | } |
435 | return 0; |
436 | } |
437 | #endif |
438 | |
439 | static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) |
440 | { |
441 | if (private_handle_t::validate(handle) < 0) |
442 | { |
443 | AERR( "Unlocking invalid buffer %p, returning error", handle ); |
444 | return -EINVAL; |
445 | } |
446 | |
447 | private_handle_t* hnd = (private_handle_t*)handle; |
448 | |
449 | if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | |
450 | private_handle_t::PRIV_FLAGS_USES_ION) |
451 | && hnd->writeOwner) |
452 | { |
453 | gralloc_backend_sync(hnd); |
454 | } |
455 | |
456 | return 0; |
457 | } |
458 | |
459 | // There is one global instance of the module |
460 | |
461 | static struct hw_module_methods_t gralloc_module_methods = |
462 | { |
463 | open: gralloc_device_open |
464 | }; |
465 | |
466 | private_module_t::private_module_t() |
467 | { |
468 | #define INIT_ZERO(obj) (memset(&(obj),0,sizeof((obj)))) |
469 | |
470 | base.common.tag = HARDWARE_MODULE_TAG; |
471 | base.common.version_major = 1; |
472 | base.common.version_minor = 0; |
473 | base.common.id = GRALLOC_HARDWARE_MODULE_ID; |
474 | base.common.name = "Graphics Memory Allocator Module"; |
475 | base.common.author = "ARM Ltd."; |
476 | base.common.methods = &gralloc_module_methods; |
477 | base.common.dso = NULL; |
478 | INIT_ZERO(base.common.reserved); |
479 | |
480 | base.registerBuffer = gralloc_register_buffer; |
481 | base.unregisterBuffer = gralloc_unregister_buffer; |
482 | base.lock = gralloc_lock; |
483 | base.lock_ycbcr = gralloc_lock_ycbcr; |
484 | base.unlock = gralloc_unlock; |
485 | base.perform = NULL; |
486 | INIT_ZERO(base.reserved_proc); |
487 | |
488 | INIT_ZERO(fb_primary); |
489 | INIT_ZERO(fb_external); |
490 | |
491 | pthread_mutex_init(&(lock), NULL); |
492 | swapInterval = 1; |
493 | |
494 | initialize_blk_conf(); |
495 | |
496 | #undef INIT_ZERO |
497 | }; |
498 | |
499 | /* |
500 | * HAL_MODULE_INFO_SYM will be initialized using the default constructor |
501 | * implemented above |
502 | */ |
503 | struct private_module_t HAL_MODULE_INFO_SYM; |
504 | |
505 |