1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define 18 # include <asm/page.h> 19 #else 20 # include <sys/user.h> 21 #endif 22 #include <limits.h> 23 #include <unistd.h> 24 #include <fcntl.h> 25 #include <errno.h> 26 #include <pthread.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include <sys/mman.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/ioctl.h> 34 35 #include <ion/ion.h> 36 #include <linux/ion.h> 37 #include <cutils/log.h> 38 #include <cutils/atomic.h> 39 40 #include <hardware/hardware.h> 41 #include <hardware/gralloc.h> 42 43 #include "gralloc_priv.h" 44 #include "exynos_format.h" 45 #include "gr.h" 46 47 #define ION_HEAP_EXYNOS_CONTIG_MASK (1 << 4) 48 #define ION_EXYNOS_FIMD_VIDEO_MASK (1 << 28) 49 #define ION_EXYNOS_MFC_OUTPUT_MASK (1 << 26) 50 #define ION_EXYNOS_MFC_INPUT_MASK (1 << 25) 51 #define ION_HEAP_SYSTEM_ID 0 52 #define ION_HEAP_EXYNOS_CONTIG_ID 4 53 #define ION_HEAP_CHUNK_ID 6 54 #define MB_1 (1024*1024) 55 56 57 /*****************************************************************************/ 58 59 struct gralloc_context_t { 60 alloc_device_t device; 61 /* our private data here */ 62 }; 63 64 static int gralloc_alloc_buffer(alloc_device_t* dev, 65 size_t size, int usage, buffer_handle_t* pHandle); 66 67 /*****************************************************************************/ 68 69 int fb_device_open(const hw_module_t* module, const char* name, 70 hw_device_t** device); 71 72 static int gralloc_device_open(const hw_module_t* module, const char* name, 73 hw_device_t** device); 74 75 extern int gralloc_lock(gralloc_module_t const* module, 76 buffer_handle_t handle, int usage, 77 int l, int t, int w, int h, 78 void** vaddr); 79 80 extern int gralloc_unlock(gralloc_module_t const* module, 81 buffer_handle_t handle); 82 83 extern int gralloc_register_buffer(gralloc_module_t const* module, 84 buffer_handle_t handle); 85 86 extern int gralloc_unregister_buffer(gralloc_module_t const* module, 87 buffer_handle_t handle); 88 89 /*****************************************************************************/ 90 91 static struct hw_module_methods_t gralloc_module_methods = { 92 open: gralloc_device_open 93 }; 94 95 struct private_module_t HAL_MODULE_INFO_SYM = { 96 base: { 97 common: { 98 tag: HARDWARE_MODULE_TAG, 99 version_major: 1, 100 version_minor: 0, 101 id: GRALLOC_HARDWARE_MODULE_ID, 102 name: "Graphics Memory Allocator Module", 103 author: "The Android Open Source Project", 104 methods: &gralloc_module_methods 105 }, 106 registerBuffer: gralloc_register_buffer, 107 unregisterBuffer: gralloc_unregister_buffer, 108 lock: gralloc_lock, 109 unlock: gralloc_unlock, 110 }, 111 framebuffer: 0, 112 flags: 0, 113 numBuffers: 0, 114 bufferMask: 0, 115 lock: PTHREAD_MUTEX_INITIALIZER, 116 currentBuffer: 0, 117 ionfd: -1, 118 }; 119 120 /*****************************************************************************/ 121 122 static unsigned int _select_heap(int usage) 123 { 124 unsigned int heap_mask; 125 126 if (usage & GRALLOC_USAGE_PROTECTED) 127 heap_mask = (1 << ION_HEAP_EXYNOS_CONTIG_ID); 128 else 129 heap_mask = (1 << ION_HEAP_SYSTEM_ID) | (1 << ION_HEAP_CHUNK_ID); 130 131 return heap_mask; 132 } 133 134 static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage, 135 unsigned int ion_flags, private_handle_t **hnd, int *stride) 136 { 137 size_t size, bpr, alignment = 0; 138 int bpp = 0, vstride, fd, err; 139 unsigned int heap_mask = _select_heap(usage); 140 141 if (format == HAL_PIXEL_FORMAT_RGBA_8888) { 142 bool sw_usage = !!(usage & (GRALLOC_USAGE_SW_READ_MASK | 143 GRALLOC_USAGE_SW_WRITE_MASK)); 144 145 if (usage & GRALLOC_USAGE_HW_FB) { 146 ALOGW_IF(sw_usage, 147 "framebuffer target should not have SW usage bits; ignoring"); 148 format = HAL_PIXEL_FORMAT_BGRA_8888; 149 } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { 150 if (sw_usage) 151 return -EINVAL; 152 format = HAL_PIXEL_FORMAT_BGRA_8888; 153 } 154 } 155 156 switch (format) { 157 case HAL_PIXEL_FORMAT_RGBA_8888: 158 case HAL_PIXEL_FORMAT_RGBX_8888: 159 case HAL_PIXEL_FORMAT_BGRA_8888: 160 bpp = 4; 161 break; 162 case HAL_PIXEL_FORMAT_RGB_888: 163 bpp = 3; 164 break; 165 case HAL_PIXEL_FORMAT_RGB_565: 166 case HAL_PIXEL_FORMAT_RAW_SENSOR: 167 bpp = 2; 168 break; 169 case HAL_PIXEL_FORMAT_BLOB: 170 *stride = w; 171 vstride = h; 172 size = w * h; 173 break; 174 default: 175 return -EINVAL; 176 } 177 178 if (format != HAL_PIXEL_FORMAT_BLOB) { 179 bpr = ALIGN(w*bpp, 64); 180 vstride = ALIGN(h, 16); 181 if (vstride < h + 2) 182 size = bpr * (h + 2); 183 else 184 size = bpr * vstride; 185 *stride = bpr / bpp; 186 size = ALIGN(size, PAGE_SIZE); 187 } 188 189 if (usage & GRALLOC_USAGE_PROTECTED) { 190 alignment = MB_1; 191 ion_flags |= ION_EXYNOS_FIMD_VIDEO_MASK; 192 } 193 194 err = ion_alloc_fd(ionfd, size, alignment, heap_mask, ion_flags, 195 &fd); 196 *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, 197 vstride); 198 199 return err; 200 } 201 202 static int gralloc_alloc_framework_yuv(int ionfd, int w, int h, int format, 203 int usage, unsigned int ion_flags, 204 private_handle_t **hnd, int *stride) 205 { 206 size_t size; 207 int err, fd; 208 unsigned int heap_mask = _select_heap(usage); 209 210 switch (format) { 211 case HAL_PIXEL_FORMAT_YV12: 212 *stride = ALIGN(w, 16); 213 size = (*stride * h) + (ALIGN(*stride / 2, 16) * h); 214 break; 215 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 216 *stride = w; 217 size = *stride * h * 3 / 2; 218 break; 219 default: 220 ALOGE("invalid yuv format %d\n", format); 221 return -EINVAL; 222 } 223 224 err = ion_alloc_fd(ionfd, size, 0, heap_mask, ion_flags, &fd); 225 if (err) 226 return err; 227 228 *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, h); 229 return err; 230 } 231 232 static int gralloc_alloc_yuv(int ionfd, int w, int h, int format, 233 int usage, unsigned int ion_flags, 234 private_handle_t **hnd, int *stride) 235 { 236 size_t luma_size, chroma_size; 237 int err, planes, fd, fd1, fd2 = 0; 238 size_t luma_vstride; 239 unsigned int heap_mask = _select_heap(usage); 240 241 *stride = ALIGN(w, 16); 242 243 if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { 244 ALOGV("HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED : usage(%x), flags(%x)\n", usage, ion_flags); 245 if ((usage & GRALLOC_USAGE_HW_CAMERA_ZSL) == GRALLOC_USAGE_HW_CAMERA_ZSL) { 246 format = HAL_PIXEL_FORMAT_YCbCr_422_I; // YUYV 247 } else if (usage & GRALLOC_USAGE_HW_TEXTURE) { 248 format = HAL_PIXEL_FORMAT_EXYNOS_YV12; 249 } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { 250 format = HAL_PIXEL_FORMAT_YCbCr_420_SP; // NV12M 251 } 252 } 253 switch (format) { 254 case HAL_PIXEL_FORMAT_EXYNOS_YV12: 255 { 256 *stride = ALIGN(w, 32); 257 luma_vstride = ALIGN(h, 16); 258 luma_size = luma_vstride * *stride; 259 chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16); 260 planes = 3; 261 break; 262 } 263 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP: 264 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 265 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: 266 { 267 size_t chroma_vstride = ALIGN(h / 2, 32); 268 luma_vstride = ALIGN(h, 32); 269 luma_size = luma_vstride * *stride; 270 chroma_size = chroma_vstride * *stride; 271 planes = 2; 272 break; 273 } 274 case HAL_PIXEL_FORMAT_YV12: 275 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 276 return gralloc_alloc_framework_yuv(ionfd, w, h, format, usage, 277 ion_flags, hnd, stride); 278 case HAL_PIXEL_FORMAT_YCbCr_422_I: 279 { 280 luma_vstride = h; 281 luma_size = luma_vstride * *stride * 2; 282 chroma_size = 0; 283 planes = 1; 284 break; 285 } 286 default: 287 ALOGE("invalid yuv format %d\n", format); 288 return -EINVAL; 289 } 290 291 if (usage & GRALLOC_USAGE_PROTECTED) 292 ion_flags |= ION_EXYNOS_MFC_OUTPUT_MASK; 293 294 err = ion_alloc_fd(ionfd, luma_size, 0, heap_mask, ion_flags, &fd); 295 if (err) 296 return err; 297 if (planes == 1) { 298 *hnd = new private_handle_t(fd, luma_size, usage, w, h, 299 format, *stride, luma_vstride); 300 } else { 301 err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd1); 302 if (err) 303 goto err1; 304 if (planes == 3) { 305 err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd2); 306 if (err) 307 goto err2; 308 309 *hnd = new private_handle_t(fd, fd1, fd2, luma_size, usage, w, h, 310 format, *stride, luma_vstride); 311 } else { 312 *hnd = new private_handle_t(fd, fd1, luma_size, usage, w, h, format, 313 *stride, luma_vstride); 314 } 315 } 316 // Set chroma & gamut fields 317 if (!err && *hnd) { 318 if (usage & GRALLOC_USAGE_PRIVATE_CHROMA) { 319 (*hnd)->chroma = HAL_PIXEL_CHROMA_BT601_8; 320 (*hnd)->gamut = HAL_PIXEL_GAMUT_NARROW_8; 321 } else { 322 (*hnd)->chroma = HAL_PIXEL_CHROMA_BT709_8; 323 (*hnd)->gamut = HAL_PIXEL_GAMUT_WIDE_8; 324 } 325 } 326 return err; 327 328 err2: 329 close(fd1); 330 err1: 331 close(fd); 332 return err; 333 } 334 335 static int gralloc_alloc(alloc_device_t* dev, 336 int w, int h, int format, int usage, 337 buffer_handle_t* pHandle, int* pStride) 338 { 339 int stride; 340 int err; 341 unsigned int ion_flags = 0; 342 private_handle_t *hnd = NULL; 343 344 if (!pHandle || !pStride) 345 return -EINVAL; 346 347 if( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) 348 ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; 349 350 private_module_t* m = reinterpret_cast<private_module_t*> 351 (dev->common.module); 352 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*> 353 (dev->common.module); 354 355 err = gralloc_alloc_rgb(m->ionfd, w, h, format, usage, ion_flags, &hnd, 356 &stride); 357 if (err) 358 err = gralloc_alloc_yuv(m->ionfd, w, h, format, usage, ion_flags, 359 &hnd, &stride); 360 if (err) 361 return err; 362 363 if (err != 0) 364 goto err; 365 366 *pHandle = hnd; 367 *pStride = stride; 368 return 0; 369 err: 370 if (!hnd) 371 return err; 372 close(hnd->fd); 373 if (hnd->fd1 >= 0) 374 close(hnd->fd1); 375 if (hnd->fd2 >= 0) 376 close(hnd->fd2); 377 return err; 378 } 379 380 static int gralloc_free(alloc_device_t* dev, 381 buffer_handle_t handle) 382 { 383 if (private_handle_t::validate(handle) < 0) 384 return -EINVAL; 385 386 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle); 387 gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( 388 dev->common.module); 389 if (hnd->base) 390 grallocUnmap(module, const_cast<private_handle_t*>(hnd)); 391 392 close(hnd->fd); 393 if (hnd->fd1 >= 0) 394 close(hnd->fd1); 395 if (hnd->fd2 >= 0) 396 close(hnd->fd2); 397 398 delete hnd; 399 return 0; 400 } 401 402 /*****************************************************************************/ 403 404 static int gralloc_close(struct hw_device_t *dev) 405 { 406 gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev); 407 if (ctx) { 408 /* TODO: keep a list of all buffer_handle_t created, and free them 409 * all here. 410 */ 411 free(ctx); 412 } 413 return 0; 414 } 415 416 int gralloc_device_open(const hw_module_t* module, const char* name, 417 hw_device_t** device) 418 { 419 int status = -EINVAL; 420 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { 421 gralloc_context_t *dev; 422 dev = (gralloc_context_t*)malloc(sizeof(*dev)); 423 424 /* initialize our state here */ 425 memset(dev, 0, sizeof(*dev)); 426 427 /* initialize the procs */ 428 dev->device.common.tag = HARDWARE_DEVICE_TAG; 429 dev->device.common.version = 0; 430 dev->device.common.module = const_cast<hw_module_t*>(module); 431 dev->device.common.close = gralloc_close; 432 433 dev->device.alloc = gralloc_alloc; 434 dev->device.free = gralloc_free; 435 436 private_module_t *p = reinterpret_cast<private_module_t*>(dev->device.common.module); 437 p->ionfd = ion_open(); 438 439 *device = &dev->device.common; 440 status = 0; 441 } else { 442 status = fb_device_open(module, name, device); 443 } 444 return status; 445 } 446