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