| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <limits.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <sys/mman.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <sys/ioctl.h> |
| |
| #include <hardware/exynos/ion.h> |
| #include <linux/ion.h> |
| #include <exynos_ion.h> |
| #include <log/log.h> |
| #include <cutils/atomic.h> |
| |
| #include <hardware/hardware.h> |
| #include <hardware/gralloc.h> |
| |
| #include "gralloc_priv.h" |
| #include "exynos_format.h" |
| #include "gr.h" |
| |
| #include "VendorVideoAPI.h" |
| #define PRIV_SIZE sizeof(ExynosVideoMeta) |
| |
| #define MSCL_EXT_SIZE 512 |
| #define MSCL_ALIGN 128 |
| |
| #if MALI_AFBC_GRALLOC == 1 /* It's for AFBC support on GPU DDK*/ |
| #include "format_chooser.h" |
| #define GRALLOC_ARM_INTFMT_EXTENSION_BIT_START 32 |
| /* This format will be use AFBC */ |
| #define GRALLOC_ARM_INTFMT_AFBC (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+0)) |
| |
| #define AFBC_PIXELS_PER_BLOCK 16 |
| #define AFBC_BODY_BUFFER_BYTE_ALIGNMENT 1024 |
| #define AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY 16 |
| #endif |
| |
| /*****************************************************************************/ |
| |
| struct gralloc_context_t { |
| alloc_device_t device; |
| /* our private data here */ |
| }; |
| |
| /*****************************************************************************/ |
| |
| int fb_device_open(const hw_module_t* module, const char* name, |
| hw_device_t** device); |
| |
| static int gralloc_device_open(const hw_module_t* module, const char* name, |
| hw_device_t** device); |
| |
| extern int gralloc_lock(gralloc_module_t const* module, |
| buffer_handle_t handle, int usage, |
| int l, int t, int w, int h, |
| void** vaddr); |
| |
| extern int gralloc_unlock(gralloc_module_t const* module, |
| buffer_handle_t handle); |
| |
| extern int gralloc_lock_ycbcr(gralloc_module_t const* module, |
| buffer_handle_t handle, int usage, |
| int l, int t, int w, int h, |
| android_ycbcr *ycbcr); |
| |
| extern int gralloc_register_buffer(gralloc_module_t const* module, |
| buffer_handle_t handle); |
| |
| extern int gralloc_unregister_buffer(gralloc_module_t const* module, |
| buffer_handle_t handle); |
| |
| /*****************************************************************************/ |
| |
| static struct hw_module_methods_t gralloc_module_methods = { |
| gralloc_device_open |
| }; |
| |
| /* version_major is for module_api_verison |
| * lock_ycbcr is for MODULE_API_VERSION_0_2 |
| */ |
| struct private_module_t HAL_MODULE_INFO_SYM = { |
| .base = { |
| .common = { |
| .tag = HARDWARE_MODULE_TAG, |
| .module_api_version = GRALLOC_MODULE_API_VERSION_0_2, |
| .hal_api_version = 0, |
| .id = GRALLOC_HARDWARE_MODULE_ID, |
| .name = "Graphics Memory Allocator Module", |
| .author = "The Android Open Source Project", |
| .methods = &gralloc_module_methods |
| }, |
| .registerBuffer = gralloc_register_buffer, |
| .unregisterBuffer = gralloc_unregister_buffer, |
| .lock = gralloc_lock, |
| .unlock = gralloc_unlock, |
| .perform = NULL, |
| .lock_ycbcr = gralloc_lock_ycbcr, |
| }, |
| .framebuffer = 0, |
| .flags = 0, |
| .numBuffers = 0, |
| .bufferMask = 0, |
| .lock = PTHREAD_MUTEX_INITIALIZER, |
| .currentBuffer = 0, |
| .ionfd = -1, |
| }; |
| |
| /*****************************************************************************/ |
| |
| static unsigned int _select_heap(int usage) |
| { |
| unsigned int heap_mask; |
| #ifdef USES_EXYNOS_COMMON_GRALLOC |
| if (usage & GRALLOC_USAGE_PROTECTED) { |
| if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE && !(usage & GRALLOC_USAGE_PHYSICALLY_LINEAR)) |
| heap_mask = ION_HEAP_SYSTEM_MASK; |
| else |
| heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK; |
| } else if (usage & GRALLOC_USAGE_CAMERA_RESERVED) { |
| heap_mask = EXYNOS_ION_HEAP_CAMERA; |
| } else if ((usage & GRALLOC_USAGE_PRIVATE_NONSECURE) && (usage & GRALLOC_USAGE_PHYSICALLY_LINEAR)) { |
| heap_mask = EXYNOS_ION_HEAP_CRYPTO_MASK; |
| } else if (usage & GRALLOC_USAGE_SECURE_CAMERA_RESERVED) { |
| heap_mask = EXYNOS_ION_HEAP_SECURE_CAMERA; |
| } else { |
| heap_mask = ION_HEAP_SYSTEM_MASK; |
| } |
| #else |
| if (usage & GRALLOC_USAGE_PROTECTED) |
| heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK; |
| else |
| heap_mask = ION_HEAP_SYSTEM_MASK; |
| #endif |
| |
| return heap_mask; |
| } |
| |
| /* |
| * Define GRALLOC_ARM_FORMAT_SELECTION_DISABLE to disable the format selection completely |
| */ |
| static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage, |
| unsigned int ion_flags, private_handle_t **hnd, int *stride) |
| { |
| size_t bpr = 0, ext_size=256, size = 0, size1 = 0; |
| int bpp = 0, vstride = 0; |
| int fd = -1, fd1 = -1; |
| |
| unsigned int heap_mask = _select_heap(usage); |
| int is_compressible = check_for_compression(w, h, format, usage); |
| |
| switch (format) { |
| case HAL_PIXEL_FORMAT_RGBA_FP16: |
| bpp = 8; |
| break; |
| case HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888: |
| case HAL_PIXEL_FORMAT_RGBA_8888: |
| case HAL_PIXEL_FORMAT_RGBX_8888: |
| case HAL_PIXEL_FORMAT_BGRA_8888: |
| case HAL_PIXEL_FORMAT_RGBA_1010102: |
| bpp = 4; |
| break; |
| case HAL_PIXEL_FORMAT_RGB_888: |
| bpp = 3; |
| break; |
| case HAL_PIXEL_FORMAT_RGB_565: |
| case HAL_PIXEL_FORMAT_RAW16: |
| case HAL_PIXEL_FORMAT_RAW_OPAQUE: |
| bpp = 2; |
| break; |
| case HAL_PIXEL_FORMAT_BLOB: |
| *stride = w; |
| vstride = h; |
| size = w * h; |
| break; |
| default: |
| return -EINVAL; |
| } |
| |
| if (format != HAL_PIXEL_FORMAT_BLOB) { |
| bpr = ALIGN(w, 16)* bpp; |
| vstride = ALIGN(h, 16); |
| |
| if (vstride < h + 2) |
| size = bpr * (h + 2); |
| else |
| size = bpr * vstride; |
| |
| *stride = bpr / bpp; |
| size = size + ext_size; |
| if (is_compressible) |
| { |
| /* if is_compressible = 1, width is alread 16 align so we can use width instead of w_aligned*/ |
| int h_aligned = ALIGN( h, AFBC_PIXELS_PER_BLOCK ); |
| int nblocks = *stride / AFBC_PIXELS_PER_BLOCK * h_aligned / AFBC_PIXELS_PER_BLOCK; |
| |
| size = *stride * h_aligned * bpp + |
| ALIGN( nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, AFBC_BODY_BUFFER_BYTE_ALIGNMENT ) + ext_size; |
| } |
| #ifdef GRALLOC_MSCL_ALIGN_RESTRICTION |
| if (w % MSCL_ALIGN) |
| size += MSCL_EXT_SIZE; |
| #endif |
| } |
| |
| if (usage & GRALLOC_USAGE_PROTECTED) { |
| if ((usage & GRALLOC_USAGE_PRIVATE_NONSECURE) && (usage & GRALLOC_USAGE_PHYSICALLY_LINEAR)) |
| ion_flags |= ION_EXYNOS_G2D_WFD_MASK; |
| else if (usage & GRALLOC_USAGE_VIDEO_EXT) |
| ion_flags |= (ION_EXYNOS_VIDEO_EXT_MASK | ION_FLAG_PROTECTED); |
| else if ((usage & GRALLOC_USAGE_HW_COMPOSER) && |
| !(usage & GRALLOC_USAGE_HW_TEXTURE) && !(usage & GRALLOC_USAGE_HW_RENDER)) { |
| // For DRM Playback |
| ion_flags |= (ION_EXYNOS_FIMD_VIDEO_MASK | ION_FLAG_PROTECTED); |
| } |
| else |
| ion_flags |= (ION_EXYNOS_MFC_OUTPUT_MASK | ION_FLAG_PROTECTED); |
| } else if ((usage & GRALLOC_USAGE_PRIVATE_NONSECURE) && (usage & GRALLOC_USAGE_PHYSICALLY_LINEAR)) { |
| ion_flags |= ION_FLAG_PROTECTED; |
| } |
| |
| fd = exynos_ion_alloc(ionfd, size, heap_mask, ion_flags); |
| if (fd < 0) |
| { |
| ALOGE("failed to get fd from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| return -EINVAL; |
| } |
| else |
| { |
| // Alloc for AFBC data |
| if (is_compressible) |
| { |
| size1 = AFBC_INFO_SIZE; |
| fd1 = exynos_ion_alloc(ionfd, size1, EXYNOS_ION_HEAP_SYSTEM_MASK, 0); |
| if (fd1 < 0) |
| { |
| ALOGE("failed to get fd1 from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| close(fd); |
| return -EINVAL; |
| } |
| } |
| } |
| |
| *hnd = new private_handle_t(fd, fd1, -1, size, size1, 0, |
| usage, w, h, format, format, format, *stride, |
| vstride, is_compressible); |
| |
| return 0; |
| } |
| |
| static int gralloc_alloc_framework_yuv(int ionfd, int w, int h, int format, int frameworkFormat, |
| int usage, unsigned int ion_flags, |
| private_handle_t **hnd, int *stride) |
| { |
| size_t size=0, ext_size=256; |
| int fd = -1; |
| unsigned int heap_mask = _select_heap(usage); |
| int is_compressible = 0; |
| |
| switch (format) { |
| case HAL_PIXEL_FORMAT_YV12: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P: |
| *stride = ALIGN(w, 16); |
| size = (*stride * h) + (ALIGN(*stride / 2, 16) * h) + ext_size; |
| break; |
| case HAL_PIXEL_FORMAT_YCrCb_420_SP: |
| *stride = w; |
| size = *stride * h * 3 / 2 + ext_size; |
| break; |
| case HAL_PIXEL_FORMAT_Y8: |
| *stride = ALIGN(w, 16); |
| size = *stride * h; |
| break; |
| case HAL_PIXEL_FORMAT_Y16: |
| *stride = ALIGN(w, 16); |
| size = (*stride * h) * 2; |
| break; |
| default: |
| ALOGE("invalid yuv format %d\n", format); |
| return -EINVAL; |
| } |
| |
| #ifdef GRALLOC_MSCL_ALIGN_RESTRICTION |
| if (w % MSCL_ALIGN) |
| size += MSCL_EXT_SIZE; |
| #endif |
| |
| if (frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) |
| *stride = 0; |
| |
| fd = exynos_ion_alloc(ionfd, size, heap_mask, ion_flags); |
| if (fd < 0) |
| { |
| ALOGE("failed to get fd from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| return -EINVAL; |
| } |
| |
| *hnd = new private_handle_t(fd, -1, -1, size, 0, 0, |
| usage, w, h, format, format, frameworkFormat, *stride, h, is_compressible); |
| return 0; |
| } |
| |
| static int gralloc_alloc_yuv(int ionfd, int w, int h, int format, |
| int usage, unsigned int ion_flags, |
| private_handle_t **hnd, int *stride) |
| { |
| size_t luma_size=0, chroma_size=0, ext_size=256; |
| int planes = 0, fd = -1, fd1 = -1, fd2 = -1; |
| size_t luma_vstride = 0; |
| unsigned int heap_mask = _select_heap(usage); |
| // Keep around original requested format for later validation |
| int frameworkFormat = format; |
| int is_compressible = 0; |
| uint64_t internal_format = 0; |
| int size = 0, size1 = 0, size2 = 0; |
| |
| *stride = ALIGN(w, 16); |
| luma_vstride = ALIGN(h, 16); |
| |
| if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { |
| ALOGV("HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED : usage(%x), flags(%x)\n", usage, ion_flags); |
| if ((usage & GRALLOC_USAGE_HW_CAMERA_ZSL) == GRALLOC_USAGE_HW_CAMERA_ZSL) { |
| format = HAL_PIXEL_FORMAT_YCbCr_422_I; // YUYV |
| } else if ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_COMPOSER)) { |
| if (usage & GRALLOC_USAGE_YUV_RANGE_FULL) |
| format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL; // NV21M Full |
| else |
| format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow |
| } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { |
| format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow |
| } else { |
| format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow |
| } |
| } |
| else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { |
| if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { |
| format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M; |
| } else { |
| // Flexible framework-accessible YUV format; map to NV21 for now |
| format = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
| } |
| } |
| |
| if (usage & GRALLOC_USAGE_PROTECTED) { |
| ion_flags |= ION_FLAG_PROTECTED; |
| if (usage & GRALLOC_USAGE_VIDEO_EXT) |
| ion_flags |= ION_EXYNOS_VIDEO_EXT_MASK; |
| else if ((usage & GRALLOC_USAGE_HW_COMPOSER) && |
| !(usage & GRALLOC_USAGE_HW_TEXTURE) && !(usage & GRALLOC_USAGE_HW_RENDER)) { |
| // For DRM Playback |
| ion_flags |= ION_EXYNOS_FIMD_VIDEO_MASK; |
| } |
| else |
| ion_flags |= ION_EXYNOS_MFC_OUTPUT_MASK; |
| } else if (usage & GRALLOC_USAGE_CAMERA_RESERVED) |
| ion_flags |= ION_EXYNOS_MFC_OUTPUT_MASK; |
| |
| // Sync iinternal_format with format |
| internal_format = format; |
| |
| switch (format) { |
| case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: |
| { |
| *stride = ALIGN(w, 32); |
| luma_size = luma_vstride * *stride + ext_size; |
| #ifdef EXYNOS_CHROMA_VSTRIDE_ALIGN |
| chroma_size = ALIGN(luma_vstride / 2, CHROMA_VALIGN) * ALIGN(*stride / 2, 16) + ext_size; |
| #else |
| chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16) + ext_size; |
| #endif |
| planes = 3; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: |
| { |
| size_t chroma_vstride = ALIGN(h / 2, 32); |
| luma_vstride = ALIGN(h, 32); |
| luma_size = luma_vstride * *stride + ext_size; |
| chroma_size = chroma_vstride * *stride + ext_size; |
| planes = 2; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_YV12: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P: |
| case HAL_PIXEL_FORMAT_YCrCb_420_SP: |
| case HAL_PIXEL_FORMAT_Y8: |
| case HAL_PIXEL_FORMAT_Y16: |
| return gralloc_alloc_framework_yuv(ionfd, w, h, format, frameworkFormat, usage, |
| ion_flags, hnd, stride); |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: |
| { |
| luma_size = *stride * luma_vstride+ext_size; |
| #ifdef EXYNOS_CHROMA_VSTRIDE_ALIGN |
| chroma_size = *stride * ALIGN(luma_vstride / 2, CHROMA_VALIGN)+ext_size; |
| #else |
| chroma_size = *stride * ALIGN(luma_vstride / 2, 8)+ext_size; |
| #endif |
| planes = 2; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: |
| { |
| luma_vstride = ALIGN(h, 32); |
| luma_size = *stride * luma_vstride+ext_size; |
| chroma_size = *stride * ALIGN(luma_vstride / 2, 8)+ext_size; |
| planes = 3; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_YCbCr_422_I: |
| { |
| luma_vstride = h; |
| luma_size = luma_vstride * *stride * 2+ext_size; |
| planes = 1; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN: |
| { |
| #ifdef EXYNOS_CHROMA_VSTRIDE_ALIGN |
| chroma_size = ALIGN((*stride * ALIGN(luma_vstride / 2, CHROMA_VALIGN)) + ext_size, 16); |
| #else |
| chroma_size = ALIGN((*stride * luma_vstride / 2) + ext_size, 16); |
| #endif |
| luma_size = (*stride * luma_vstride) + ext_size + chroma_size; |
| planes = 1; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B: |
| { |
| #ifdef GRALLOC_10B_ALIGN_RESTRICTION |
| luma_size = (*stride * luma_vstride + ext_size) + ((ALIGN(w / 4, 16) * luma_vstride) + ext_size); |
| chroma_size = (*stride * luma_vstride / 2 + ext_size) + ((ALIGN(w / 4, 16) * (luma_vstride / 2)) + ext_size); |
| #else |
| luma_size = (*stride * luma_vstride + ext_size) + ((ALIGN(w / 4, 16) * h) + ext_size); |
| chroma_size = (*stride * luma_vstride / 2 + ext_size) + ((ALIGN(w / 4, 16) * (h / 2)) + ext_size); |
| #endif |
| planes = 3; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B: |
| { |
| chroma_size = ALIGN((*stride * luma_vstride / 2) + ext_size, 16) + (ALIGN(w / 4, 16) * (luma_vstride / 2)) + 64; |
| luma_size = (*stride * luma_vstride) + ext_size + (ALIGN(w / 4, 16) * luma_vstride) + 64 + chroma_size; |
| planes = 1; |
| break; |
| } |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M: |
| { |
| chroma_size = ((*stride * 2) * luma_vstride / 2) + ext_size; |
| luma_size = ((*stride * 2) * luma_vstride) + ext_size; |
| planes = 3; |
| break; |
| } |
| default: |
| ALOGE("invalid yuv format %d\n", format); |
| return -EINVAL; |
| } |
| |
| #ifdef GRALLOC_MSCL_ALIGN_RESTRICTION |
| if (w % MSCL_ALIGN) { |
| luma_size += MSCL_EXT_SIZE; |
| chroma_size += MSCL_EXT_SIZE/2; |
| } |
| #endif |
| |
| size = luma_size; |
| fd = exynos_ion_alloc(ionfd, size, heap_mask, ion_flags); |
| if (fd < 0) { |
| ALOGE("failed to get fd from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| return -EINVAL; |
| } |
| |
| if (planes == 1) { |
| *hnd = new private_handle_t(fd, -1, -1, size, 0, 0, usage, w, h, |
| format, internal_format, frameworkFormat, *stride, luma_vstride, is_compressible); |
| } else { |
| size1 = chroma_size; |
| fd1 = exynos_ion_alloc(ionfd, size1, heap_mask, ion_flags); |
| if (fd1 < 0) |
| { |
| ALOGE("failed to get fd from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| close(fd); |
| return -EINVAL; |
| } |
| |
| if (planes == 3) { |
| if ((format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) || |
| (format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) { |
| size2 = PRIV_SIZE; |
| fd2 = exynos_ion_alloc(ionfd, size2, ION_HEAP_SYSTEM_MASK, 0); |
| } else { |
| size2 = chroma_size; |
| fd2 = exynos_ion_alloc(ionfd, size2, heap_mask, ion_flags); |
| } |
| if (fd2 < 0) |
| { |
| ALOGE("failed to get fd2 from exynos_ion_alloc, %s, %d\n", __func__, __LINE__); |
| close(fd); |
| close(fd1); |
| return -EINVAL; |
| } |
| |
| *hnd = new private_handle_t(fd, fd1, fd2, size, size1, size2, usage, w, h, |
| format, internal_format, frameworkFormat, *stride, luma_vstride, is_compressible); |
| } else { |
| *hnd = new private_handle_t(fd, fd1, -1, size, size1, 0, usage, w, h, |
| format, internal_format, frameworkFormat, *stride, luma_vstride, is_compressible); |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int gralloc_alloc(alloc_device_t* dev, |
| int w, int h, int format, int usage, |
| buffer_handle_t* pHandle, int* pStride) |
| { |
| int stride; |
| int err; |
| unsigned int ion_flags = 0; |
| private_handle_t *hnd = NULL; |
| |
| if (!pHandle || !pStride || w <= 0 || h <= 0) |
| return -EINVAL; |
| |
| if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN) { |
| ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; |
| if (usage & GRALLOC_USAGE_HW_RENDER) |
| ion_flags |= ION_FLAG_SYNC_FORCE; |
| } |
| |
| if (usage & GRALLOC_USAGE_HW_RENDER) |
| ion_flags |= ION_FLAG_MAY_HWRENDER; |
| |
| if (usage & GRALLOC_USAGE_NOZEROED) |
| ion_flags |= ION_FLAG_NOZEROED; |
| |
| private_module_t* m = reinterpret_cast<private_module_t*> |
| (dev->common.module); |
| |
| err = gralloc_alloc_rgb(m->ionfd, w, h, format, usage, ion_flags, &hnd, |
| &stride); |
| if (err) |
| err = gralloc_alloc_yuv(m->ionfd, w, h, format, usage, ion_flags, |
| &hnd, &stride); |
| if (err) |
| goto err; |
| |
| *pHandle = hnd; |
| *pStride = stride; |
| return 0; |
| err: |
| if (!hnd) |
| return err; |
| close(hnd->fd); |
| if (hnd->fd1 >= 0) |
| close(hnd->fd1); |
| if (hnd->fd2 >= 0) |
| close(hnd->fd2); |
| delete hnd; |
| return err; |
| } |
| |
| static int gralloc_free(alloc_device_t* dev, |
| buffer_handle_t handle) |
| { |
| if (private_handle_t::validate(handle) < 0) |
| return -EINVAL; |
| |
| private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle); |
| gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( |
| dev->common.module); |
| if (hnd->base) |
| grallocUnmap(const_cast<private_handle_t*>(hnd)); |
| |
| if (hnd->handle) |
| exynos_ion_free_handle(getIonFd(module), hnd->handle); |
| if (hnd->handle1) |
| exynos_ion_free_handle(getIonFd(module), hnd->handle1); |
| if (hnd->handle2) |
| exynos_ion_free_handle(getIonFd(module), hnd->handle2); |
| |
| close(hnd->fd); |
| if (hnd->fd1 >= 0) |
| close(hnd->fd1); |
| if (hnd->fd2 >= 0) |
| close(hnd->fd2); |
| |
| delete hnd; |
| return 0; |
| } |
| |
| /*****************************************************************************/ |
| |
| static int gralloc_close(struct hw_device_t *dev) |
| { |
| gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev); |
| if (ctx) { |
| /* TODO: keep a list of all buffer_handle_t created, and free them |
| * all here. |
| */ |
| free(ctx); |
| } |
| return 0; |
| } |
| |
| int gralloc_device_open(const hw_module_t* module, const char* name, |
| hw_device_t** device) |
| { |
| int status = -EINVAL; |
| if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { |
| gralloc_context_t *dev; |
| dev = (gralloc_context_t*)malloc(sizeof(*dev)); |
| |
| /* initialize our state here */ |
| memset(dev, 0, sizeof(*dev)); |
| |
| /* initialize the procs */ |
| dev->device.common.tag = HARDWARE_DEVICE_TAG; |
| dev->device.common.version = 0; |
| dev->device.common.module = const_cast<hw_module_t*>(module); |
| dev->device.common.close = gralloc_close; |
| |
| dev->device.alloc = gralloc_alloc; |
| dev->device.free = gralloc_free; |
| |
| private_module_t *p = reinterpret_cast<private_module_t*>(dev->device.common.module); |
| if (p->ionfd == -1) |
| p->ionfd = exynos_ion_open(); |
| |
| *device = &dev->device.common; |
| status = 0; |
| } else { |
| status = fb_device_open(module, name, device); |
| } |
| return status; |
| } |