e_hwc: support e_explicit_sync in hwc_windows 85/238085/2
authorChangyeon Lee <cyeon.lee@samsung.com>
Wed, 8 Jul 2020 08:12:23 +0000 (17:12 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Wed, 8 Jul 2020 08:48:52 +0000 (17:48 +0900)
Change-Id: If3e7e54375124a77735842a373c2592b0b0f8850

src/bin/e_hwc.c
src/bin/e_hwc.h
src/bin/e_hwc_window.c
src/bin/e_hwc_window.h
src/bin/e_hwc_windows.c
src/bin/e_hwc_windows.h

index 0598a0f6b6c33ccd9b136e7d76bc1d3378d6f57c..34c70433c9c579164d5cda1cfbd3df3dcca639a0 100644 (file)
@@ -356,6 +356,8 @@ e_hwc_new(E_Output *output, Eina_Bool primary_output)
    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
    hwc->output = output;
 
+   hwc->commit_fence_fd = -1;
+
    /*
     * E20 has two hwc policy options.
     * 1. One is the E_HWC_POLICY_PLANES.
@@ -398,6 +400,8 @@ e_hwc_new(E_Output *output, Eina_Bool primary_output)
           hwc->tdm_hwc_video_transform = EINA_TRUE;
         if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCANOUT)
           hwc->tdm_hwc_video_scanout = EINA_TRUE;
+        if (hwc_caps & TDM_HWC_CAPABILITY_FENCE)
+          hwc->tdm_hwc_fence = EINA_TRUE;
      }
 
    /* set the pirmary_output */
@@ -444,6 +448,9 @@ e_hwc_del(E_Hwc *hwc)
 
    _e_hwc_ee_deinit(hwc);
 
+   if (hwc->commit_fence_fd >= 0)
+     close(hwc->commit_fence_fd);
+
    E_FREE(hwc);
 }
 
index 1cac472e6a2392d5dd7f2d88ccb35b6aa4ec8224..6716cca31b0cf9e51f0ea80a387058555dafe322 100644 (file)
@@ -140,6 +140,9 @@ struct _E_Hwc
    int                  flapse;
 
    Eina_Bool            present_sync;
+
+   Eina_Bool            tdm_hwc_fence;
+   int                  commit_fence_fd;
 };
 
 E_API extern int E_EVENT_HWC_ACTIVE;
index 7c7f5ea19a75ceb2de92b0d236bb64780e432e20..3556b628c239d6613070fbf21110c170fe91e222 100644 (file)
@@ -1277,9 +1277,13 @@ e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window)
    tdm_error error = TDM_ERROR_NONE;
    E_Hwc_Window_Queue_Buffer *queue_buffer = NULL, *queue_buffer2 = NULL;
    E_Client *ec = NULL;
+   E_Hwc *hwc;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
 
+   hwc = hwc_window->hwc;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
    thwc_window = hwc_window->thwc_window;
    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
 
@@ -1364,6 +1368,12 @@ e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window)
    error = tdm_hwc_window_set_buffer(thwc_window, hwc_window->buffer.tsurface);
    EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
 
+   if ((ec) && (ec->explicit_sync_surface) && (e_hwc_windows_fence_enabled_get(hwc)))
+     {
+        error = tdm_hwc_window_set_acquire_fence(thwc_window, ec->explicit_sync_surface->acquire_fence_fd);
+        EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+     }
+
    return EINA_TRUE;
 }
 
index 31388395c6828fb4f1b122479f4bb87f5fd09265..527762fb9e9673777ea6363b96b898cb6dd37fd6 100644 (file)
@@ -164,7 +164,9 @@ struct _E_Hwc_Window_Target
    Eina_Bool           is_rendering;
    int                 max_transition_failures;
 
-   Eina_Bool skip_surface_set;
+   Eina_Bool           skip_surface_set;
+
+   E_Egl_Sync         *end_render_sync;
 };
 
 struct _E_Hwc_Window_Commit_Data {
index bb955b142b5e31ec1613da08f6b549f6582164b7..c3588412ee1d586867dbcc52164f4117bf1094fa 100644 (file)
@@ -71,6 +71,7 @@ struct _E_Hwc_Windows_Buffer_Comp_Info
 {
    E_Presentation_Time_Container presentation_container;
    Eina_Bool skip;
+   E_Egl_Sync *release_fence;
 };
 
 static Eina_Bool ehws_trace = EINA_FALSE;
@@ -583,6 +584,16 @@ _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc, Eina_Bool tdm_set)
         if (tdm_set)
           tdm_hwc_set_client_target_buffer(thwc, hwc_window->buffer.tsurface, fb_damage);
 
+        if ((target_hwc_window->end_render_sync) && (e_hwc_windows_fence_enabled_get(hwc)))
+          {
+             int fence = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
+             if (fence >= 0)
+               {
+                  tdm_hwc_set_client_target_acquire_fence(thwc, fence);
+                  close(fence);
+               }
+          }
+
         if (ehws_trace)
           {
              rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(hwc_window->buffer.tsurface);
@@ -636,6 +647,9 @@ _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc, Eina_Bool tdm_set)
         CLEAR(fb_damage);
 
         tdm_hwc_set_client_target_buffer(thwc, NULL, fb_damage);
+
+        if (e_hwc_windows_fence_enabled_get(hwc))
+          tdm_hwc_set_client_target_acquire_fence(thwc, -1);
      }
 
    return EINA_TRUE;
@@ -1061,6 +1075,47 @@ _e_hwc_windows_target_window_queue_set(E_Hwc_Window_Target *target_hwc_window)
    return EINA_TRUE;
 }
 
+static void
+_e_hwc_windows_target_window_render_flush_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+   E_Hwc_Window *hwc_window;
+   E_Hwc_Windows_Buffer_Comp_Info *buffer_comp_info;
+   E_Hwc *hwc;
+   Eina_List *l;
+
+   hwc = target_hwc_window->hwc;
+   if (!e_hwc_windows_fence_enabled_get(hwc)) return;
+
+   if (target_hwc_window->dequeued_tsurface)
+     {
+        buffer_comp_info = _e_hwc_windows_buffer_comp_info_get(target_hwc_window->dequeued_tsurface);
+        if (buffer_comp_info && buffer_comp_info->release_fence)
+          e_egl_sync_wait(buffer_comp_info->release_fence);
+     }
+
+   if (target_hwc_window->end_render_sync)
+     {
+        e_egl_sync_destroy(target_hwc_window->end_render_sync);
+        target_hwc_window->end_render_sync = NULL;
+     }
+
+   target_hwc_window->end_render_sync = e_egl_sync_fence_create();
+   if (!target_hwc_window->end_render_sync)
+     EHWSERR("Failed to create E_Egl_Sync", hwc);
+
+   EINA_LIST_FOREACH(hwc->visible_windows, l, hwc_window)
+     {
+        if (!hwc_window->is_deleted) continue;
+        if (!hwc_window->ec) continue;
+        if (!hwc_window->ec->explicit_sync_surface) continue;
+        if (e_hwc_window_accepted_state_get(hwc_window) != E_HWC_WINDOW_STATE_CLIENT)
+          continue;
+
+        e_explicit_sync_surface_sync(hwc_window->ec->explicit_sync_surface);
+     }
+}
+
 static void
 _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
 {
@@ -1073,6 +1128,7 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE
    Eina_List *rendered_windows = NULL;
    Eina_List *visible_windows = NULL;
    Eina_List *l;
+   Eina_Bool fence_enabled;
 
    EHWSTRACE("{%s} gets render_flush_post noti.", NULL, target_hwc_window->hwc, "@TARGET WINDOW@");
 
@@ -1106,6 +1162,8 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE
    if (!buffer_comp_info)
      EHWSERR("fail to get buffer_comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface);
 
+   fence_enabled = e_hwc_windows_fence_enabled_get(target_hwc_window->hwc);
+
    /* all ecs have been composited so we can attach a list of composited e_hwc_windows to the surface
     * which contains their ecs composited */
    rendered_windows = eina_list_clone(target_hwc_window->rendered_windows);
@@ -1135,6 +1193,22 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE
          */
         if (!buffer->resource) continue;
 
+        if ((fence_enabled) && (buffer->buffer_release) && (target_hwc_window->end_render_sync))
+          {
+             int fence_fd = -1;
+
+             fence_fd = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
+             if (fence_fd != -1)
+               {
+                  if (!e_explicit_sync_buffer_release_fence_fd_set(buffer->buffer_release, fence_fd))
+                    close(fence_fd);
+
+                  continue;
+               }
+             else
+               EHWSERR("failed to dup native fence fd", target_hwc_window->hwc);
+          }
+
         buffer_ref = E_NEW(E_Comp_Wl_Buffer_Ref, 1);
         if (!buffer_ref) continue;
 
@@ -1164,6 +1238,10 @@ _e_hwc_windows_target_window_free(E_Hwc_Window_Target *target_hwc_window)
                            EVAS_CALLBACK_RENDER_FLUSH_POST,
                            _e_hwc_windows_target_window_render_flush_post_cb);
 
+   evas_event_callback_del(target_hwc_window->evas,
+                           EVAS_CALLBACK_RENDER_FLUSH_PRE,
+                           _e_hwc_windows_target_window_render_flush_pre_cb);
+
    ecore_main_fd_handler_del(target_hwc_window->event_hdlr);
    close(target_hwc_window->event_fd);
 
@@ -1227,6 +1305,11 @@ _e_hwc_windows_target_window_new(E_Hwc *hwc)
                            _e_hwc_windows_target_window_render_flush_post_cb,
                            target_hwc_window);
 
+   evas_event_callback_add(evas,
+                           EVAS_CALLBACK_RENDER_FLUSH_PRE,
+                           _e_hwc_windows_target_window_render_flush_pre_cb,
+                           target_hwc_window);
+
    return target_hwc_window;
 
 fail:
@@ -3285,11 +3368,89 @@ e_hwc_windows_render(E_Hwc *hwc)
    return EINA_TRUE;
 }
 
+static void
+_e_hwc_windows_release_fence_fd_update(E_Hwc *hwc)
+{
+   E_Hwc_Window *hwc_window;
+   E_Hwc_Window_Target *target_hwc_window;
+   E_Hwc_Window_Queue_Buffer *queue_buffer;
+   E_Hwc_Windows_Buffer_Comp_Info *comp_info;
+   tdm_hwc_window **thwc_wins = NULL;
+   int *release_fences = NULL;
+   uint32_t num_thwc_wins = 0;
+   tdm_error ret = TDM_ERROR_NONE;
+   int i;
+
+   target_hwc_window = hwc->target_hwc_window;
+   EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+
+   hwc_window = (E_Hwc_Window *)target_hwc_window;
+   if ((hwc_window->display.buffer.tsurface) && (hwc_window->display.buffer.queue))
+     {
+        comp_info = _e_hwc_windows_buffer_comp_info_get(hwc_window->display.buffer.tsurface);
+        EINA_SAFETY_ON_NULL_RETURN(comp_info);
+
+        if (comp_info->release_fence)
+          e_egl_sync_destroy(comp_info->release_fence);
+
+        comp_info->release_fence = e_egl_sync_fence_create_with_fd(hwc->commit_fence_fd);
+
+        queue_buffer = e_hwc_window_queue_buffer_find(hwc_window->display.buffer.queue,
+                                                      hwc_window->display.buffer.tsurface);
+        if (queue_buffer)
+          e_hwc_window_queue_buffer_release(hwc_window->display.buffer.queue, queue_buffer);
+
+        /* prevent release buffer to queue in commit handler */
+        hwc_window->display.buffer.queue = NULL;
+     }
+
+   ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, NULL, NULL);
+   EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
+
+   if (!num_thwc_wins) return;
+
+   thwc_wins = E_NEW(tdm_hwc_window *, num_thwc_wins);
+   EINA_SAFETY_ON_NULL_GOTO(thwc_wins, clean);
+
+   release_fences = E_NEW(int, num_thwc_wins);
+   EINA_SAFETY_ON_NULL_GOTO(release_fences, clean);
+
+   ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, thwc_wins, release_fences);
+   EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
+
+   for (i = 0; i < num_thwc_wins; i++)
+     {
+        hwc_window = _e_hwc_windows_window_find_by_twin(hwc, thwc_wins[i]);
+
+        if ((!hwc_window) ||
+            (!hwc_window->display.buffer_ref.buffer) ||
+            (!hwc_window->display.buffer_ref.buffer->buffer_release))
+          {
+             close(release_fences[i]);
+             continue;
+          }
+
+        if (!e_explicit_sync_buffer_release_fence_fd_set(hwc_window->display.buffer_ref.buffer->buffer_release,
+                                                         release_fences[i]))
+          {
+             close(release_fences[i]);
+             continue;
+          }
+
+        e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
+     }
+
+clean:
+  if (thwc_wins) free(thwc_wins);
+  if (release_fences) free(release_fences);
+}
+
 EINTERN Eina_Bool
 e_hwc_windows_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
 {
    E_Output *output = NULL;
    tdm_error error = TDM_ERROR_NONE;
+   int commit_fence_fd = -1;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
 
@@ -3376,8 +3537,24 @@ e_hwc_windows_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
              goto fail;
           }
 
-          /* send tizen_hwc_commit feedback committed */
-          e_comp_wl_tizen_hwc_committed();
+        if (e_hwc_windows_fence_enabled_get(hwc))
+          {
+             error = tdm_hwc_get_commit_fence(hwc->thwc, &commit_fence_fd);
+             if (error == TDM_ERROR_NONE)
+               {
+                  if (hwc->commit_fence_fd >= 0)
+                    close(hwc->commit_fence_fd);
+
+                  hwc->commit_fence_fd = commit_fence_fd;
+
+                  _e_hwc_windows_release_fence_fd_update(hwc);
+               }
+             else
+               EHWSERR("tdm_hwc_get_commit_sync_fence_fd failed.", hwc);
+          }
+
+        /* send tizen_hwc_commit feedback committed */
+        e_comp_wl_tizen_hwc_committed();
      }
 
    return EINA_TRUE;
@@ -4017,3 +4194,15 @@ e_hwc_windows_client_type_override(E_Hwc *hwc)
         e_hwc_window_client_type_override(hwc_window);
      }
 }
+
+EINTERN Eina_Bool
+e_hwc_windows_fence_enabled_get(E_Hwc *hwc)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
+   if (!hwc->tdm_hwc_fence) return EINA_FALSE;
+   if (!e_egl_sync_enabled_get()) return EINA_FALSE;
+   if (!e_explicit_sync_enabled_get()) return EINA_FALSE;
+
+   return EINA_TRUE;
+}
index d54151f6d1118b95bd3b86ec834e19cfe4c92f6b..1de1f285f72324f1f5786bf4df197929b1bd39ef 100644 (file)
@@ -46,5 +46,7 @@ EINTERN Eina_Bool            e_hwc_windows_present_sync(E_Hwc *hwc);
 
 EINTERN void                 e_hwc_windows_client_type_override(E_Hwc *hwc);
 
+EINTERN Eina_Bool            e_hwc_windows_fence_enabled_get(E_Hwc *hwc);
+
 #endif
 #endif