From 9f6d828714b4b232205235a1c75f24ec23f8b888 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Thu, 4 Oct 2012 13:25:29 -0700 Subject: [PATCH] libgscaler: Add support for sync fences gsc_m2m_run returns a release fence for both the src and dst images. The src releaseFenceFd can be returned to userspace as the releaseFenceFd of the layer and the dst releaseFenceFd can be used as the acquiredFenceFd for the next pipeline step. Bug: 7286984 Change-Id: I16bd2828f03fd3eed2c62b23e2325357b1e477e9 --- include/exynos_gscaler.h | 12 +++++-- libcsc/csc.c | 4 +-- libgscaler/exynos_gsc_utils.h | 3 ++ libgscaler/exynos_gscaler.c | 61 ++++++++++++++++++++++++++++------- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/include/exynos_gscaler.h b/include/exynos_gscaler.h index 50a4586..faf9ed7 100644 --- a/include/exynos_gscaler.h +++ b/include/exynos_gscaler.h @@ -263,12 +263,16 @@ int exynos_gsc_set_rotation( * \param addr * buffer pointer array[in] * + * \param acquireFenceFd + * acquire fence fd for the buffer or -1[in] + * * \return * error code */ int exynos_gsc_set_src_addr( void *handle, - void *addr[3]); + void *addr[3], + int acquireFenceFd); /*! * Set destination buffer @@ -279,12 +283,16 @@ int exynos_gsc_set_src_addr( * \param addr * buffer pointer array[in] * + * \param acquireFenceFd + * acquire fence fd for the buffer or -1[in] + * * \return * error code */ int exynos_gsc_set_dst_addr( void *handle, - void *addr[3]); + void *addr[3], + int acquireFenceFd); /*! * Convert color space with presetup color format diff --git a/libcsc/csc.c b/libcsc/csc.c index 255f462..ac01db1 100644 --- a/libcsc/csc.c +++ b/libcsc/csc.c @@ -439,8 +439,8 @@ static CSC_ERRORCODE csc_set_buffer( break; #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: - exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes); - exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes); + exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1); + exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1); break; #endif default: diff --git a/libgscaler/exynos_gsc_utils.h b/libgscaler/exynos_gsc_utils.h index dfe7925..ec30772 100644 --- a/libgscaler/exynos_gsc_utils.h +++ b/libgscaler/exynos_gsc_utils.h @@ -103,11 +103,14 @@ struct gsc_info { bool dirty; void *addr[NUM_OF_GSC_PLANES]; + int acquireFenceFd; + int releaseFenceFd; bool stream_on; enum v4l2_buf_type buf_type; struct v4l2_format format; struct v4l2_buffer buffer; + bool buffer_queued; struct v4l2_plane planes[NUM_OF_GSC_PLANES]; struct v4l2_crop crop; int src_buf_idx; diff --git a/libgscaler/exynos_gscaler.c b/libgscaler/exynos_gscaler.c index b731054..9c83fa7 100644 --- a/libgscaler/exynos_gscaler.c +++ b/libgscaler/exynos_gscaler.c @@ -42,6 +42,8 @@ //#define LOG_NDEBUG 0 #include "exynos_gsc_utils.h" +static int exynos_gsc_m2m_wait_frame_done(void *handle); + static unsigned int m_gsc_get_plane_count( int v4l_pixel_format) { @@ -703,10 +705,12 @@ static bool m_exynos_gsc_set_addr( info->v4l2_colorformat); info->buffer.index = 0; + info->buffer.flags = V4L2_BUF_FLAG_USE_SYNC; info->buffer.type = info->buf_type; info->buffer.memory = V4L2_MEMORY_DMABUF; info->buffer.m.planes = info->planes; info->buffer.length = info->format.fmt.pix_mp.num_planes; + info->buffer.reserved = info->acquireFenceFd; for (i = 0; i < info->format.fmt.pix_mp.num_planes; i++) { info->buffer.m.planes[i].m.fd = (int)info->addr[i]; @@ -718,6 +722,9 @@ static bool m_exynos_gsc_set_addr( ALOGE("%s::exynos_v4l2_qbuf() fail", __func__); return false; } + info->buffer_queued = true; + + info->releaseFenceFd = info->buffer.reserved; return true; } @@ -1169,7 +1176,8 @@ done: int exynos_gsc_set_src_addr( void *handle, - void *addr[3]) + void *addr[3], + int acquireFenceFd) { struct GSC_HANDLE *gsc_handle; gsc_handle = (struct GSC_HANDLE *)handle; @@ -1186,7 +1194,7 @@ int exynos_gsc_set_src_addr( gsc_handle->src.addr[0] = addr[0]; gsc_handle->src.addr[1] = addr[1]; gsc_handle->src.addr[2] = addr[2]; - + gsc_handle->src.acquireFenceFd = acquireFenceFd; exynos_mutex_unlock(gsc_handle->op_mutex); @@ -1197,7 +1205,8 @@ int exynos_gsc_set_src_addr( int exynos_gsc_set_dst_addr( void *handle, - void *addr[3]) + void *addr[3], + int acquireFenceFd) { struct GSC_HANDLE *gsc_handle; gsc_handle = (struct GSC_HANDLE *)handle; @@ -1215,6 +1224,7 @@ int exynos_gsc_set_dst_addr( gsc_handle->dst.addr[0] = addr[0]; gsc_handle->dst.addr[1] = addr[1]; gsc_handle->dst.addr[2] = addr[2]; + gsc_handle->dst.acquireFenceFd = acquireFenceFd; exynos_mutex_unlock(gsc_handle->op_mutex); @@ -1784,6 +1794,14 @@ static int exynos_gsc_m2m_run_core(void *handle) gsc_handle->dst.dirty = false; } + /* dequeue buffers from previous work if necessary */ + if (gsc_handle->src.stream_on == true) { + if (exynos_gsc_m2m_wait_frame_done(handle) < 0) { + ALOGE("%s::exynos_gsc_m2m_wait_frame_done fail", __func__); + goto done; + } + } + if (m_exynos_gsc_set_addr(gsc_handle->gsc_fd, &gsc_handle->src) == false) { ALOGE("%s::m_exynos_gsc_set_addr(src) fail", __func__); goto done; @@ -1836,14 +1854,20 @@ static int exynos_gsc_m2m_wait_frame_done(void *handle) return -1; } - if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->src.buffer) < 0) { - ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__); - return -1; + if (gsc_handle->src.buffer_queued) { + if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->src.buffer) < 0) { + ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__); + return -1; + } + gsc_handle->src.buffer_queued = false; } - if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->dst.buffer) < 0) { - ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__); - return -1; + if (gsc_handle->dst.buffer_queued) { + if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->dst.buffer) < 0) { + ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__); + return -1; + } + gsc_handle->dst.buffer_queued = false; } Exynos_gsc_Out(); @@ -1926,6 +1950,16 @@ int exynos_gsc_convert( goto done; } + if (gsc_handle->src.releaseFenceFd >= 0) { + close(gsc_handle->src.releaseFenceFd); + gsc_handle->src.releaseFenceFd = -1; + } + + if (gsc_handle->dst.releaseFenceFd >= 0) { + close(gsc_handle->dst.releaseFenceFd); + gsc_handle->dst.releaseFenceFd = -1; + } + if (exynos_gsc_m2m_stop(handle) < 0) { ALOGE("%s::exynos_gsc_m2m_stop", __func__); goto done; @@ -1950,6 +1984,7 @@ int exynos_gsc_m2m_run(void *handle, exynos_gsc_img *src_img, exynos_gsc_img *dst_img) { + struct GSC_HANDLE *gsc_handle = handle; void *addr[3] = {NULL, NULL, NULL}; int ret = 0; @@ -1958,8 +1993,7 @@ int exynos_gsc_m2m_run(void *handle, addr[0] = (void *)src_img->yaddr; addr[1] = (void *)src_img->uaddr; addr[2] = (void *)src_img->vaddr; - - ret = exynos_gsc_set_src_addr(handle, addr); + ret = exynos_gsc_set_src_addr(handle, addr, src_img->acquireFenceFd); if (ret < 0) { ALOGE("%s::fail: exynos_gsc_set_src_addr[%x %x %x]", __func__, (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]); @@ -1969,7 +2003,7 @@ int exynos_gsc_m2m_run(void *handle, addr[0] = (void *)dst_img->yaddr; addr[1] = (void *)dst_img->uaddr; addr[2] = (void *)dst_img->vaddr; - ret = exynos_gsc_set_dst_addr(handle, addr); + ret = exynos_gsc_set_dst_addr(handle, addr, dst_img->acquireFenceFd); if (ret < 0) { ALOGE("%s::fail: exynos_gsc_set_dst_addr[%x %x %x]", __func__, (unsigned int)addr[0], (unsigned int)addr[1], (unsigned int)addr[2]); @@ -1982,6 +2016,9 @@ int exynos_gsc_m2m_run(void *handle, return -1; } + src_img->releaseFenceFd = gsc_handle->src.releaseFenceFd; + dst_img->releaseFenceFd = gsc_handle->dst.releaseFenceFd; + Exynos_gsc_Out(); return 0; -- 2.20.1