diff options
author | codewalker <codewalker@hardkernel.com> | 2014-08-19 18:20:50 +0900 |
---|---|---|
committer | Dongjin Kim <tobetter@gmail.com> | 2014-08-19 18:47:59 +0900 |
commit | 500214a10db4a78d4eee9649ced413716b7c2fbb (patch) | |
tree | 5731fbcab43476265d26996e5be9e6fe50545f8b /gralloc | |
parent | 6414706ded5e58737ec115a9963d24627e02f8e1 (diff) | |
download | android_hardware_samsung_slsi_exynos5430-500214a10db4a78d4eee9649ced413716b7c2fbb.tar.gz android_hardware_samsung_slsi_exynos5430-500214a10db4a78d4eee9649ced413716b7c2fbb.tar.xz android_hardware_samsung_slsi_exynos5430-500214a10db4a78d4eee9649ced413716b7c2fbb.zip |
Samsung Patch (05/27/2014) - RTM 1.00
Change-Id: I013f933ac0a52c4cc1b5e5b550a92b06534a0a34
Diffstat (limited to 'gralloc')
-rw-r--r-- | gralloc/Android.mk | 40 | ||||
-rw-r--r-- | gralloc/framebuffer.cpp | 274 | ||||
-rw-r--r-- | gralloc/gr.h | 43 | ||||
-rw-r--r-- | gralloc/gralloc.cpp | 457 | ||||
-rw-r--r-- | gralloc/mapper.cpp | 273 |
5 files changed, 1087 insertions, 0 deletions
diff --git a/gralloc/Android.mk b/gralloc/Android.mk new file mode 100644 index 0000000..6c84519 --- /dev/null +++ b/gralloc/Android.mk @@ -0,0 +1,40 @@ +# 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. + + +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation stored in +# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) + +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libion libutils + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + $(TOP)/hardware/samsung_slsi/exynos5/include + +LOCAL_SRC_FILES := \ + gralloc.cpp \ + framebuffer.cpp \ + mapper.cpp + +LOCAL_MODULE := gralloc.exynos5 +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_OWNER := samsung_arm + +include $(BUILD_SHARED_LIBRARY) diff --git a/gralloc/framebuffer.cpp b/gralloc/framebuffer.cpp new file mode 100644 index 0000000..e3ff9f1 --- /dev/null +++ b/gralloc/framebuffer.cpp @@ -0,0 +1,274 @@ +/* + * 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 <sys/mman.h> + +#include <dlfcn.h> + +#include <cutils/ashmem.h> +#include <cutils/log.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <string.h> +#include <stdlib.h> + +#include <utils/Vector.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#if HAVE_ANDROID_OS +#include <linux/fb.h> +#endif + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +// numbers of buffers for page flipping +#define NUM_BUFFERS 2 +#define HWC_EXIST 0 + +struct hwc_callback_entry +{ + void (*callback)(void *, private_handle_t *); + void *data; +}; + +typedef android::Vector<struct hwc_callback_entry> hwc_callback_queue_t; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +static int fb_setSwapInterval(struct framebuffer_device_t* dev, + int interval) +{ + fb_context_t* ctx = (fb_context_t*)dev; + if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) + return -EINVAL; + // FIXME: implement fb_setSwapInterval + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + return -EINVAL; + + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); +#if HWC_EXIST + hwc_callback_queue_t *queue = reinterpret_cast<hwc_callback_queue_t *>(m->queue); + pthread_mutex_lock(&m->queue_lock); + if(queue->isEmpty()) + pthread_mutex_unlock(&m->queue_lock); + else { + private_handle_t *hnd = private_handle_t::dynamicCast(buffer); + struct hwc_callback_entry entry = queue->top(); + queue->pop(); + pthread_mutex_unlock(&m->queue_lock); + entry.callback(entry.data, hnd); + } +#else + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, + GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, + &fb_vaddr); + + m->base.lock(&m->base, buffer, + GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); +#endif + return 0; +} + +/*****************************************************************************/ + +static int fb_close(struct hw_device_t *dev) +{ + fb_context_t* ctx = (fb_context_t*)dev; + if (ctx) { + free(ctx); + } + return 0; +} + +int init_fb(struct private_module_t* module) +{ + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + NULL + }; + + int fd = -1; + int i = 0; + + fd = open("/dev/graphics/fb0", O_RDWR); + if (fd < 0) { + ALOGE("/dev/graphics/fb0 Open fail"); + return -errno; + } + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + ALOGE("Fail to get FB Screen Info"); + close(fd); + return -errno; + } + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { + ALOGE("First, Fail to get FB VScreen Info"); + close(fd); + return -errno; + } + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) + refreshRate = 60*1000; /* 60 Hz */ + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + ALOGI("using (id=%s)\n" + "xres = %d px\n" + "yres = %d px\n" + "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + finfo.id, info.xres, info.yres, info.width, xdpi, info.height, ydpi, + fps); + + module->xres = info.xres; + module->yres = info.yres; + module->line_length = info.xres; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + module->info = info; + module->finfo = finfo; + + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, 0); + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); + close(fd); + return -errno; + } + module->framebuffer->base = vaddr; + memset(vaddr, 0, fbSize); + + close(fd); + + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; +#ifdef GRALLOC_16_BITS + int bits_per_pixel = 16; + int format = HAL_PIXEL_FORMAT_RGB_565; +#else + int bits_per_pixel = 32; + int format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif + + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) { + ALOGE("Fail to Open gralloc device"); + return status; + } + + framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t)); + if (dev == NULL) { + ALOGE("Failed to allocate memory for dev"); + gralloc_close(gralloc_device); + return status; + } + + private_module_t* m = (private_module_t*)module; + status = init_fb(m); + if (status < 0) { + ALOGE("Fail to init framebuffer"); + free(dev); + gralloc_close(gralloc_device); + return status; + } + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast<hw_module_t*>(module); + dev->common.close = fb_close; + dev->setSwapInterval = 0; + dev->post = fb_post; + dev->setUpdateRect = 0; + dev->compositionComplete = 0; + m->queue = new hwc_callback_queue_t; + pthread_mutex_init(&m->queue_lock, NULL); + + int stride = m->line_length / (bits_per_pixel >> 3); + const_cast<uint32_t&>(dev->flags) = 0; + const_cast<uint32_t&>(dev->width) = m->xres; + const_cast<uint32_t&>(dev->height) = m->yres; + const_cast<int&>(dev->stride) = stride; + const_cast<int&>(dev->format) = format; + const_cast<float&>(dev->xdpi) = m->xdpi; + const_cast<float&>(dev->ydpi) = m->ydpi; + const_cast<float&>(dev->fps) = m->fps; + const_cast<int&>(dev->minSwapInterval) = 1; + const_cast<int&>(dev->maxSwapInterval) = 1; + *device = &dev->common; + status = 0; + + return status; +} diff --git a/gralloc/gr.h b/gralloc/gr.h new file mode 100644 index 0000000..6fe26b6 --- /dev/null +++ b/gralloc/gr.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef GR_H_ +#define GR_H_ + +#include <stdint.h> +#include <limits.h> +#include <sys/cdefs.h> +#include <hardware/gralloc.h> +#include <pthread.h> +#include <errno.h> + +#include <cutils/native_handle.h> + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +#ifndef SUPPORT_DIRECT_FB +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} +#endif + +int grallocMap(gralloc_module_t const* module, private_handle_t *hnd); +int grallocUnmap(gralloc_module_t const* module, private_handle_t *hnd); + +#endif /* GR_H_ */ diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp new file mode 100644 index 0000000..8409789 --- /dev/null +++ b/gralloc/gralloc.cpp @@ -0,0 +1,457 @@ +/* + * 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. + */ + +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include <asm/page.h> +#else +# include <sys/user.h> +#endif +#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 <ion/ion.h> +#include <linux/ion.h> +#include <cutils/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" + +#define ION_HEAP_EXYNOS_CONTIG_MASK (1 << 4) +#define ION_EXYNOS_FIMD_VIDEO_MASK (1 << 28) +#define ION_EXYNOS_MFC_OUTPUT_MASK (1 << 26) +#define ION_EXYNOS_MFC_INPUT_MASK (1 << 25) +#define ION_EXYNOS_G2D_WFD_MASK (1 << 22) +#define MB_1 (1024*1024) + +#define ION_FLAG_PRESERVE_KMAP 4 + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ +}; + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle); + +/*****************************************************************************/ + +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_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 = { +open: gralloc_device_open +}; + +struct private_module_t HAL_MODULE_INFO_SYM = { +base: { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 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, +}, +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; + if (usage & GRALLOC_USAGE_PROTECTED) + heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK; + else + heap_mask = ION_HEAP_SYSTEM_MASK; + + if (usage & GRALLOC_USAGE_GPU_BUFFER) + heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK; + + return heap_mask; +} + +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 size, bpr, alignment = 0, ext_size=256; + int bpp = 0, vstride, fd, err; + unsigned int heap_mask = _select_heap(usage); + + switch (format) { + 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: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RAW_SENSOR: + 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) { + if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) || (format == HAL_PIXEL_FORMAT_BGRA_8888)) { + bpr = ALIGN(w, 16)* bpp; + vstride = ALIGN(h, 16); + } else { + bpr = ALIGN(w*bpp, 16); + vstride = h; + } + if (vstride < h + 2) + size = bpr * (h + 2); + else + size = bpr * vstride; + *stride = bpr / bpp; + size = ALIGN(size, PAGE_SIZE)+ext_size; + } + + if (usage & GRALLOC_USAGE_PROTECTED) { + if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE) + alignment = 0; + else + alignment = MB_1; + if ((usage & GRALLOC_USAGE_PRIVATE_NONSECURE) && (usage & GRALLOC_USAGE_PHYSICALLY_LINEAR)) + ion_flags |= ION_EXYNOS_G2D_WFD_MASK; + else + ion_flags |= ION_EXYNOS_FIMD_VIDEO_MASK; + } + + err = ion_alloc_fd(ionfd, size, alignment, heap_mask, ion_flags, + &fd); + if (err) { + if (usage & GRALLOC_USAGE_GPU_BUFFER) { + usage &= ~GRALLOC_USAGE_GPU_BUFFER; + heap_mask = _select_heap(usage); + err = ion_alloc_fd(ionfd, size, alignment, heap_mask, ion_flags, + &fd); + if (err) + return err; + } + else + return err; + } + *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, + vstride); + + return err; +} + +static int gralloc_alloc_framework_yuv(int ionfd, int w, int h, int format, + int usage, unsigned int ion_flags, + private_handle_t **hnd, int *stride) +{ + size_t size=0, ext_size=256; + int err, fd; + unsigned int heap_mask = _select_heap(usage); + + 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 * ALIGN(h, 16) * 3 / 2 + ext_size; + break; + default: + ALOGE("invalid yuv format %d\n", format); + return -EINVAL; + } + + err = ion_alloc_fd(ionfd, size, 0, heap_mask, ion_flags, &fd); + if (err) + return err; + + *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, h); + return err; +} + +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 err, planes, fd = -1, fd1 = -1, fd2 = -1; + size_t luma_vstride; + unsigned int heap_mask = _select_heap(usage); + + *stride = ALIGN(w, 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) { + format = HAL_PIXEL_FORMAT_EXYNOS_YV12_M; + } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { + format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M; // NV12M + } + } + if (usage & GRALLOC_USAGE_PROTECTED) + ion_flags |= ION_EXYNOS_MFC_OUTPUT_MASK; + + switch (format) { + case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: + { + *stride = ALIGN(w, 32); + luma_vstride = ALIGN(h, 16); + luma_size = luma_vstride * *stride + ext_size; + chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16) + ext_size; + 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: + return gralloc_alloc_framework_yuv(ionfd, w, h, format, 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_vstride = ALIGN(h, 16); + luma_size = *stride * luma_vstride+ext_size; + chroma_size = *stride * ALIGN(luma_vstride / 2, 8)+ext_size; + planes = 2; + break; + } + case HAL_PIXEL_FORMAT_YCbCr_422_I: + { + luma_vstride = h; + luma_size = luma_vstride * *stride * 2+ext_size; + chroma_size = 0; + planes = 1; + break; + } + default: + ALOGE("invalid yuv format %d\n", format); + return -EINVAL; + } + + err = ion_alloc_fd(ionfd, luma_size, 0, heap_mask, ion_flags, &fd); + if (err) + return err; + if (planes == 1) { + *hnd = new private_handle_t(fd, luma_size, usage, w, h, + format, *stride, luma_vstride); + } else { + err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd1); + if (err) + goto err1; + if (planes == 3) { + err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd2); + if (err) + goto err2; + + *hnd = new private_handle_t(fd, fd1, fd2, luma_size, usage, w, h, + format, *stride, luma_vstride); + } else { + *hnd = new private_handle_t(fd, fd1, luma_size, usage, w, h, format, + *stride, luma_vstride); + } + } + return err; + +err2: + close(fd1); +err1: + close(fd); + return err; +} + +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 | ION_FLAG_PRESERVE_KMAP; + + private_module_t* m = reinterpret_cast<private_module_t*> + (dev->common.module); + gralloc_module_t* module = reinterpret_cast<gralloc_module_t*> + (dev->common.module); + + if ((usage & GRALLOC_USAGE_GPU_BUFFER) && (w*h != (m->xres)*(m->yres))) + usage &= ~GRALLOC_USAGE_GPU_BUFFER; + + 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(module, const_cast<private_handle_t*>(hnd)); + + 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); + p->ionfd = ion_open(); + + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/gralloc/mapper.cpp b/gralloc/mapper.cpp new file mode 100644 index 0000000..915b540 --- /dev/null +++ b/gralloc/mapper.cpp @@ -0,0 +1,273 @@ +/* + * 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 <errno.h> +#include <pthread.h> +#include <unistd.h> +#include <string.h> + +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include "gralloc_priv.h" +#include "exynos_format.h" + +#include <ion/ion.h> +#include <linux/ion.h> + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle) +{ + size_t chroma_vstride = 0; + size_t chroma_size = 0; + size_t ext_size = 256; + + private_handle_t *hnd = (private_handle_t*)handle; + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: + chroma_vstride = ALIGN(hnd->height / 2, 32); + chroma_size = chroma_vstride * hnd->stride + ext_size; + break; + 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: + chroma_size = hnd->stride * ALIGN(hnd->vstride / 2, 8) + ext_size; + break; + case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: + chroma_size = (hnd->vstride / 2) * ALIGN(hnd->stride / 2, 16) + ext_size; + break; + default: + break; + } + + void* mappedAddress = mmap(0, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, + hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + ALOGE("%s: could not mmap %s", __func__, strerror(errno)); + return -errno; + } + ALOGV("%s: base %p %d %d %d %d\n", __func__, mappedAddress, hnd->size, + hnd->width, hnd->height, hnd->stride); + hnd->base = mappedAddress; + + if (hnd->fd1 >= 0) { + void *mappedAddress1 = (void*)mmap(0, chroma_size, PROT_READ|PROT_WRITE, + MAP_SHARED, hnd->fd1, 0); + hnd->base1 = mappedAddress1; + } + if (hnd->fd2 >= 0) { + void *mappedAddress2 = (void*)mmap(0, chroma_size, PROT_READ|PROT_WRITE, + MAP_SHARED, hnd->fd2, 0); + hnd->base2 = mappedAddress2; + } + + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + size_t chroma_vstride = 0; + size_t chroma_size = 0; + size_t ext_size = 256; + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: + chroma_vstride = ALIGN(hnd->height / 2, 32); + chroma_size = chroma_vstride * hnd->stride + ext_size; + break; + 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: + chroma_size = hnd->stride * ALIGN(hnd->vstride / 2, 8) + ext_size; + break; + case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: + chroma_size = (hnd->vstride / 2) * ALIGN(hnd->stride / 2, 16) + ext_size; + break; + default: + break; + } + + if (!hnd->base) + return 0; + + if (munmap(hnd->base, hnd->size) < 0) { + ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno), + hnd->base, hnd->size); + } + ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size, + hnd->width, hnd->height, hnd->stride); + hnd->base = 0; + if (hnd->fd1 >= 0) { + if (!hnd->base1) + return 0; + if (munmap(hnd->base1, chroma_size) < 0) { + ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno), + hnd->base1, chroma_size); + } + hnd->base1 = 0; + } + if (hnd->fd2 >= 0) { + if (!hnd->base2) + return 0; + if (munmap(hnd->base2, chroma_size) < 0) { + ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno), + hnd->base2, chroma_size); + } + hnd->base2 = 0; + } + return 0; +} + +/*****************************************************************************/ + +int grallocMap(gralloc_module_t const* module, private_handle_t *hnd) +{ + return gralloc_map(module, hnd); +} + +int grallocUnmap(gralloc_module_t const* module, private_handle_t *hnd) +{ + return gralloc_unmap(module, hnd); +} + +int getIonFd(gralloc_module_t const *module) +{ + private_module_t* m = const_cast<private_module_t*>(reinterpret_cast<const private_module_t*>(module)); + if (m->ionfd == -1) + m->ionfd = ion_open(); + return m->ionfd; +} + +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + int err; + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + err = gralloc_map(module, handle); + + private_handle_t* hnd = (private_handle_t*)handle; + ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size, + hnd->width, hnd->height, hnd->stride); + + int ret; + ret = ion_import(getIonFd(module), hnd->fd, &hnd->handle); + if (ret) + ALOGE("error importing handle %d %x\n", hnd->fd, hnd->format); + if (hnd->fd1 >= 0) { + ret = ion_import(getIonFd(module), hnd->fd1, &hnd->handle1); + if (ret) + ALOGE("error importing handle1 %d %x\n", hnd->fd1, hnd->format); + } + if (hnd->fd2 >= 0) { + ret = ion_import(getIonFd(module), hnd->fd2, &hnd->handle2); + if (ret) + ALOGE("error importing handle2 %d %x\n", hnd->fd2, hnd->format); + } + + return err; +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size, + hnd->width, hnd->height, hnd->stride); + + gralloc_unmap(module, handle); + + if (hnd->handle) + ion_free(getIonFd(module), hnd->handle); + if (hnd->handle1) + ion_free(getIonFd(module), hnd->handle1); + if (hnd->handle2) + ion_free(getIonFd(module), hnd->handle2); + + return 0; +} + +int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr) +{ + // this is called when a buffer is being locked for software + // access. in thin implementation we have nothing to do since + // not synchronization with the h/w is needed. + // typically this is used to wait for the h/w to finish with + // this buffer if relevant. the data cache may need to be + // flushed or invalidated depending on the usage bits and the + // hardware. + + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + if (!hnd->base) + gralloc_map(module, hnd); + *vaddr = (void*)hnd->base; + + if (hnd->fd1 >= 0) + vaddr[1] = (void*)hnd->base1; + if (hnd->fd2 >= 0) + vaddr[2] = (void*)hnd->base2; + + return 0; +} + +int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle) +{ + // we're done with a software buffer. nothing to do in this + // implementation. typically this is used to flush the data cache. + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + + if (!((hnd->flags & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)) + return 0; + + ion_sync_fd(getIonFd(module), hnd->fd); + if (hnd->fd1 >= 0) + ion_sync_fd(getIonFd(module), hnd->fd1); + if (hnd->fd2 >= 0) + ion_sync_fd(getIonFd(module), hnd->fd2); + + return 0; +} |