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;
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 default:
269 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
270 hnd->format);
271 err = -EINVAL;
272 }
273 }
274 return err;
275 }
276
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)277 int gralloc_unlock(gralloc_module_t const* module,
278 buffer_handle_t handle)
279 {
280 if (private_handle_t::validate(handle) < 0)
281 return -EINVAL;
282 int err = 0;
283 private_handle_t* hnd = (private_handle_t*)handle;
284 IMemAlloc* memalloc = getAllocator(hnd->flags);
285
286 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
287 err = memalloc->clean_buffer((void*)hnd->base,
288 hnd->size, hnd->offset, hnd->fd,
289 CACHE_CLEAN_AND_INVALIDATE);
290 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
291 } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
292 hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
293 } else {
294 //Probably a round about way to do this, but this avoids adding new
295 //flags
296 err = memalloc->clean_buffer((void*)hnd->base,
297 hnd->size, hnd->offset, hnd->fd,
298 CACHE_INVALIDATE);
299 }
300
301 return err;
302 }
303
304 /*****************************************************************************/
305
gralloc_perform(struct gralloc_module_t const * module,int operation,...)306 int gralloc_perform(struct gralloc_module_t const* module,
307 int operation, ... )
308 {
309 int res = -EINVAL;
310 va_list args;
311 va_start(args, operation);
312 switch (operation) {
313 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
314 {
315 int fd = va_arg(args, int);
316 size_t size = va_arg(args, size_t);
317 size_t offset = va_arg(args, size_t);
318 void* base = va_arg(args, void*);
319 int width = va_arg(args, int);
320 int height = va_arg(args, int);
321 int format = va_arg(args, int);
322
323 native_handle_t** handle = va_arg(args, native_handle_t**);
324 int memoryFlags = va_arg(args, int);
325 private_handle_t* hnd = (private_handle_t*)native_handle_create(
326 private_handle_t::sNumFds, private_handle_t::sNumInts);
327 hnd->magic = private_handle_t::sMagic;
328 hnd->fd = fd;
329 hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
330 hnd->size = size;
331 hnd->offset = offset;
332 hnd->base = intptr_t(base) + offset;
333 hnd->gpuaddr = 0;
334 hnd->width = width;
335 hnd->height = height;
336 hnd->format = format;
337 *handle = (native_handle_t *)hnd;
338 res = 0;
339 break;
340
341 }
342 #ifdef QCOM_BSP
343 case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY:
344 {
345 int width = va_arg(args, int);
346 int height = va_arg(args, int);
347 int format = va_arg(args, int);
348 private_handle_t* hnd = va_arg(args, private_handle_t*);
349 if (private_handle_t::validate(hnd)) {
350 return res;
351 }
352 hnd->width = width;
353 hnd->height = height;
354 hnd->format = format;
355 res = 0;
356 }
357 break;
358 #endif
359 case GRALLOC_MODULE_PERFORM_GET_STRIDE:
360 {
361 int width = va_arg(args, int);
362 int format = va_arg(args, int);
363 int *stride = va_arg(args, int *);
364 *stride = AdrenoMemInfo::getInstance().getStride(width, format);
365 res = 0;
366 } break;
367 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
368 {
369 private_handle_t* hnd = va_arg(args, private_handle_t*);
370 int *stride = va_arg(args, int *);
371 if (private_handle_t::validate(hnd)) {
372 return res;
373 }
374 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
375 if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
376 *stride = metadata->bufferDim.sliceWidth;
377 } else {
378 *stride = hnd->width;
379 }
380 res = 0;
381 } break;
382 default:
383 break;
384 }
385 va_end(args);
386 return res;
387 }
388