blob: aa31bc345ec20d01ed2cde3c90231a3f82c6c413 [file] [log] [blame]
/*
* Copyright (C) 2016 ARM Limited. All rights reserved.
*
* Copyright (C) 2008 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 "mali_gralloc_bufferaccess.h"
static int gralloc_map(mali_gralloc_module const* module, buffer_handle_t handle)
{
private_handle_t *hnd = (private_handle_t*)handle;
int err = 0;
hnd->base = hnd->base1 = hnd->base2 = 0;
// AFBC must not be mapped.
if (hnd->is_compressible)
return 0;
// Map for Private data
mapForPrivateData(module, hnd);
// Don't be mapped for Secure DRM & Secure Camera
if (((hnd->producer_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) && !GRALLOC1_SLSI_USAGE_CHECK(hnd->consumer_usage, GRALLOC1_PRODUCER_USAGE_PRIVATE_NONSECURE))
|| GRALLOC1_SLSI_USAGE_CHECK(hnd->producer_usage, GRALLOC1_PRODUCER_USAGE_SECURE_CAMERA_RESERVED))
return 0;
// Map for Buffer
if (!(hnd->producer_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED)
&& !GRALLOC1_SLSI_USAGE_CHECK(hnd->producer_usage, GRALLOC1_PRODUCER_USAGE_NOZEROED)
&& !GRALLOC1_SLSI_USAGE_CHECK(hnd->producer_usage, GRALLOC1_PRODUCER_USAGE_SECURE_CAMERA_RESERVED))
{
// Map for fd
if (hnd->fd >= 0 && !hnd->base)
{
err = mapForFds(module, hnd, 0);
if (err)
return err;
}
// Map for fd1
if (hnd->fd1 >= 0 && !hnd->base1)
{
err = mapForFds(module, hnd, 1);
if (err)
return err;
}
// Map for fd2
if (hnd->fd2 >= 0 && !hnd->base2)
{
err = mapForFds(module, hnd, 2);
if (err)
return err;
}
}
return 0;
}
static int gralloc_unmap(buffer_handle_t handle)
{
private_handle_t* hnd = (private_handle_t*)handle;
// Unmap for Private data
unmapForPrivateData(hnd);
// Early-out for Unmapped Buffer
if (!hnd->base)
return 0;
// Unmap for fd
if (hnd->fd >= 0 && hnd->base)
{
if (munmap(INT_TO_PTR(hnd->base), hnd->size) < 0)
AERR("%s(%d) :could not unmap %s %d %#" PRIx64, __func__, __LINE__, strerror(errno), hnd->size, hnd->base);
hnd->base = 0;
}
// Unmap for fd1
if (hnd->fd1 >= 0 && hnd->base1)
{
if (munmap(INT_TO_PTR(hnd->base1), hnd->size1) < 0)
AERR("%s(%d) :could not unmap %s %d %#" PRIx64, __func__, __LINE__, strerror(errno), hnd->size1, hnd->base1);
hnd->base1 = 0;
}
// Unmap for fd2
if (hnd->fd2 >= 0 && hnd->base2)
{
if (munmap(INT_TO_PTR(hnd->base2), hnd->size2) < 0)
AERR("%s(%d) :could not unmap %s %d %#" PRIx64, __func__, __LINE__, strerror(errno), hnd->size2, hnd->base2);
hnd->base2 = 0;
}
return 0;
}
int grallocUnmap(private_handle_t *hnd)
{
return gralloc_unmap(hnd);
}
int gralloc_register_buffer(mali_gralloc_module const* module,
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
gralloc_map(module, handle);
private_handle_t* hnd = (private_handle_t*)handle;
int ret;
ret = exynos_ion_import_handle(getIonFd(module), hnd->fd, &hnd->handle);
if (ret)
AERR("error importing handle fd(%d) format(%x)\n", hnd->fd, hnd->format);
if (hnd->fd1 >= 0)
{
ret = exynos_ion_import_handle(getIonFd(module), hnd->fd1, &hnd->handle1);
if (ret)
AERR("error importing handle1 fd1(%d) format(%x)\n", hnd->fd1, hnd->format);
}
if (hnd->fd2 >= 0)
{
ret = exynos_ion_import_handle(getIonFd(module), hnd->fd2, &hnd->handle2);
if (ret)
AERR("error importing handle2 fd2(%d) format(%x)\n", hnd->fd2, hnd->format);
}
return 0;
}
int gralloc_unregister_buffer(mali_gralloc_module const* module,
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
private_handle_t* hnd = (private_handle_t*)handle;
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 mali_gralloc_lock(const mali_gralloc_module* m, buffer_handle_t buffer, uint64_t usage, int l, int t, int w, int h, void** vaddr)
{
GRALLOC_UNUSED(m);
GRALLOC_UNUSED(l);
GRALLOC_UNUSED(t);
GRALLOC_UNUSED(w);
GRALLOC_UNUSED(h);
if (private_handle_t::validate(buffer) < 0)
{
AERR("Locking invalid buffer %p, returning error", buffer);
return -EINVAL;
}
private_handle_t* hnd = (private_handle_t*)buffer;
if (hnd->internal_format == HAL_PIXEL_FORMAT_YCbCr_420_888)
{
AERR("Buffers with format YCbCr_420_888 must be locked using (*lock_ycbcr)" );
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:
case HAL_PIXEL_FORMAT_RGBA_FP16:
break;
default:
AERR("mali_gralloc_lock doesn't support YUV formats. Please use gralloc_lock_ycbcr()");
return -EINVAL;
}
// For Range Flush
lockForRangeFlush(hnd, usage, t, h);
// Map if CPU address is NULL
if (!hnd->base)
{
gralloc_map(m, hnd);
}
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_ION))
hnd->writeOwner = usage & GRALLOC1_USAGE_SW_WRITE_MASK;
// return CPU address
if (usage & (GRALLOC1_USAGE_SW_READ_MASK | GRALLOC1_USAGE_SW_WRITE_MASK))
*vaddr = INT_TO_PTR(hnd->base);
return 0;
}
int mali_gralloc_unlock(const mali_gralloc_module* module, buffer_handle_t buffer)
{
if (private_handle_t::validate(buffer) < 0)
{
AERR( "Unlocking invalid buffer %p, returning error", buffer);
return -EINVAL;
}
private_handle_t* hnd = (private_handle_t*)buffer;
// Ealry out for Non-cachable buffer
if (!((hnd->consumer_usage & GRALLOC1_USAGE_SW_READ_MASK) == GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
return 0;
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_ION) && hnd->writeOwner && !hnd->is_compressible)
{
// Cache flush & Invalidate for all fds
doCacheFlushAndInvalidate(module, hnd);
}
return 0;
}
int mali_gralloc_get_num_flex_planes(const mali_gralloc_module* m, buffer_handle_t buffer, uint32_t* num_planes)
{
GRALLOC_UNUSED(m);
if (private_handle_t::validate(buffer) < 0)
{
AERR("Invalid buffer %p, returning error", buffer);
return -EINVAL;
}
if (NULL == num_planes)
{
return -EINVAL;
}
private_handle_t* hnd = (private_handle_t*)buffer;
uint64_t base_format = hnd->internal_format & GRALLOC_ARM_INTFMT_FMT_MASK;
// the number of YCBCR planes should be 3.
switch (base_format)
{
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
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_P_M:
case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
case HAL_PIXEL_FORMAT_Y8:
case HAL_PIXEL_FORMAT_Y16:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
*num_planes = 3;
break;
default:
AERR("Can't get planes number of buffer %p: with format %" PRIx64, hnd, hnd->internal_format);
return -EINVAL;
}
return 0;
}
int mali_gralloc_lock_async(const mali_gralloc_module* m, buffer_handle_t buffer, uint64_t usage,
int l, int t, int w, int h, void** vaddr, int32_t fence_fd)
{
if (fence_fd >= 0)
{
sync_wait(fence_fd, -1);
close(fence_fd);
}
return mali_gralloc_lock(m, buffer, usage, l, t, w, h, vaddr);
}
static int getYCbCrInfo(private_handle_t *hnd, uint64_t usage, android_ycbcr* ycbcr)
{
// Calculate offsets to underlying YUV data
int ext_size = 256;
size_t yStride;
size_t cStride;
size_t uOffset;
size_t vOffset;
size_t cStep;
switch (hnd->format)
{
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
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 (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_3PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base2);
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
yStride = cStride = hnd->stride;
uOffset = (SBWC_8B_Y_SIZE(hnd->width, hnd->height) + SBWC_8B_Y_HEADER_SIZE(hnd->width, hnd->height));
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);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_2PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base1);
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
yStride = cStride = hnd->stride;
uOffset = NV12N_S8B_LUMA_SIZE(yStride, hnd->vstride, ext_size) + NV12N_S2B_SIZE(hnd->width, hnd->vstride);
uOffset = (SBWC_10B_Y_SIZE(hnd->width, hnd->height) + SBWC_10B_Y_HEADER_SIZE(hnd->width, hnd->height));
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);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_2PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base1);
}
break;
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 = GRALLOC_ALIGN(hnd->width, 16);
cStride = GRALLOC_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_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 (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_3PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base2);
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
yStride = hnd->stride;
cStride = GRALLOC_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;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
if (usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER)
{
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 {
AERR("getYCbCrInfo 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);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_3PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cb = (void *)((unsigned long)hnd->base2);
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
yStride = hnd->stride;
cStride = GRALLOC_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 = GRALLOC_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;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
yStride = cStride = hnd->stride;
uOffset = NV12N_S8B_LUMA_SIZE(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);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_2PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base1);
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
yStride = cStride = hnd->stride;
uOffset = NV12N_S8B_LUMA_SIZE(yStride, hnd->vstride, ext_size) + NV12N_S2B_SIZE(hnd->width, hnd->vstride);
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);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_2PRIVATE_DATA)
&& GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA))
{
ycbcr->cr = (void *)((unsigned long)hnd->base1);
}
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->base1 + vOffset);
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_3PRIVATE_DATA)
&& (GRALLOC1_SLSI_USAGE_CHECK(usage, GRALLOC1_CONSUMER_USAGE_VIDEO_PRIVATE_DATA)))
{
ycbcr->cr = (void *)((unsigned long)hnd->base2);
}
break;
default:
AERR("getYCbCrInfo 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));
return 0;
}
int mali_gralloc_lock_flex_async(const mali_gralloc_module* m, buffer_handle_t buffer, uint64_t usage,
int l, int t, int w, int h,
struct android_flex_layout* flex_layout, int32_t fence_fd)
{
GRALLOC_UNUSED(m);
GRALLOC_UNUSED(l);
GRALLOC_UNUSED(t);
GRALLOC_UNUSED(w);
GRALLOC_UNUSED(h);
if (private_handle_t::validate(buffer) < 0)
{
AERR("Locking invalid buffer %p, returning error", buffer);
return -EINVAL;
}
if (NULL == flex_layout)
{
return -EINVAL;
}
if (fence_fd >= 0)
{
sync_wait(fence_fd, -1);
close(fence_fd);
}
private_handle_t* hnd = (private_handle_t*)buffer;
if (GRALLOC1_FLAGS_CHECK(hnd->flags, private_handle_t::PRIV_FLAGS_USES_ION))
hnd->writeOwner = usage & GRALLOC1_USAGE_SW_WRITE_MASK;
// Map if all CPU addresses are NULL
if (!hnd->base && !hnd->base1 && !hnd->base2)
gralloc_map(m, hnd);
android_ycbcr ycbcr;
// Get CPU addresses and stride
if(getYCbCrInfo(hnd, usage, &ycbcr))
return -EINVAL;
// Convert android_ycbcr to android_flex_layout
if (usage & (GRALLOC1_USAGE_SW_READ_MASK | GRALLOC1_USAGE_SW_WRITE_MASK) &&
!(hnd->internal_format & GRALLOC_ARM_INTFMT_EXT_MASK))
{
flex_layout->format = FLEX_FORMAT_YCbCr;
flex_layout->num_planes = 3;
for (uint32_t i = 0; i < flex_layout->num_planes; i++) {
flex_layout->planes[i].bits_per_component = 8;
flex_layout->planes[i].bits_used = 8;
flex_layout->planes[i].h_increment = 1;
flex_layout->planes[i].v_increment = 1;
flex_layout->planes[i].h_subsampling = 2;
flex_layout->planes[i].v_subsampling = 2;
}
flex_layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y);
flex_layout->planes[0].component = FLEX_COMPONENT_Y;
flex_layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride);
flex_layout->planes[1].top_left = static_cast<uint8_t *>(ycbcr.cb);
flex_layout->planes[1].component = FLEX_COMPONENT_Cb;
flex_layout->planes[1].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
flex_layout->planes[1].v_increment = static_cast<int32_t>(ycbcr.cstride);
flex_layout->planes[2].top_left = static_cast<uint8_t *>(ycbcr.cr);
flex_layout->planes[2].component = FLEX_COMPONENT_Cr;
flex_layout->planes[2].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
flex_layout->planes[2].v_increment = static_cast<int32_t>(ycbcr.cstride);
}
else if (is_sbwc_format(hnd->format))
{
flex_layout->format = FLEX_FORMAT_YCbCr;
flex_layout->num_planes = 3;
switch (hnd->format)
{
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
for (uint32_t i = 0; i < flex_layout->num_planes; i++) {
flex_layout->planes[i].bits_per_component = 8;
flex_layout->planes[i].bits_used = 8;
flex_layout->planes[i].h_increment = 1;
flex_layout->planes[i].v_increment = 1;
flex_layout->planes[i].h_subsampling = 2;
flex_layout->planes[i].v_subsampling = 2;
}
break;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
for (uint32_t i = 0; i < flex_layout->num_planes; i++) {
flex_layout->planes[i].bits_per_component = 10;
flex_layout->planes[i].bits_used = 10;
flex_layout->planes[i].h_increment = 1;
flex_layout->planes[i].v_increment = 1;
flex_layout->planes[i].h_subsampling = 2;
flex_layout->planes[i].v_subsampling = 2;
}
}
flex_layout->planes[0].top_left = static_cast<uint8_t *>(ycbcr.y);
flex_layout->planes[0].component = FLEX_COMPONENT_Y;
flex_layout->planes[0].v_increment = static_cast<int32_t>(ycbcr.ystride);
flex_layout->planes[1].top_left = static_cast<uint8_t *>(ycbcr.cb);
flex_layout->planes[1].component = FLEX_COMPONENT_Cb;
flex_layout->planes[1].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
flex_layout->planes[1].v_increment = static_cast<int32_t>(ycbcr.cstride);
flex_layout->planes[2].top_left = static_cast<uint8_t *>(ycbcr.cr);
flex_layout->planes[2].component = FLEX_COMPONENT_Cr;
flex_layout->planes[2].h_increment = static_cast<int32_t>(ycbcr.chroma_step);
flex_layout->planes[2].v_increment = static_cast<int32_t>(ycbcr.cstride);
}
else
{
AERR("Don't support to lock buffer %p: with format %" PRIx64, hnd, hnd->internal_format);
return -EINVAL;
}
return 0;
}
int mali_gralloc_unlock_async(const mali_gralloc_module* m, buffer_handle_t buffer, int32_t* fence_fd)
{
*fence_fd = -1;
if (mali_gralloc_unlock(m, buffer) < 0)
{
return -EINVAL;
}
return 0;
}