Add original Samsung hardware projects
Change-Id: I04cce2f71eab586a3782127a55b33e019613bc3f
Signed-off-by: Sam Protsenko <joe.skb7@gmail.com>
diff --git a/gralloc/mapper.cpp b/gralloc/mapper.cpp
new file mode 100644
index 0000000..1f3d3f6
--- /dev/null
+++ b/gralloc/mapper.cpp
@@ -0,0 +1,527 @@
+/*
+ * 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 <log/log.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+#include <inttypes.h>
+#include <sync/sync.h>
+
+#include <hardware/exynos/ion.h>
+#include <linux/ion.h>
+#include <exynos_ion.h>
+#include "gralloc_priv.h"
+#include "exynos_format.h"
+
+#include "VendorVideoAPI.h"
+#define INT_TO_PTR(var) ((void *)(unsigned long)var)
+#define MSCL_EXT_SIZE 512
+#define MSCL_ALIGN 128
+
+#define PRIV_SIZE sizeof(ExynosVideoMeta)
+
+#include "format_chooser.h"
+
+/*****************************************************************************/
+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 = exynos_ion_open();
+ return m->ionfd;
+}
+
+static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle)
+{
+ void *privAddress;
+
+ private_handle_t *hnd = (private_handle_t*)handle;
+ hnd->base = hnd->base1 = hnd->base2 = 0;
+
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
+ privAddress = mmap(0, hnd->size2, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd2, 0);
+ if (privAddress == MAP_FAILED) {
+ ALOGE("%s: could not mmap %s", __func__, strerror(errno));
+ } else {
+ hnd->base2 = (uint64_t)privAddress;
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd2);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ((hnd->flags & GRALLOC_USAGE_PROTECTED) &&
+ !(hnd->flags & GRALLOC_USAGE_PRIVATE_NONSECURE)) {
+ return 0;
+ }
+
+ if (!(hnd->flags & GRALLOC_USAGE_PROTECTED) && !(hnd->flags & GRALLOC_USAGE_NOZEROED)) {
+ 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;
+ }
+ hnd->base = (uint64_t)mappedAddress;
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd);
+
+ if (hnd->fd1 >= 0) {
+ void *mappedAddress1 = (void*)mmap(0, hnd->size1, PROT_READ|PROT_WRITE,
+ MAP_SHARED, hnd->fd1, 0);
+ if (mappedAddress1 == MAP_FAILED) {
+ ALOGE("%s: could not mmap %s", __func__, strerror(errno));
+ return -errno;
+ }
+ hnd->base1 = (uint64_t)mappedAddress1;
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd1);
+ }
+ if (hnd->fd2 >= 0) {
+ if ((hnd->format != HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) &&
+ (hnd->format != HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) {
+ void *mappedAddress2 = (void*)mmap(0, hnd->size2, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd2, 0);
+ if (mappedAddress2 == MAP_FAILED) {
+ ALOGE("%s: could not mmap %s", __func__, strerror(errno));
+ return -errno;
+ }
+ hnd->base2 = (uint64_t)mappedAddress2;
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd2);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int gralloc_unmap(buffer_handle_t handle)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
+ if (munmap(INT_TO_PTR(hnd->base2), hnd->size2) < 0) {
+ ALOGE("%s :could not unmap %s %#" PRIx64 " %d", __func__, strerror(errno), hnd->base2, hnd->size2);
+ }
+ hnd->base2 = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (!hnd->base)
+ return 0;
+
+ if (munmap(INT_TO_PTR(hnd->base), hnd->size) < 0) {
+ ALOGE("%s :could not unmap %s %#" PRIx64 " %d", __func__, strerror(errno), hnd->base, hnd->size);
+ }
+ hnd->base = 0;
+
+ if (hnd->fd1 >= 0) {
+ if (!hnd->base1)
+ return 0;
+ if (munmap(INT_TO_PTR(hnd->base1), hnd->size1) < 0) {
+ ALOGE("%s :could not unmap %s %#" PRIx64 " %d", __func__, strerror(errno), hnd->base1, hnd->size1);
+ }
+ hnd->base1 = 0;
+ }
+ if (hnd->fd2 >= 0) {
+ if (!hnd->base2)
+ return 0;
+ if (munmap(INT_TO_PTR(hnd->base2), hnd->size2) < 0) {
+ ALOGE("%s :could not unmap %s %#" PRIx64 " %d", __func__, strerror(errno), hnd->base2, hnd->size2);
+ }
+ hnd->base2 = 0;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+
+int grallocMap(gralloc_module_t const* module, private_handle_t *hnd)
+{
+ return gralloc_map(module, hnd);
+}
+
+int grallocUnmap(private_handle_t *hnd)
+{
+ return gralloc_unmap(hnd);
+}
+
+/*****************************************************************************/
+
+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 %#" PRIx64 " %d %d %d %d\n", __func__, hnd->base, hnd->size,
+ hnd->width, hnd->height, hnd->stride);
+
+ int ret;
+ ret = exynos_ion_import_handle(getIonFd(module), hnd->fd, &hnd->handle);
+ if (ret)
+ ALOGE("error importing handle %d %x\n", hnd->fd, hnd->format);
+ if (hnd->fd1 >= 0) {
+ ret = exynos_ion_import_handle(getIonFd(module), hnd->fd1, &hnd->handle1);
+ if (ret)
+ ALOGE("error importing handle1 %d %x\n", hnd->fd1, hnd->format);
+ }
+ if (hnd->fd2 >= 0) {
+ ret = exynos_ion_import_handle(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 %#" PRIx64 " %d %d %d %d\n", __func__, hnd->base, hnd->size,
+ hnd->width, hnd->height, hnd->stride);
+
+ gralloc_unmap(handle);
+
+ 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);
+
+ 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)
+ {
+ ALOGE("handle is not valid. usage(%x), l,t,w,h(%d, %d, %d, %d)\n", usage, l, t, w, h);
+ return -EINVAL;
+ }
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+ if (hnd->frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ ALOGE("gralloc_lock can't be used with YCbCr_420_888 format");
+ return -EINVAL;
+ }
+
+ switch(hnd->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:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ break;
+ default:
+ ALOGE("gralloc_lock doesn't support YUV formats. Please use gralloc_lock_ycbcr()");
+ return -EINVAL;
+ }
+
+#ifdef GRALLOC_RANGE_FLUSH
+ if(usage & GRALLOC_USAGE_SW_WRITE_MASK)
+ {
+ hnd->lock_usage = GRALLOC_USAGE_SW_WRITE_RARELY;
+ hnd->lock_offset = t * hnd->stride;
+ hnd->lock_len = h * hnd->stride;
+ }
+ else
+ {
+ hnd->lock_usage = 0;
+ hnd->lock_offset = 0;
+ hnd->lock_len = 0;
+ }
+#endif
+
+ if (!hnd->base)
+ gralloc_map(module, hnd);
+
+ *vaddr = INT_TO_PTR(hnd->base);
+
+ 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;
+
+#ifdef GRALLOC_RANGE_FLUSH
+ if(hnd->lock_usage & GRALLOC_USAGE_SW_WRITE_MASK)
+ {
+ if(((hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+ || (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)) && (hnd->lock_offset != 0))
+ exynos_ion_sync_fd_partial(getIonFd(module), hnd->fd, hnd->lock_offset * 4, hnd->lock_len * 4);
+ else
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd);
+
+ if (hnd->fd1 >= 0)
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd1);
+ if (hnd->fd2 >= 0)
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd2);
+
+ hnd->lock_usage = 0;
+ }
+#else
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd);
+
+ if (hnd->fd1 >= 0)
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd1);
+ if (hnd->fd2 >= 0)
+ exynos_ion_sync_fd(getIonFd(module), hnd->fd2);
+#endif
+
+ return 0;
+}
+
+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)
+{
+ if (private_handle_t::validate(handle) < 0)
+ {
+ ALOGE("handle is not valid. usage(%x), l,t,w,h(%d, %d, %d, %d)\n", usage, l, t, w, h);
+ return -EINVAL;
+ }
+
+ if (!ycbcr) {
+ ALOGE("gralloc_lock_ycbcr got NULL ycbcr struct");
+ return -EINVAL;
+ }
+
+ int ext_size = 256;
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+ if (!hnd->base)
+ gralloc_map(module, hnd);
+
+ // If all CPU addresses are still NULL, do not anything.
+ if (!hnd->base && !hnd->base1 && !hnd->base2)
+ return 0;
+
+ // Calculate offsets to underlying YUV data
+ size_t yStride;
+ size_t cStride;
+ size_t uOffset;
+ size_t vOffset;
+ size_t cStep;
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ yStride = cStride = hnd->width;
+ vOffset = yStride * hnd->height;
+ uOffset = vOffset + 1;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)(((unsigned long)hnd->base) + uOffset);
+ ycbcr->cr = (void *)(((unsigned long)hnd->base) + vOffset);
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ yStride = ALIGN(hnd->width, 16);
+ cStride = ALIGN(yStride/2, 16);
+ vOffset = yStride * hnd->height;
+ uOffset = vOffset + (cStride * (hnd->height / 2));
+ cStep = 1;
+ ycbcr->y = (void*)((unsigned long)hnd->base);
+ ycbcr->cr = (void*)(((unsigned long)hnd->base) + vOffset);
+ ycbcr->cb = (void*)(((unsigned long)hnd->base) + uOffset);
+ cStep = 1;
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ yStride = cStride = hnd->stride;
+ vOffset = 1;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)((unsigned long)hnd->base1);
+ ycbcr->cr = (void *)(((unsigned long)hnd->base1) + vOffset);
+
+ if ((hnd->format != HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M) && (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) /* usage name will be changed as GRALLOC_USAGE_HW_VIDEO since v2.0 */
+ ycbcr->cr = (void *)((unsigned long)hnd->base2);
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+ yStride = hnd->stride;
+ cStride = ALIGN(yStride/2, 16);
+ uOffset = yStride * hnd->height;
+ vOffset = uOffset + (cStride * (hnd->height / 2));
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void*)(((unsigned long)hnd->base) + uOffset);
+ ycbcr->cr = (void*)(((unsigned long)hnd->base) + vOffset);
+ break;
+ /* separated color plane */
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: /* can't describe tiled format for user application */
+ if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { /* usage name will be changed as GRALLOC_USAGE_HW_VIDEO since v2.0 */
+ yStride = hnd->stride;
+ cStride = hnd->stride;
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)((unsigned long)hnd->base1);
+ ycbcr->cr = NULL;
+ } else {
+ ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
+ hnd->format);
+ return -EINVAL;
+ }
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
+ yStride = cStride = hnd->stride;
+ uOffset = 1;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cr = (void *)((unsigned long)hnd->base1);
+ ycbcr->cb = (void *)(((unsigned long)hnd->base1) + uOffset);
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+ yStride = hnd->stride;
+ cStride = ALIGN(yStride/2, 16);
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)((unsigned long)hnd->base1);
+ ycbcr->cr = (void *)((unsigned long)hnd->base2);
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+ yStride = hnd->stride;
+ cStride = ALIGN(yStride/2, 16);
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cr = (void *)((unsigned long)hnd->base1);
+ ycbcr->cb = (void *)((unsigned long)hnd->base2);
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ yStride = cStride = hnd->stride;
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = 0;
+ ycbcr->cr = 0;
+ break;
+ /* included h/w restrictions */
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+ yStride = cStride = hnd->stride;
+ uOffset = (yStride * hnd->vstride) + ext_size;
+ vOffset = uOffset + 1;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)(((unsigned long)hnd->base) + uOffset);
+ ycbcr->cr = (void *)(((unsigned long)hnd->base) + vOffset);
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
+ yStride = cStride = hnd->stride;
+ uOffset = ((yStride * hnd->vstride) + ext_size) + ((ALIGN(hnd->width / 4, 16) * hnd->vstride) + 64);
+ vOffset = uOffset + 1;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)(((unsigned long)hnd->base) + uOffset);
+ ycbcr->cr = (void *)(((unsigned long)hnd->base) + vOffset);
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_Y16:
+ yStride = cStride = hnd->stride;
+ uOffset = 0;
+ vOffset = 0;
+ cStep = 1;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = 0;
+ ycbcr->cr = 0;
+ break;
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
+ yStride = cStride = hnd->stride;
+ vOffset = 2;
+ cStep = 2;
+ ycbcr->y = (void *)((unsigned long)hnd->base);
+ ycbcr->cb = (void *)((unsigned long)hnd->base1);
+ ycbcr->cr = (void *)((unsigned long)hnd->base2);
+ break;
+ default:
+ ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
+ hnd->format);
+ return -EINVAL;
+ }
+
+ ycbcr->ystride = yStride;
+ ycbcr->cstride = cStride;
+ ycbcr->chroma_step = cStep;
+
+ // Zero out reserved fields
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+/*
+ ALOGD("gralloc_lock_ycbcr success. format : %x, usage: %x, ycbcr.y: %p, .cb: %p, .cr: %p, "
+ ".ystride: %d , .cstride: %d, .chroma_step: %d", hnd->format, usage,
+ ycbcr->y, ycbcr->cb, ycbcr->cr, ycbcr->ystride, ycbcr->cstride,
+ ycbcr->chroma_step);
+*/
+
+ return 0;
+}