exynos5: libgscaler: GSC m2m non-blocking feature is added
authorYongbae Song <yb.song@samsung.com>
Fri, 29 Jun 2012 05:25:33 +0000 (14:25 +0900)
committerGreg Hackmann <ghackmann@google.com>
Tue, 31 Jul 2012 01:02:02 +0000 (18:02 -0700)
Added the GSC m2m non-blocking mode in libgscaler. By using this
feature,  other tasks (like glDraw) can be parallelized to GSC
processing.

libgscaler provids 3 APIs for GSC frame processing
1)exynos_gsc_config_exclusive  ==> GSC configuration
2)exynos_gsc_run_exclusive     ==> Queue the buffer and streamon the
                                   GSC.
3)exynos_gsc_stop_exclusive    ==> Deque the buffer (wait for frame
                                   done) & streamoff the GSC.

Change-Id: I86d2da0b9fb9284c2a2a135f1c36a50c876928a0
Signed-off-by: Yongbae Song <yb.song@samsung.com>
libgscaler/exynos_gscaler.c

index a015190b3894c56ae85f27e676457f8555409ecb..c100cb5c426f699f56d6ad262c6da68940fb55a0 100755 (executable)
@@ -1785,12 +1785,10 @@ SKIP_STREAMOFF:
     return 0;
 }
 
-int exynos_gsc_convert(
-    void *handle)
+static int exynos_gsc_m2m_run_core(void *handle)
 {
     struct GSC_HANDLE *gsc_handle;
-    int ret    = -1;
-    int i      = 0;
+
     gsc_handle = (struct GSC_HANDLE *)handle;
 
     Exynos_gsc_In();
@@ -1800,16 +1798,8 @@ int exynos_gsc_convert(
         return -1;
     }
 
-    char mutex_name[32];
     bool flag_new_gsc = false;
 
-    exynos_mutex_lock(gsc_handle->op_mutex);
-
-    if (gsc_handle->flag_local_path == true) {
-        ALOGE("%s::this exynos_gsc is connected by another hw internaly. So, don't call exynos_gsc_convert()", __func__);
-        goto done;
-    }
-
     if (gsc_handle->flag_exclusive_open == false) {
         if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == false) {
             if (m_exynos_gsc_find_and_trylock_and_create(gsc_handle) == false) {
@@ -1873,13 +1863,106 @@ int exynos_gsc_convert(
         gsc_handle->dst.stream_on = true;
     }
 
+    Exynos_gsc_Out();
+
+    return 0;
+
+done:
+    return -1;
+}
+
+static int exynos_gsc_m2m_wait_frame_done(void *handle)
+{
+    struct GSC_HANDLE *gsc_handle;
+    struct v4l2_requestbuffers req_buf;
+
+    gsc_handle = (struct GSC_HANDLE *)handle;
+
+    Exynos_gsc_In();
+
+    if (handle == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    if ((gsc_handle->src.stream_on == false) || (gsc_handle->dst.stream_on == false)) {
+        ALOGE("%s:: src_strean_on or dst_stream_on are false", __func__);
+        return -1;
+    }
+
     if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->src.buffer) < 0) {
         ALOGE("%s::exynos_v4l2_dqbuf(src) fail", __func__);
-        goto done;
+        return -1;
     }
 
     if (exynos_v4l2_dqbuf(gsc_handle->gsc_fd, &gsc_handle->dst.buffer) < 0) {
         ALOGE("%s::exynos_v4l2_dqbuf(dst) fail", __func__);
+        return -1;
+    }
+
+    if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->src.buf_type) < 0) {
+        ALOGE("%s::exynos_v4l2_streamoff(src) fail", __func__);
+        return -1;
+    }
+    gsc_handle->src.stream_on = false;
+
+    if (exynos_v4l2_streamoff(gsc_handle->gsc_fd, gsc_handle->dst.buf_type) < 0) {
+        ALOGE("%s::exynos_v4l2_streamoff(dst) fail", __func__);
+        return -1;
+    }
+    gsc_handle->dst.stream_on = false;
+
+    /* src: clear_buf */
+    req_buf.count  = 0;
+    req_buf.type   = gsc_handle->src.buf_type;
+    req_buf.memory = V4L2_MEMORY_DMABUF;
+    if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
+        ALOGE("%s::exynos_v4l2_reqbufs():src: fail", __func__);
+        return -1;
+    }
+
+    /* dst: clear_buf */
+    req_buf.count  = 0;
+    req_buf.type   = gsc_handle->dst.buf_type;
+    req_buf.memory = V4L2_MEMORY_DMABUF;
+    if (exynos_v4l2_reqbufs(gsc_handle->gsc_fd, &req_buf) < 0) {
+        ALOGE("%s::exynos_v4l2_reqbufs():dst: fail", __func__);
+        return -1;
+    }
+
+    Exynos_gsc_Out();
+
+     return 0;
+}
+
+int exynos_gsc_convert(
+    void *handle)
+{
+    struct GSC_HANDLE *gsc_handle;
+    int ret    = -1;
+    gsc_handle = (struct GSC_HANDLE *)handle;
+
+    Exynos_gsc_In();
+
+    if (handle == NULL) {
+        ALOGE("%s::handle == NULL() fail", __func__);
+        return -1;
+    }
+
+    exynos_mutex_lock(gsc_handle->op_mutex);
+
+    if (gsc_handle->flag_local_path == true) {
+        ALOGE("%s::this exynos_gsc is connected by another hw internaly. So, don't call exynos_gsc_convert()", __func__);
+            goto done;
+        }
+
+    if (exynos_gsc_m2m_run_core(handle) < 0) {
+        ALOGE("%s::exynos_gsc_run_core fail", __func__);
+            goto done;
+        }
+
+    if (exynos_gsc_m2m_wait_frame_done(handle) < 0) {
+        ALOGE("%s::exynos_gsc_m2m_wait_frame_done", __func__);
         goto done;
     }
 
@@ -1915,6 +1998,7 @@ int exynos_gsc_m2m_run(void *handle,
     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]);
+        return -1;
     }
 
     addr[0] = (void *)dst_img->yaddr;
@@ -1924,11 +2008,13 @@ int exynos_gsc_m2m_run(void *handle,
     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]);
+        return -1;
     }
 
-    ret = exynos_gsc_convert(handle);
+    ret = exynos_gsc_m2m_run_core(handle);
      if (ret < 0) {
-        ALOGE("%s::fail: exynos_gsc_convert", __func__);
+        ALOGE("%s::fail: exynos_gsc_m2m_run_core", __func__);
+        return -1;
     }
 
     Exynos_gsc_Out();
@@ -1977,6 +2063,9 @@ int exynos_gsc_run_exclusive(void *handle,
 {
     struct GSC_HANDLE *gsc_handle;
     int ret = 0;
+
+    Exynos_gsc_In();
+
     gsc_handle = (struct GSC_HANDLE *)handle;
     if (handle == NULL) {
         ALOGE("%s::handle == NULL() fail", __func__);
@@ -1997,6 +2086,9 @@ int exynos_gsc_run_exclusive(void *handle,
     default:
         break;
     }
+
+    Exynos_gsc_Out();
+
     return ret;
 }
 
@@ -2015,7 +2107,7 @@ int exynos_gsc_stop_exclusive(void *handle)
 
     switch (gsc_handle->gsc_mode) {
     case GSC_M2M_MODE:
-        // nothing to do
+        ret = exynos_gsc_m2m_wait_frame_done(handle);
         break;
     case GSC_OUTPUT_MODE:
         ret = exynos_gsc_out_stop(handle);