e_hwc_window_client_type_override(ec->hwc_window);
}
+static void
+_e_hwc_window_client_subsurface_present_sync(E_Client *ec)
+{
+ E_Hwc_Window_State state;
+ Eina_List *l;
+ E_Client *subc;
+
+ if (!ec->hwc_window) return;
+
+ state = e_hwc_window_accepted_state_get(ec->hwc_window);
+ if ((state == E_HWC_WINDOW_STATE_DEVICE) || (state == E_HWC_WINDOW_STATE_VIDEO))
+ e_hwc_window_present_sync(ec->hwc_window);
+
+ EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
+ {
+ if (!subc->hwc_window) continue;
+ _e_hwc_window_client_subsurface_present_sync(subc);
+ }
+
+ EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
+ {
+ if (!subc->hwc_window) continue;
+ _e_hwc_window_client_subsurface_present_sync(subc);
+ }
+}
+
+static void
+_e_hwc_window_client_cb_transform_change(void *data EINA_UNUSED, E_Client *ec)
+{
+ E_Output *output;
+ E_Zone *zone;
+ E_Client *topmost;
+ Eina_List *l;
+ E_Client *subc;
+ E_Hwc_Window_State state;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ zone = ec->zone;
+ EINA_SAFETY_ON_NULL_RETURN(zone);
+ EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
+
+ output = e_output_find(zone->output_id);
+ EINA_SAFETY_ON_NULL_RETURN(output);
+
+ /* If an e_client belongs to the e_output managed by hwc_plane policy,
+ * there's no need to deal with hwc_windows. */
+ if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES) return;
+ if (!ec->hwc_window) return;
+
+ if (!e_comp_wl_video_subsurface_has(ec) && !e_comp_wl_normal_subsurface_has(ec))
+ return;
+
+ topmost = e_comp_wl_topmost_parent_get(ec);
+ if (topmost != ec) return;
+
+ /* if window is device state, sync is not needed */
+ state = e_hwc_window_accepted_state_get(ec->hwc_window);
+ if (state != E_HWC_WINDOW_STATE_CLIENT) return;
+
+ EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
+ {
+ if (!subc->hwc_window) continue;
+ _e_hwc_window_client_subsurface_present_sync(subc);
+ }
+
+ EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
+ {
+ if (!subc->hwc_window) continue;
+ _e_hwc_window_client_subsurface_present_sync(subc);
+ }
+}
+
static Eina_Bool
_e_hwc_window_client_cb_zone_set(void *data, int type, void *event)
{
{
E_LIST_HOOK_APPEND(hwc_window_client_hooks, E_CLIENT_HOOK_DEL,
_e_hwc_window_client_cb_del, NULL);
+ E_LIST_HOOK_APPEND(hwc_window_client_hooks, E_CLIENT_HOOK_TRANSFORM_CHANGE,
+ _e_hwc_window_client_cb_transform_change, NULL);
E_LIST_HANDLER_APPEND(hwc_window_event_hdlrs, E_EVENT_CLIENT_ZONE_SET,
_e_hwc_window_client_cb_zone_set, NULL);
if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+ if ((hwc_window->present_sync) || (eina_list_count(hwc_window->pending_update_list)))
+ return EINA_FALSE;
+
if (e_hwc_window_is_cursor(hwc_window))
{
if (!_e_hwc_window_cursor_info_get(hwc_window, &hwc_win_info))
return EINA_TRUE;
}
+ if ((hwc_window->present_sync) || (eina_list_count(hwc_window->pending_update_list)))
+ return EINA_FALSE;
+
ec = hwc_window->ec;
if ((hwc_window->is_deleted) || (!ec) || e_object_is_del(E_OBJECT(ec)))
update->info.dst_pos.x, update->info.dst_pos.y,
update->info.transform);
+ hwc_window->pending_update_list = eina_list_append(hwc_window->pending_update_list, update);
+
return update;
}
return EINA_FALSE;
}
+EINTERN Eina_Bool
+e_hwc_window_present_sync(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Window_Target *target_hwc_window;
+ E_Hwc_Window_State state;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
+
+ target_hwc_window = hwc_window->hwc->target_hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ if (e_hwc_window_is_cursor(hwc_window))
+ {
+ EHWERR("cursor doesn't support present sync", hwc_window->ec, hwc_window->hwc, hwc_window);
+ return EINA_FALSE;
+ }
+
+ /* if gl compositor is disabled, present sync isn't needed */
+ state = e_hwc_window_accepted_state_get((E_Hwc_Window *)target_hwc_window);
+ if (state == E_HWC_WINDOW_STATE_NONE)
+ return EINA_TRUE;
+
+ if (hwc_window->present_sync) return EINA_TRUE;
+
+ hwc_window->present_sync = EINA_TRUE;
+
+ if (!eina_list_data_find(target_hwc_window->present_sync_windows, hwc_window))
+ {
+ target_hwc_window->present_sync_windows = eina_list_append(target_hwc_window->present_sync_windows,
+ hwc_window);
+ e_hwc_window_ref(hwc_window);
+ }
+
+ return EINA_TRUE;
+}
+
EINTERN E_Hwc_Window_Hook *
e_hwc_window_hook_add(E_Hwc_Window_Hook_Point hookpoint, E_Hwc_Window_Hook_Cb func, const void *data)
{
E_Presentation_Time_Container presentation_container;
Eina_Bool skip;
E_Egl_Sync *release_fence;
+ Eina_List *pending_update_list;
};
static Eina_Bool ehws_trace = EINA_FALSE;
}
}
+static Eina_Bool
+_e_hwc_windows_pending_update_data_enqueue(E_Hwc_Windows_Buffer_Comp_Info *buffer_comp_info)
+{
+ E_Hwc_Window_Update_Data *update;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(buffer_comp_info, EINA_FALSE);
+
+ EINA_LIST_FREE(buffer_comp_info->pending_update_list, update)
+ e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
+
+ buffer_comp_info->pending_update_list = NULL;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_hwc_windows_pending_update_data_dequeue(E_Hwc_Window_Target *target_hwc_window,
+ E_Hwc_Windows_Buffer_Comp_Info *buffer_comp_info)
+{
+ Eina_List *pending_update_list = NULL;
+ E_Hwc_Window_Update_Data *update;
+ E_Hwc_Window *hwc_window;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(buffer_comp_info, EINA_FALSE);
+
+ EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
+ {
+ hwc_window->present_sync = EINA_FALSE;
+
+ update = e_hwc_window_pending_update_data_dequeue(hwc_window);
+ if (update)
+ {
+ pending_update_list = eina_list_append(pending_update_list, update);
+ if (e_hwc_window_is_video(hwc_window))
+ e_client_video_commit_data_release(hwc_window->ec, 0, 0, 0);
+ }
+
+ e_object_unref(E_OBJECT(hwc_window));
+ }
+
+ EINA_LIST_FREE(buffer_comp_info->pending_update_list, update)
+ e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
+
+ buffer_comp_info->pending_update_list = pending_update_list;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_hwc_windows_pending_update_data_clear(E_Hwc_Window_Target *target_hwc_window)
+{
+ E_Hwc_Window *hwc_window;
+ E_Hwc_Window_Update_Data *update;
+ tbm_surface_h tsurface;
+ E_Hwc_Windows_Buffer_Comp_Info *buffer_comp_info;
+ Eina_List *l, *ll;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
+ {
+ hwc_window->present_sync = EINA_FALSE;
+ e_object_unref(E_OBJECT(hwc_window));
+ }
+
+ EINA_LIST_FOREACH_SAFE(target_hwc_window->rendering_tsurfaces, l, ll, tsurface)
+ {
+ buffer_comp_info = _e_hwc_windows_buffer_comp_info_get(tsurface);
+ if (!buffer_comp_info) continue;
+
+ EINA_LIST_FREE(buffer_comp_info->pending_update_list, update)
+ e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update);
+ }
+
+ return EINA_TRUE;
+}
+
/* gets called as somebody modifies target_window's queue */
static void
_e_hwc_windows_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_queue,
target_hwc_window->rendering_tsurfaces =
eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface);
+
+ buffer_comp_info = _e_hwc_windows_buffer_comp_info_get(tsurface);
+ if (buffer_comp_info)
+ _e_hwc_windows_pending_update_data_enqueue(buffer_comp_info);
}
/* tsurface has been released at the queue */
{
EHWSINF("flush_post_cb is called but tsurface isn't dequeued", NULL, target_hwc_window->hwc);
+ _e_hwc_windows_pending_update_data_clear(target_hwc_window);
+
if (eina_list_count(target_hwc_window->rendered_windows))
{
EINA_LIST_FREE(target_hwc_window->rendered_windows, hwc_window)
}
buffer_comp_info = _e_hwc_windows_buffer_comp_info_get(target_hwc_window->dequeued_tsurface);
- if (!buffer_comp_info)
+ if (buffer_comp_info)
+ _e_hwc_windows_pending_update_data_dequeue(target_hwc_window, buffer_comp_info);
+ else
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);
E_Hwc_Window *hwc_window = NULL;
Eina_Bool update_changes = EINA_FALSE;
const Eina_List *l;
- Eina_Bool ret = EINA_FALSE;
if (hwc->property_changed)
{
if (_e_hwc_windows_device_state_available_update(hwc))
update_changes = EINA_TRUE;
- /* fetch the target buffer (try acquire) */
- if (_e_hwc_windows_target_buffer_fetch(hwc))
- update_changes = EINA_TRUE;
-
EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
{
if (e_hwc_window_is_target(hwc_window)) continue;
if (e_hwc_window_is_external(hwc_window)) continue;
/* fetch the window buffer */
- ret = e_hwc_window_buffer_fetch(hwc_window);
- if (ret)
+ if (e_hwc_window_buffer_fetch(hwc_window))
update_changes = EINA_TRUE;
else
{
/* sometimes client add frame cb without buffer attach */
if ((hwc_window->ec) &&
+ (hwc_window->ec->pixmap) &&
+ (e_pixmap_type_get(hwc_window->ec->pixmap) == E_PIXMAP_TYPE_WL) &&
(hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE))
- {
- if ((hwc_window->ec->pixmap) &&
- (e_pixmap_type_get(hwc_window->ec->pixmap) == E_PIXMAP_TYPE_WL))
- e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
- }
+ e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
}
/* update the window's info */
update_changes = EINA_TRUE;
}
+ /* fetch the target buffer (try acquire) */
+ if (_e_hwc_windows_target_buffer_fetch(hwc))
+ update_changes = EINA_TRUE;
+
if (hwc->pp_set)
_e_hwc_windows_pp_hwc_window_update(hwc);
{
E_Hwc_Window *target_window = (E_Hwc_Window *)target_hwc_window;
+ if ((state == E_HWC_WINDOW_STATE_NONE) && (e_hwc_window_state_get(target_window) != state))
+ _e_hwc_windows_pending_update_data_clear(target_hwc_window);
+
e_hwc_window_state_set(target_window, state, EINA_FALSE);
e_hwc_window_accepted_state_set(target_window, state);
}