From: Lajos Molnar Date: Wed, 28 Jan 2015 02:47:28 +0000 (-0800) Subject: exynos: gralloc: implement gralloc_lock_ycbcr X-Git-Url: https://git.stricted.de/?p=GitHub%2FLineageOS%2Fandroid_hardware_samsung_slsi_exynos5.git;a=commitdiff_plain;h=25ffbfe5e8b51f392fafc1bffb16b6633a8ba3df exynos: gralloc: implement gralloc_lock_ycbcr Support only NV12 TILED format used by video decoder for surface output. Bug: 19179288 Change-Id: Iac345ca76cb856a39031d82ee1bbb6177c09a30d --- diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp index b5f269b..8e26ced 100644 --- a/gralloc/gralloc.cpp +++ b/gralloc/gralloc.cpp @@ -71,6 +71,11 @@ extern int gralloc_lock(gralloc_module_t const* module, int l, int t, int w, int h, void** vaddr); +extern int gralloc_lock_ycbcr(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + struct android_ycbcr *ycbcr); + extern int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle); @@ -80,6 +85,9 @@ extern int gralloc_register_buffer(gralloc_module_t const* module, extern int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle); +extern int gralloc_perform(struct gralloc_module_t const* module, + int operation, ... ); + /*****************************************************************************/ static struct hw_module_methods_t gralloc_module_methods = { @@ -101,6 +109,8 @@ base: { unregisterBuffer: gralloc_unregister_buffer, lock: gralloc_lock, unlock: gralloc_unlock, + perform: gralloc_perform, + lock_ycbcr: gralloc_lock_ycbcr, }, framebuffer: 0, flags: 0, diff --git a/gralloc/mapper.cpp b/gralloc/mapper.cpp index 1a70973..190a7a7 100644 --- a/gralloc/mapper.cpp +++ b/gralloc/mapper.cpp @@ -31,6 +31,7 @@ #include #include "gralloc_priv.h" +#include "exynos_format.h" #include #include @@ -57,16 +58,59 @@ static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle) { private_handle_t* hnd = (private_handle_t*)handle; - if (!hnd->base) - return 0; - - if (munmap(hnd->base, hnd->size) < 0) { + if (hnd->base != NULL && munmap(hnd->base, hnd->size) < 0) { ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno), hnd->base, hnd->size); } + hnd->base = NULL; + if (hnd->base1 != NULL && hnd->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + // unmap plane-2 of mapped NV12 TILED format + size_t chroma_vstride = ALIGN(hnd->height / 2, 32); + size_t chroma_size = chroma_vstride * hnd->stride; + if (munmap(hnd->base1, chroma_size) < 0) { + ALOGE("%s :could not unmap %s %p %zd", __func__, strerror(errno), + hnd->base1, chroma_size); + } + hnd->base1 = NULL; + } ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size, hnd->width, hnd->height, hnd->stride); - hnd->base = 0; + return 0; +} + + +static int gralloc_map_yuv(gralloc_module_t const* module, buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + + // only support NV12 TILED format + if (hnd->format != HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + return -EINVAL; + } + + size_t chroma_vstride = ALIGN(hnd->height / 2, 32); + size_t chroma_size = chroma_vstride * hnd->stride; + ALOGI("map_yuv: size=%d/%zu", hnd->size, chroma_size); + + if (hnd->base == NULL) { + int err = gralloc_map(module, handle); + if (err != 0) { + return err; + } + } + + // map plane-2 for NV12 TILED format + void* mappedAddress = mmap(0, chroma_size, PROT_READ|PROT_WRITE, MAP_SHARED, + hnd->fd1, 0); + if (mappedAddress == MAP_FAILED) { + ALOGE("%s: could not mmap %s", __func__, strerror(errno)); + gralloc_unmap(module, handle); + return -errno; + } + + ALOGV("%s: chroma %p %d %d %d %d\n", __func__, mappedAddress, hnd->size, + hnd->width, hnd->height, hnd->stride); + hnd->base1 = mappedAddress; return 0; } @@ -157,6 +201,54 @@ int gralloc_lock(gralloc_module_t const* module, 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, + struct android_ycbcr *ycbcr) +{ + // This is called when a YUV buffer is being locked for software + // access. In this implementation we have nothing to do since + // no synchronization with the HW 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; + ALOGV("lock_ycbcr for fmt=%d %dx%d %dx%d %d", hnd->format, hnd->width, hnd->height, + hnd->stride, hnd->vstride, hnd->size); + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + { + int err = 0; + if (hnd->base1 == NULL || hnd->base == NULL) { + err = gralloc_map_yuv(module, hnd); + } + if (err == 0) { + ycbcr->y = (void*)hnd->base; + ycbcr->cb = (void*)hnd->base1; + ycbcr->cr = (void*)((uint8_t *)hnd->base + 1); + ycbcr->ystride = hnd->stride; + ycbcr->cstride = hnd->stride; + ycbcr->chroma_step = 2; + memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved)); + } + return err; + } + default: + return -EINVAL; + } +} + +int gralloc_perform(struct gralloc_module_t const* module, int operation, ... ) +{ + // dummy implementation required to implement lock_ycbcr + return -EINVAL; +} + int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) {