From: Changyeon Lee Date: Wed, 8 Jul 2020 08:12:23 +0000 (+0900) Subject: e_hwc: support e_explicit_sync in hwc_windows X-Git-Tag: submit/tizen/20200709.054137~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3b7f9b51137d09feb97cfc5ab0273dcb584eab26;p=platform%2Fupstream%2Fenlightenment.git e_hwc: support e_explicit_sync in hwc_windows Change-Id: If3e7e54375124a77735842a373c2592b0b0f8850 --- diff --git a/src/bin/e_hwc.c b/src/bin/e_hwc.c index 0598a0f6b6..34c70433c9 100644 --- a/src/bin/e_hwc.c +++ b/src/bin/e_hwc.c @@ -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); } diff --git a/src/bin/e_hwc.h b/src/bin/e_hwc.h index 1cac472e6a..6716cca31b 100644 --- a/src/bin/e_hwc.h +++ b/src/bin/e_hwc.h @@ -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; diff --git a/src/bin/e_hwc_window.c b/src/bin/e_hwc_window.c index 7c7f5ea19a..3556b628c2 100644 --- a/src/bin/e_hwc_window.c +++ b/src/bin/e_hwc_window.c @@ -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; } diff --git a/src/bin/e_hwc_window.h b/src/bin/e_hwc_window.h index 31388395c6..527762fb9e 100644 --- a/src/bin/e_hwc_window.h +++ b/src/bin/e_hwc_window.h @@ -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 { diff --git a/src/bin/e_hwc_windows.c b/src/bin/e_hwc_windows.c index bb955b142b..c3588412ee 100644 --- a/src/bin/e_hwc_windows.c +++ b/src/bin/e_hwc_windows.c @@ -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; +} diff --git a/src/bin/e_hwc_windows.h b/src/bin/e_hwc_windows.h index d54151f6d1..1de1f285f7 100644 --- a/src/bin/e_hwc_windows.h +++ b/src/bin/e_hwc_windows.h @@ -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