1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <limits.h>
19 #include <errno.h>
20 #include <pthread.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdarg.h>
24
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/ioctl.h>
29 #include <linux/ashmem.h>
30
31 #include <cutils/log.h>
32 #include <cutils/atomic.h>
33 #include <cutils/ashmem.h>
34
35 #include <hardware/hardware.h>
36 #include <hardware/gralloc.h>
37
38 #include "gralloc_priv.h"
39 #include "gr.h"
40 #include "alloc_controller.h"
41 #include "memalloc.h"
42 #include <qdMetaData.h>
43
44 using namespace gralloc;
45 /*****************************************************************************/
46
47 // Return the type of allocator -
48 // these are used for mapping/unmapping
getAllocator(int flags)49 static IMemAlloc* getAllocator(int flags)
50 {
51 IMemAlloc* memalloc;
52 IAllocController* alloc_ctrl = IAllocController::getInstance();
53 memalloc = alloc_ctrl->getAllocator(flags);
54 return memalloc;
55 }
56
gralloc_map(gralloc_module_t const * module,buffer_handle_t handle)57 static int gralloc_map(gralloc_module_t const* module,
58 buffer_handle_t handle)
59 {
60 private_handle_t* hnd = (private_handle_t*)handle;
61 void *mappedAddress;
62 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
63 !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
64 size_t size = hnd->size;
65 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
66 int err = memalloc->map_buffer(&mappedAddress, size,
67 hnd->offset, hnd->fd);
68 if(err || mappedAddress == MAP_FAILED) {
69 ALOGE("Could not mmap handle %p, fd=%d (%s)",
70 handle, hnd->fd, strerror(errno));
71 hnd->base = 0;
72 return -errno;
73 }
74
75 hnd->base = intptr_t(mappedAddress) + hnd->offset;
76 mappedAddress = MAP_FAILED;
77 size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
78 err = memalloc->map_buffer(&mappedAddress, size,
79 hnd->offset_metadata, hnd->fd_metadata);
80 if(err || mappedAddress == MAP_FAILED) {
81 ALOGE("Could not mmap handle %p, fd=%d (%s)",
82 handle, hnd->fd_metadata, strerror(errno));
83 hnd->base_metadata = 0;
84 return -errno;
85 }
86 hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
87 }
88 return 0;
89 }
90
gralloc_unmap(gralloc_module_t const * module,buffer_handle_t handle)91 static int gralloc_unmap(gralloc_module_t const* module,
92 buffer_handle_t handle)
93 {
94 private_handle_t* hnd = (private_handle_t*)handle;
95 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
96 int err = -EINVAL;
97 void* base = (void*)hnd->base;
98 size_t size = hnd->size;
99 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
100 if(memalloc != NULL) {
101 err = memalloc->unmap_buffer(base, size, hnd->offset);
102 if (err) {
103 ALOGE("Could not unmap memory at address %p", base);
104 }
105 base = (void*)hnd->base_metadata;
106 size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
107 err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
108 if (err) {
109 ALOGE("Could not unmap memory at address %p", base);
110 }
111 }
112 }
113 /* need to initialize the pointer to NULL otherwise unmapping for that
114 * buffer happens twice which leads to crash */
115 hnd->base = 0;
116 hnd->base_metadata = 0;
117 return 0;
118 }
119
120 /*****************************************************************************/
121
122 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
123
124 /*****************************************************************************/
125
gralloc_register_buffer(gralloc_module_t const * module,buffer_handle_t handle)126 int gralloc_register_buffer(gralloc_module_t const* module,
127 buffer_handle_t handle)
128 {
129 if (private_handle_t::validate(handle) < 0)
130 return -EINVAL;
131
132 // In this implementation, we don't need to do anything here
133
134 /* NOTE: we need to initialize the buffer as not mapped/not locked
135 * because it shouldn't when this function is called the first time
136 * in a new process. Ideally these flags shouldn't be part of the
137 * handle, but instead maintained in the kernel or at least
138 * out-of-line
139 */
140
141 private_handle_t* hnd = (private_handle_t*)handle;
142 hnd->base = 0;
143 hnd->base_metadata = 0;
144 int err = gralloc_map(module, handle);
145 if (err) {
146 ALOGE("%s: gralloc_map failed", __FUNCTION__);
147 return err;
148 }
149
150 return 0;
151 }
152
gralloc_unregister_buffer(gralloc_module_t const * module,buffer_handle_t handle)153 int gralloc_unregister_buffer(gralloc_module_t const* module,
154 buffer_handle_t handle)
155 {
156 if (private_handle_t::validate(handle) < 0)
157 return -EINVAL;
158
159 /*
160 * If the buffer has been mapped during a lock operation, it's time
161 * to un-map it. It's an error to be here with a locked buffer.
162 * NOTE: the framebuffer is handled differently and is never unmapped.
163 */
164
165 private_handle_t* hnd = (private_handle_t*)handle;
166
167 if (hnd->base != 0) {
168 gralloc_unmap(module, handle);
169 }
170 hnd->base = 0;
171 hnd->base_metadata = 0;
172 return 0;
173 }
174
terminateBuffer(gralloc_module_t const * module,private_handle_t * hnd)175 int terminateBuffer(gralloc_module_t const* module,
176 private_handle_t* hnd)
177 {
178 /*
179 * If the buffer has been mapped during a lock operation, it's time
180 * to un-map it. It's an error to be here with a locked buffer.
181 */
182
183 if (hnd->base != 0) {
184 // this buffer was mapped, unmap it now
185 if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
186 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
187 private_handle_t::PRIV_FLAGS_USES_ASHMEM |
188 private_handle_t::PRIV_FLAGS_USES_ION)) {
189 gralloc_unmap(module, hnd);
190 } else {
191 ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
192 hnd->flags);
193 gralloc_unmap(module, hnd);
194 }
195 }
196
197 return 0;
198 }
199
gralloc_map_and_invalidate(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h)200 static int gralloc_map_and_invalidate (gralloc_module_t const* module,
201 buffer_handle_t handle, int usage,
202 int l, int t, int w, int h)
203 {
204 if (private_handle_t::validate(handle) < 0)
205 return -EINVAL;
206
207 int err = 0;
208 private_handle_t* hnd = (private_handle_t*)handle;
209 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
210 if (hnd->base == 0) {
211 // we need to map for real
212 pthread_mutex_t* const lock = &sMapLock;
213 pthread_mutex_lock(lock);
214 err = gralloc_map(module, handle);
215 pthread_mutex_unlock(lock);
216 }
217 //Invalidate if reading in software. No need to do this for the metadata
218 //buffer as it is only read/written in software.
219 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
220 err = memalloc->clean_buffer((void*)hnd->base,
221 hnd->size, hnd->offset, hnd->fd,
222 CACHE_INVALIDATE);
223 if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
224 !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
225 // Mark the buffer to be flushed after cpu read/write
226 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
227 }
228 } else {
229 hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
230 }
231 return err;
232 }
233
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)234 int gralloc_lock(gralloc_module_t const* module,
235 buffer_handle_t handle, int usage,
236 int l, int t, int w, int h,
237 void** vaddr)
238 {
239 private_handle_t* hnd = (private_handle_t*)handle;
240 int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
241 if(!err)
242 *vaddr = (void*)hnd->base;
243 return err;
244 }
245
gralloc_lock_ycbcr(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,struct android_ycbcr * ycbcr)246 int gralloc_lock_ycbcr(gralloc_module_t const* module,
247 buffer_handle_t handle, int usage,
248 int l, int t, int w, int h,
249 struct android_ycbcr *ycbcr)
250 {
251 private_handle_t* hnd = (private_handle_t*)handle;
252 int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
253 int ystride, cstride;
254 if(!err) {
255 //hnd->format holds our implementation defined format
256 //HAL_PIXEL_FORMAT_YCrCb_420_SP is the only one set right now.
257 switch (hnd->format) {
258 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
259 ystride = ALIGN(hnd->width, 16);
260 ycbcr->y = (void*)hnd->base;
261 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
262 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
263 ycbcr->ystride = ystride;
264 ycbcr->cstride = ystride;
265 ycbcr->chroma_step = 2;
266 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
267 break;
268 // YCbCr_420_SP
269 case HAL_PIXEL_FORMAT_NV12:
270 ystride = ALIGN(hnd->width, 16);
271 ycbcr->y = (void*)hnd->base;
272 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
273 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
274 ycbcr->ystride = ystride;
275 ycbcr->cstride = ystride;
276 ycbcr->chroma_step = 2;
277 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
278 break;
279 // YCrCb_420_P
280 case HAL_PIXEL_FORMAT_YV12:
281 ystride = ALIGN(hnd->width, 16);
282 cstride = ALIGN(ystride / 2, 16);
283 ycbcr->y = (void*)hnd->base;
284 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
285 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height
286 + cstride * hnd->height / 2);
287 ycbcr->ystride = ystride;
288 ycbcr->cstride = cstride;
289 ycbcr->chroma_step = 1;
290 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
291 break;
292 default:
293 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
294 hnd->format);
295 err = -EINVAL;
296 }
297 }
298 return err;
299 }
300
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)301 int gralloc_unlock(gralloc_module_t const* module,
302 buffer_handle_t handle)
303 {
304 if (private_handle_t::validate(handle) < 0)
305 return -EINVAL;
306 int err = 0;
307 private_handle_t* hnd = (private_handle_t*)handle;
308 IMemAlloc* memalloc = getAllocator(hnd->flags);
309
310 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
311 err = memalloc->clean_buffer((void*)hnd->base,
312 hnd->size, hnd->offset, hnd->fd,
313 CACHE_CLEAN_AND_INVALIDATE);
314 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
315 } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
316 hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
317 } else {
318 //Probably a round about way to do this, but this avoids adding new
319 //flags
320 err = memalloc->clean_buffer((void*)hnd->base,
321 hnd->size, hnd->offset, hnd->fd,
322 CACHE_INVALIDATE);
323 }
324
325 return err;
326 }
327
328 /*****************************************************************************/
329
gralloc_perform(struct gralloc_module_t const * module,int operation,...)330 int gralloc_perform(struct gralloc_module_t const* module,
331 int operation, ... )
332 {
333 int res = -EINVAL;
334 va_list args;
335 va_start(args, operation);
336 switch (operation) {
337 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
338 {
339 int fd = va_arg(args, int);
340 size_t size = va_arg(args, size_t);
341 size_t offset = va_arg(args, size_t);
342 void* base = va_arg(args, void*);
343 int width = va_arg(args, int);
344 int height = va_arg(args, int);
345 int format = va_arg(args, int);
346
347 native_handle_t** handle = va_arg(args, native_handle_t**);
348 int memoryFlags __attribute__((__unused__)) = va_arg(args, int);
349 private_handle_t* hnd = (private_handle_t*)native_handle_create(
350 private_handle_t::sNumFds, private_handle_t::sNumInts);
351 hnd->magic = private_handle_t::sMagic;
352 hnd->fd = fd;
353 hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
354 hnd->size = size;
355 hnd->offset = offset;
356 hnd->base = intptr_t(base) + offset;
357 hnd->gpuaddr = 0;
358 hnd->width = width;
359 hnd->height = height;
360 hnd->format = format;
361 *handle = (native_handle_t *)hnd;
362 res = 0;
363 break;
364
365 }
366 #ifdef QCOM_BSP
367 case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY:
368 {
369 int width = va_arg(args, int);
370 int height = va_arg(args, int);
371 int format = va_arg(args, int);
372 private_handle_t* hnd = va_arg(args, private_handle_t*);
373 if (private_handle_t::validate(hnd)) {
374 return res;
375 }
376 hnd->width = width;
377 hnd->height = height;
378 hnd->format = format;
379 res = 0;
380 }
381 break;
382 #endif
383 case GRALLOC_MODULE_PERFORM_GET_STRIDE:
384 {
385 int width = va_arg(args, int);
386 int format = va_arg(args, int);
387 int *stride = va_arg(args, int *);
388 *stride = AdrenoMemInfo::getInstance().getStride(width, format);
389 res = 0;
390 } break;
391 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
392 {
393 private_handle_t* hnd = va_arg(args, private_handle_t*);
394 int *stride = va_arg(args, int *);
395 if (private_handle_t::validate(hnd)) {
396 return res;
397 }
398 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
399 if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
400 *stride = metadata->bufferDim.sliceWidth;
401 } else {
402 *stride = hnd->width;
403 }
404 res = 0;
405 } break;
406 default:
407 break;
408 }
409 va_end(args);
410 return res;
411 }
412