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 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
218 //Invalidate if reading in software. No need to do this for the
219 //metadata buffer as it is only read/written in software.
220 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
221 err = memalloc->clean_buffer((void*)hnd->base,
222 hnd->size, hnd->offset, hnd->fd,
223 CACHE_INVALIDATE);
224 if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
225 // Mark the buffer to be flushed after cpu read/write
226 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
227 }
228 }
229 } else {
230 hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
231 }
232 return err;
233 }
234
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)235 int gralloc_lock(gralloc_module_t const* module,
236 buffer_handle_t handle, int usage,
237 int l, int t, int w, int h,
238 void** vaddr)
239 {
240 private_handle_t* hnd = (private_handle_t*)handle;
241 int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
242 if(!err)
243 *vaddr = (void*)hnd->base;
244 return err;
245 }
246
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)247 int gralloc_lock_ycbcr(gralloc_module_t const* module,
248 buffer_handle_t handle, int usage,
249 int l, int t, int w, int h,
250 struct android_ycbcr *ycbcr)
251 {
252 private_handle_t* hnd = (private_handle_t*)handle;
253 int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
254 int ystride, cstride;
255
256 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
257 if(!err) {
258 //hnd->format holds our implementation defined format
259 switch (hnd->format) {
260 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
261 ystride = ALIGN(hnd->width, 16);
262 ycbcr->y = (void*)hnd->base;
263 ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
264 ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
265 ycbcr->ystride = ystride;
266 ycbcr->cstride = ystride;
267 ycbcr->chroma_step = 2;
268 break;
269 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
270 ystride = cstride = hnd->width;
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 = cstride;
276 ycbcr->chroma_step = 2;
277 break;
278 default:
279 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
280 hnd->format);
281 err = -EINVAL;
282 }
283 }
284 return err;
285 }
286
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)287 int gralloc_unlock(gralloc_module_t const* module,
288 buffer_handle_t handle)
289 {
290 if (private_handle_t::validate(handle) < 0)
291 return -EINVAL;
292 int err = 0;
293 private_handle_t* hnd = (private_handle_t*)handle;
294
295 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
296 IMemAlloc* memalloc = getAllocator(hnd->flags);
297 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
298 err = memalloc->clean_buffer((void*)hnd->base,
299 hnd->size, hnd->offset, hnd->fd,
300 CACHE_CLEAN_AND_INVALIDATE);
301 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
302 } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
303 hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
304 } else {
305 //Probably a round about way to do this, but this avoids adding new
306 //flags
307 err = memalloc->clean_buffer((void*)hnd->base,
308 hnd->size, hnd->offset, hnd->fd,
309 CACHE_INVALIDATE);
310 }
311 }
312
313 return err;
314 }
315
316 /*****************************************************************************/
317
gralloc_perform(struct gralloc_module_t const * module,int operation,...)318 int gralloc_perform(struct gralloc_module_t const* module,
319 int operation, ... )
320 {
321 int res = -EINVAL;
322 va_list args;
323 va_start(args, operation);
324 switch (operation) {
325 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
326 {
327 int fd = va_arg(args, int);
328 size_t size = va_arg(args, size_t);
329 size_t offset = va_arg(args, size_t);
330 void* base = va_arg(args, void*);
331 int width = va_arg(args, int);
332 int height = va_arg(args, int);
333 int format = va_arg(args, int);
334
335 native_handle_t** handle = va_arg(args, native_handle_t**);
336 int memoryFlags = va_arg(args, int);
337 private_handle_t* hnd = (private_handle_t*)native_handle_create(
338 private_handle_t::sNumFds, private_handle_t::sNumInts);
339 hnd->magic = private_handle_t::sMagic;
340 hnd->fd = fd;
341 hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
342 hnd->size = size;
343 hnd->offset = offset;
344 hnd->base = intptr_t(base) + offset;
345 hnd->gpuaddr = 0;
346 hnd->width = width;
347 hnd->height = height;
348 hnd->format = format;
349 *handle = (native_handle_t *)hnd;
350 res = 0;
351 break;
352
353 }
354 #ifdef QCOM_BSP
355 case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY:
356 {
357 int width = va_arg(args, int);
358 int height = va_arg(args, int);
359 int format = va_arg(args, int);
360 private_handle_t* hnd = va_arg(args, private_handle_t*);
361 if (private_handle_t::validate(hnd)) {
362 return res;
363 }
364 hnd->width = width;
365 hnd->height = height;
366 hnd->format = format;
367 res = 0;
368 }
369 break;
370 #endif
371 case GRALLOC_MODULE_PERFORM_GET_STRIDE:
372 {
373 int width = va_arg(args, int);
374 int format = va_arg(args, int);
375 int *stride = va_arg(args, int *);
376 *stride = AdrenoMemInfo::getInstance().getStride(width, format);
377 res = 0;
378 } break;
379 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
380 {
381 private_handle_t* hnd = va_arg(args, private_handle_t*);
382 int *stride = va_arg(args, int *);
383 if (private_handle_t::validate(hnd)) {
384 return res;
385 }
386 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
387 if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
388 *stride = metadata->bufferDim.sliceWidth;
389 } else {
390 *stride = hnd->width;
391 }
392 res = 0;
393 } break;
394 default:
395 break;
396 }
397 va_end(args);
398 return res;
399 }
400