mapper.cpp revision 54df445a5148c4c03c5079ab97f29a31a1185f2d
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * Copyright (c) 2011-2014, 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 30#include <cutils/log.h> 31#include <cutils/atomic.h> 32 33#include <hardware/hardware.h> 34#include <hardware/gralloc.h> 35 36#include "gralloc_priv.h" 37#include "gr.h" 38#include "alloc_controller.h" 39#include "memalloc.h" 40#include <qdMetaData.h> 41 42using namespace gralloc; 43/*****************************************************************************/ 44 45// Return the type of allocator - 46// these are used for mapping/unmapping 47static IMemAlloc* getAllocator(int flags) 48{ 49 IMemAlloc* memalloc; 50 IAllocController* alloc_ctrl = IAllocController::getInstance(); 51 memalloc = alloc_ctrl->getAllocator(flags); 52 return memalloc; 53} 54 55static int gralloc_map(gralloc_module_t const* module, 56 buffer_handle_t handle, 57 void** vaddr) 58{ 59 private_handle_t* hnd = (private_handle_t*)handle; 60 void *mappedAddress; 61 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) && 62 !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) { 63 size_t size = hnd->size; 64 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 65 int err = memalloc->map_buffer(&mappedAddress, size, 66 hnd->offset, hnd->fd); 67 if(err || mappedAddress == MAP_FAILED) { 68 ALOGE("Could not mmap handle %p, fd=%d (%s)", 69 handle, hnd->fd, strerror(errno)); 70 hnd->base = 0; 71 return -errno; 72 } 73 74 hnd->base = intptr_t(mappedAddress) + hnd->offset; 75 //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", 76 // hnd->fd, hnd->offset, hnd->size, mappedAddress); 77 mappedAddress = MAP_FAILED; 78 size = ROUND_UP_PAGESIZE(sizeof(MetaData_t)); 79 err = memalloc->map_buffer(&mappedAddress, size, 80 hnd->offset_metadata, hnd->fd_metadata); 81 if(err || mappedAddress == MAP_FAILED) { 82 ALOGE("Could not mmap handle %p, fd=%d (%s)", 83 handle, hnd->fd_metadata, strerror(errno)); 84 hnd->base_metadata = 0; 85 return -errno; 86 } 87 hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata; 88 } 89 *vaddr = (void*)hnd->base; 90 return 0; 91} 92 93static int gralloc_unmap(gralloc_module_t const* module, 94 buffer_handle_t handle) 95{ 96 private_handle_t* hnd = (private_handle_t*)handle; 97 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 98 int err = -EINVAL; 99 void* base = (void*)hnd->base; 100 size_t size = hnd->size; 101 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 102 if(memalloc != NULL) { 103 err = memalloc->unmap_buffer(base, size, hnd->offset); 104 if (err) { 105 ALOGE("Could not unmap memory at address %p", base); 106 } 107 base = (void*)hnd->base_metadata; 108 size = ROUND_UP_PAGESIZE(sizeof(MetaData_t)); 109 err = memalloc->unmap_buffer(base, size, hnd->offset_metadata); 110 if (err) { 111 ALOGE("Could not unmap memory at address %p", base); 112 } 113 } 114 } 115 /* need to initialize the pointer to NULL otherwise unmapping for that 116 * buffer happens twice which leads to crash */ 117 hnd->base = 0; 118 hnd->base_metadata = 0; 119 return 0; 120} 121 122/*****************************************************************************/ 123 124static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; 125 126/*****************************************************************************/ 127 128int gralloc_register_buffer(gralloc_module_t const* module, 129 buffer_handle_t handle) 130{ 131 if (private_handle_t::validate(handle) < 0) 132 return -EINVAL; 133 134 // In this implementation, we don't need to do anything here 135 136 /* NOTE: we need to initialize the buffer as not mapped/not locked 137 * because it shouldn't when this function is called the first time 138 * in a new process. Ideally these flags shouldn't be part of the 139 * handle, but instead maintained in the kernel or at least 140 * out-of-line 141 */ 142 143 private_handle_t* hnd = (private_handle_t*)handle; 144 hnd->base = 0; 145 hnd->base_metadata = 0; 146 void *vaddr; 147 int err = gralloc_map(module, handle, &vaddr); 148 if (err) { 149 ALOGE("%s: gralloc_map failed", __FUNCTION__); 150 return err; 151 } 152 153 return 0; 154} 155 156int gralloc_unregister_buffer(gralloc_module_t const* module, 157 buffer_handle_t handle) 158{ 159 if (private_handle_t::validate(handle) < 0) 160 return -EINVAL; 161 162 /* 163 * If the buffer has been mapped during a lock operation, it's time 164 * to un-map it. It's an error to be here with a locked buffer. 165 * NOTE: the framebuffer is handled differently and is never unmapped. 166 */ 167 168 private_handle_t* hnd = (private_handle_t*)handle; 169 170 if (hnd->base != 0) { 171 gralloc_unmap(module, handle); 172 } 173 hnd->base = 0; 174 hnd->base_metadata = 0; 175 return 0; 176} 177 178int terminateBuffer(gralloc_module_t const* module, 179 private_handle_t* hnd) 180{ 181 /* 182 * If the buffer has been mapped during a lock operation, it's time 183 * to un-map it. It's an error to be here with a locked buffer. 184 */ 185 186 if (hnd->base != 0) { 187 // this buffer was mapped, unmap it now 188 if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM | 189 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP | 190 private_handle_t::PRIV_FLAGS_USES_ASHMEM | 191 private_handle_t::PRIV_FLAGS_USES_ION)) { 192 gralloc_unmap(module, hnd); 193 } else { 194 ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", 195 hnd->flags); 196 gralloc_unmap(module, hnd); 197 } 198 } 199 200 return 0; 201} 202 203int gralloc_lock(gralloc_module_t const* module, 204 buffer_handle_t handle, int usage, 205 int l, int t, int w, int h, 206 void** vaddr) 207{ 208 if (private_handle_t::validate(handle) < 0) 209 return -EINVAL; 210 211 int err = 0; 212 private_handle_t* hnd = (private_handle_t*)handle; 213 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { 214 if (hnd->base == 0) { 215 // we need to map for real 216 pthread_mutex_t* const lock = &sMapLock; 217 pthread_mutex_lock(lock); 218 err = gralloc_map(module, handle, vaddr); 219 pthread_mutex_unlock(lock); 220 } 221 *vaddr = (void*)hnd->base; 222 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { 223 //Invalidate if reading in software. No need to do this for the 224 //metadata buffer as it is only read/written in software. 225 IMemAlloc* memalloc = getAllocator(hnd->flags) ; 226 err = memalloc->clean_buffer((void*)hnd->base, 227 hnd->size, hnd->offset, hnd->fd, 228 CACHE_INVALIDATE); 229 if (usage & GRALLOC_USAGE_SW_WRITE_MASK) { 230 // Mark the buffer to be flushed after cpu read/write 231 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; 232 } 233 } 234 } else { 235 hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH; 236 } 237 return err; 238} 239 240int gralloc_unlock(gralloc_module_t const* module, 241 buffer_handle_t handle) 242{ 243 if (private_handle_t::validate(handle) < 0) 244 return -EINVAL; 245 int err = 0; 246 private_handle_t* hnd = (private_handle_t*)handle; 247 248 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) { 249 IMemAlloc* memalloc = getAllocator(hnd->flags); 250 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { 251 err = memalloc->clean_buffer((void*)hnd->base, 252 hnd->size, hnd->offset, hnd->fd, 253 CACHE_CLEAN_AND_INVALIDATE); 254 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; 255 } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) { 256 hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH; 257 } else { 258 //Probably a round about way to do this, but this avoids adding new 259 //flags 260 err = memalloc->clean_buffer((void*)hnd->base, 261 hnd->size, hnd->offset, hnd->fd, 262 CACHE_INVALIDATE); 263 } 264 } 265 266 return err; 267} 268 269/*****************************************************************************/ 270 271int gralloc_perform(struct gralloc_module_t const* module, 272 int operation, ... ) 273{ 274 int res = -EINVAL; 275 va_list args; 276 va_start(args, operation); 277 switch (operation) { 278 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: 279 { 280 int fd = va_arg(args, int); 281 size_t size = va_arg(args, size_t); 282 size_t offset = va_arg(args, size_t); 283 void* base = va_arg(args, void*); 284 int width = va_arg(args, int); 285 int height = va_arg(args, int); 286 int format = va_arg(args, int); 287 288 native_handle_t** handle = va_arg(args, native_handle_t**); 289 int memoryFlags = va_arg(args, int); 290 private_handle_t* hnd = (private_handle_t*)native_handle_create( 291 private_handle_t::sNumFds, private_handle_t::sNumInts); 292 hnd->magic = private_handle_t::sMagic; 293 hnd->fd = fd; 294 hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; 295 hnd->size = size; 296 hnd->offset = offset; 297 hnd->base = intptr_t(base) + offset; 298 hnd->gpuaddr = 0; 299 hnd->width = width; 300 hnd->height = height; 301 hnd->format = format; 302 *handle = (native_handle_t *)hnd; 303 res = 0; 304 break; 305 306 } 307#ifdef QCOM_BSP 308 case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY: 309 { 310 int width = va_arg(args, int); 311 int height = va_arg(args, int); 312 int format = va_arg(args, int); 313 private_handle_t* hnd = va_arg(args, private_handle_t*); 314 if (private_handle_t::validate(hnd)) { 315 return res; 316 } 317 hnd->width = width; 318 hnd->height = height; 319 hnd->format = format; 320 res = 0; 321 } 322 break; 323#endif 324 case GRALLOC_MODULE_PERFORM_GET_STRIDE: 325 { 326 int width = va_arg(args, int); 327 int format = va_arg(args, int); 328 int *stride = va_arg(args, int *); 329 int alignedw = 0, alignedh = 0; 330 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, 331 0, format, false, alignedw, alignedh); 332 *stride = alignedw; 333 res = 0; 334 } break; 335 336 case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE: 337 { 338 private_handle_t* hnd = va_arg(args, private_handle_t*); 339 int *stride = va_arg(args, int *); 340 if (private_handle_t::validate(hnd)) { 341 return res; 342 } 343 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 344 if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) { 345 *stride = metadata->bufferDim.sliceWidth; 346 } else { 347 *stride = hnd->width; 348 } 349 res = 0; 350 } break; 351 352 case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES: 353 { 354 int width = va_arg(args, int); 355 int height = va_arg(args, int); 356 int format = va_arg(args, int); 357 int usage = va_arg(args, int); 358 int *alignedWidth = va_arg(args, int *); 359 int *alignedHeight = va_arg(args, int *); 360 int *tileEnabled = va_arg(args,int *); 361 *tileEnabled = isMacroTileEnabled(format, usage); 362 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, 363 height, format, *tileEnabled, *alignedWidth, 364 *alignedHeight); 365 res = 0; 366 } break; 367 368 case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: 369 { 370 private_handle_t* hnd = va_arg(args, private_handle_t*); 371 int *color_space = va_arg(args, int *); 372 if (private_handle_t::validate(hnd)) { 373 return res; 374 } 375 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; 376 if(metadata && metadata->operation & UPDATE_COLOR_SPACE) { 377 *color_space = metadata->colorSpace; 378 res = 0; 379 } 380 } break; 381 default: 382 break; 383 } 384 va_end(args); 385 return res; 386} 387