return EINA_TRUE;
}
+
+E_API E_Hwc_Presentation_Callback *
+e_client_hwc_presentation_callback_add(E_Client *ec, E_Hwc_Presentation_Done_Cb cb, void *data)
+{
+ E_Hwc_Presentation_Callback *callback;
+ E_Hwc *hwc;
+ E_Output *output;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec->hwc_window, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec->zone, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
+
+ output = e_output_find(ec->zone->output_id);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+ hwc = output->hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc->hwc_policy == E_HWC_POLICY_WINDOWS, NULL);
+
+ callback = E_NEW(E_Hwc_Presentation_Callback, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(callback, NULL);
+
+ callback->hwc = hwc;
+ callback->cb = cb;
+ callback->data = data;
+
+ if (!e_hwc_window_presentation_callback_pending_set(ec->hwc_window, callback))
+ {
+ ERR("fail to e_hwc_window_presentation_callback_set");
+ free(callback);
+ return NULL;
+ }
+
+ EHINF("Add Presentation Callback:%p ec:%p hwc_window:%p",
+ hwc,
+ callback,
+ ec,
+ ec->hwc_window);
+
+ return callback;
+}
+
+E_API void
+e_hwc_presentation_callback_del(E_Hwc_Presentation_Callback *callback)
+{
+ EINA_SAFETY_ON_NULL_RETURN(callback);
+
+ EHINF("Del Presentation Callback:%p", callback->hwc, callback);
+
+ if (callback->list)
+ callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
+
+ free(callback);
+}
+
+EINTERN void
+e_hwc_presentation_callback_list_init(E_Hwc_Presentation_Callback_List *list)
+{
+ EINA_SAFETY_ON_NULL_RETURN(list);
+}
+
+EINTERN void
+e_hwc_presentation_callback_list_finish(E_Hwc_Presentation_Callback_List *list)
+{
+ E_Hwc_Presentation_Callback *callback = NULL;
+ Eina_List *l, *ll;
+
+ if (!list) return;
+
+ /* remove list in resource_destroy callback */
+ EINA_LIST_FOREACH_SAFE(list->callbacks, l, ll, callback)
+ {
+ callback->list = NULL;
+ list->callbacks = eina_list_remove_list(list->callbacks, l);
+ e_hwc_presentation_callback_call(callback);
+ }
+}
+
+EINTERN Eina_Bool
+e_hwc_presentation_callback_list_set(E_Hwc_Presentation_Callback_List *list,
+ E_Hwc_Presentation_Callback *callback)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
+
+ if (callback->list)
+ callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
+
+ if (!eina_list_data_find(list->callbacks, callback))
+ list->callbacks = eina_list_prepend(list->callbacks, callback);
+
+ callback->list = list;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_presentation_callback_list_unset(E_Hwc_Presentation_Callback_List *list,
+ E_Hwc_Presentation_Callback *callback)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
+
+ if (callback->list)
+ callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
+
+ callback->list = NULL;
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_hwc_presentation_callback_list_merge(E_Hwc_Presentation_Callback_List *inout,
+ E_Hwc_Presentation_Callback_List *input)
+{
+ E_Hwc_Presentation_Callback *callback = NULL;
+ Eina_List *l, *ll;
+
+ EINA_SAFETY_ON_NULL_RETURN(inout);
+ EINA_SAFETY_ON_NULL_RETURN(input);
+
+ /* remove list in feedback_set */
+ EINA_LIST_FOREACH_SAFE(input->callbacks, l, ll, callback)
+ e_hwc_presentation_callback_list_set(inout, callback);
+}
+
+EINTERN Eina_Bool
+e_hwc_presentation_callback_call(E_Hwc_Presentation_Callback *callback)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
+
+ if (callback->done) return EINA_TRUE;
+
+ callback->done = EINA_TRUE;
+
+ if (!callback->cb) return EINA_TRUE;
+
+ EHINF("Call Presentation Callback:%p", callback->hwc, callback);
+
+ /* it is possible callback is freed in callback */
+ callback->cb(callback->data, callback);
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_hwc_presentation_callback_list_call(E_Hwc_Presentation_Callback_List *list)
+{
+ E_Hwc_Presentation_Callback *callback = NULL;
+ Eina_List *l, *ll;
+
+ EINA_SAFETY_ON_NULL_RETURN(list);
+
+ /* remove list in resource_destroy callback */
+ EINA_LIST_FOREACH_SAFE(list->callbacks, l, ll, callback)
+ e_hwc_presentation_callback_call(callback);
+}
typedef struct _E_Hwc E_Hwc;
typedef struct _E_Hwc_Sync_Callback E_Hwc_Sync_Callback;
+typedef struct _E_Hwc_Presentation_Callback E_Hwc_Presentation_Callback;
+typedef struct _E_Hwc_Presentation_Callback_List E_Hwc_Presentation_Callback_List;
#define HWC_NAME_LEN 64
typedef struct _E_Hwc_Hook E_Hwc_Hook;
typedef void (*E_Hwc_Sync_Done_Cb)(void *data, E_Hwc *hwc);
+typedef void (*E_Hwc_Presentation_Done_Cb)(void *data, E_Hwc_Presentation_Callback *callback);
+
+struct _E_Hwc_Presentation_Callback_List
+{
+ Eina_List *callbacks;
+};
#else
#ifndef E_HWC_H
Eina_Bool done;
};
+struct _E_Hwc_Presentation_Callback
+{
+ E_Hwc *hwc;
+ void *data;
+ E_Hwc_Presentation_Done_Cb cb;
+
+ Eina_Bool done;
+ E_Hwc_Presentation_Callback_List *list;
+};
+
struct _E_Hwc
{
E_Output *output;
E_API E_Hwc_Sync_Callback *e_hwc_sync_callback_add(E_Hwc *hwc, E_Hwc_Sync_Done_Cb cb, void *data);
E_API void e_hwc_sync_callback_del(E_Hwc_Sync_Callback *sync_callback);
+/* Once callback of E_Hwc_Presentation_Callback is called, E_Hwc_Presentation_Callback should be destroyed */
+E_API E_Hwc_Presentation_Callback *e_client_hwc_presentation_callback_add(E_Client *ec, E_Hwc_Presentation_Done_Cb cb, void *data);
+E_API void e_hwc_presentation_callback_del(E_Hwc_Presentation_Callback *callback);
+
+EINTERN Eina_Bool e_hwc_presentation_callback_call(E_Hwc_Presentation_Callback *callback);
+
+EINTERN void e_hwc_presentation_callback_list_init(E_Hwc_Presentation_Callback_List *list);
+EINTERN void e_hwc_presentation_callback_list_finish(E_Hwc_Presentation_Callback_List *list);
+EINTERN Eina_Bool e_hwc_presentation_callback_list_set(E_Hwc_Presentation_Callback_List *list, E_Hwc_Presentation_Callback *callback);
+EINTERN Eina_Bool e_hwc_presentation_callback_list_unset(E_Hwc_Presentation_Callback_List *list, E_Hwc_Presentation_Callback *callback);
+EINTERN void e_hwc_presentation_callback_list_merge(E_Hwc_Presentation_Callback_List *inout, E_Hwc_Presentation_Callback_List *input);
+EINTERN void e_hwc_presentation_callback_list_call(E_Hwc_Presentation_Callback_List *list);
+
#endif
#endif
hwc->hwc_windows = eina_list_remove(hwc->hwc_windows, hwc_window);
e_presentation_time_container_finish(&hwc_window->presentation_container);
+ e_hwc_presentation_callback_list_finish(&hwc_window->pending_presentation_callbacks);
+ e_hwc_presentation_callback_list_finish(&hwc_window->presentation_callbacks);
output = hwc->output;
EINA_SAFETY_ON_NULL_GOTO(hwc->output, done);
hwc->hwc_windows = eina_list_append(hwc->hwc_windows, hwc_window);
e_presentation_time_container_init(&hwc_window->presentation_container);
+ e_hwc_presentation_callback_list_init(&hwc_window->pending_presentation_callbacks);
+ e_hwc_presentation_callback_list_init(&hwc_window->presentation_callbacks);
EHWINF("is created on eout:%p, zone_id:%d video:%d cursor:%d",
hwc_window->ec, hwc_window->hwc, hwc_window, hwc->output, ec->zone->id,
e_object_unref(E_OBJECT(hwc_window));
}
+
+EINTERN Eina_Bool
+e_hwc_window_presentation_callback_pending_set(E_Hwc_Window *hwc_window, E_Hwc_Presentation_Callback *callback)
+{
+ 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);
+
+ if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) &&
+ (!hwc_window->ec || !evas_object_visible_get(hwc_window->ec->frame)))
+ {
+ EHWERR("hwc_window is invisible on display", hwc_window->ec, hwc_window->hwc, hwc_window);
+ return EINA_FALSE;
+ }
+
+ if (!e_hwc_presentation_callback_list_set(&hwc_window->pending_presentation_callbacks, callback))
+ {
+ EHWERR("fail to e_hwc_presentation_callback_list_set", hwc_window->ec, hwc_window->hwc, hwc_window);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_presentation_callback_take(E_Hwc_Window *hwc_window,
+ E_Hwc_Presentation_Callback_List *list)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
+
+ e_hwc_presentation_callback_list_merge(&hwc_window->presentation_callbacks,
+ list);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_presentation_callback_call(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (!eina_list_count(hwc_window->presentation_callbacks.callbacks))
+ return EINA_TRUE;
+
+ e_hwc_presentation_callback_list_call(&hwc_window->presentation_callbacks);
+
+ return EINA_TRUE;
+}
E_Presentation_Time_Container presentation_container;
Eina_Bool present_sync;
+
+ E_Hwc_Presentation_Callback_List pending_presentation_callbacks;
+ E_Hwc_Presentation_Callback_List presentation_callbacks;
};
struct _E_Hwc_Window_Target
EINTERN Eina_Bool e_hwc_window_pending_update_data_dequeue_cancel(E_Hwc_Window *hwc_window, E_Hwc_Window_Update_Data *update);
EINTERN Eina_Bool e_hwc_window_pending_update_data_has(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_presentation_callback_pending_set(E_Hwc_Window *hwc_window, E_Hwc_Presentation_Callback *callback);
+EINTERN Eina_Bool e_hwc_window_presentation_callback_take(E_Hwc_Window *hwc_window, E_Hwc_Presentation_Callback_List *list);
+EINTERN Eina_Bool e_hwc_window_presentation_callback_call(E_Hwc_Window *hwc_window);
+
#endif // E_HWC_WINDOW_H
#endif
struct _E_Hwc_Windows_Comp_Info
{
E_Presentation_Time_Container presentation_container;
+ E_Hwc_Presentation_Callback_List presentation_callbacks;
Eina_Bool skip;
E_Egl_Sync *release_fence;
Eina_List *pending_update_list;
_e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
e_presentation_time_container_finish(&comp_info->presentation_container);
+ e_hwc_presentation_callback_list_finish(&comp_info->presentation_callbacks);
E_FREE(comp_info);
}
EINA_SAFETY_ON_FALSE_RETURN_VAL(comp_info, NULL);
e_presentation_time_container_init(&comp_info->presentation_container);
+ e_hwc_presentation_callback_list_init(&comp_info->presentation_callbacks);
tbm_surface_internal_add_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
_e_hwc_windows_comp_info_cb_tbm_surface_destroy);
e_hwc_window_presentation_time_feedback_take(hwc_window, container);
}
+static void
+_e_hwc_windows_presentation_callback_take(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Presentation_Callback_List *list = NULL;
+
+ if (hwc_window->is_target)
+ {
+ E_Hwc_Windows_Comp_Info *comp_info;
+
+ if (!hwc_window->current.buffer.tsurface) return;
+
+ comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
+ if (!comp_info) return;
+
+ list = &comp_info->presentation_callbacks;
+ }
+ else
+ {
+ list = &hwc_window->pending_presentation_callbacks;
+ }
+
+ if (!list) return;
+
+ e_hwc_window_presentation_callback_take(hwc_window, list);
+}
+
static void
_e_hwc_windows_commit_data_release(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data,
int sequence, unsigned int tv_sec, unsigned int tv_usec)
sequence,
tv_sec,
tv_usec);
+ e_hwc_window_presentation_callback_call(hwc_window);
/* it is possible that other hwc_window is freed in
* _e_hwc_windows_rendered_windows_free.
if (hwc_window->is_target) continue;
e_hwc_window_presentation_time_feedback_present(hwc_window, sequence, tv_sec, tv_usec);
+ e_hwc_window_presentation_callback_call(hwc_window);
if (e_hwc_window_is_video(hwc_window) && hwc_window->ec)
{
if (!commit_data) continue;
_e_hwc_windows_presentation_feedback_take(hwc_window);
+ _e_hwc_windows_presentation_callback_take(hwc_window);
if (ehws_dump_enable)
e_hwc_window_commit_data_buffer_dump(hwc_window, commit_data);
if (hwc_window_target)
{
e_hwc_window_presentation_time_feedback_discard(hwc_window_target);
+ e_hwc_window_presentation_callback_call(hwc_window_target);
commit_data = e_hwc_window_commit_data_acquire(hwc_window_target);
if (commit_data)
e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
e_hwc_window_presentation_time_feedback_discard(hwc_window);
+ e_hwc_window_presentation_callback_call(hwc_window);
e_hwc_window_commit_data_release(hwc_window, commit_data);
}
{
comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
if (comp_info)
- e_hwc_window_presentation_time_feedback_take(hwc_window,
- &comp_info->presentation_container);
+ {
+ e_hwc_window_presentation_time_feedback_take(hwc_window,
+ &comp_info->presentation_container);
+ e_hwc_window_presentation_callback_take(hwc_window,
+ &comp_info->presentation_callbacks);
+ }
if (hwc_window->current.buffer.queue)
{
{
e_hwc_window_presentation_time_feedback_take(hwc_window,
&comp_info->presentation_container);
+ e_hwc_window_presentation_callback_take(hwc_window,
+ &comp_info->presentation_callbacks);
e_hwc_window_queue_buffer_release(queue, queue_buffer);
return EINA_FALSE;
}
comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
if (comp_info)
- e_hwc_window_presentation_time_feedback_take(hwc_window,
- &comp_info->presentation_container);
+ {
+ e_hwc_window_presentation_time_feedback_take(hwc_window,
+ &comp_info->presentation_container);
+ e_hwc_window_presentation_callback_take(hwc_window,
+ &comp_info->presentation_callbacks);
+ }
e_hwc_window_queue_buffer_release(hwc_window->current.buffer.queue, queue_buffer);
}
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);
-
- EINA_LIST_FOREACH(rendered_windows, l, hwc_window)
+ EINA_LIST_FOREACH(target_hwc_window->hwc->hwc_windows, l, hwc_window)
{
E_Client *ec = NULL;
E_Comp_Wl_Client_Data *cdata;
+ if (hwc_window->render_target)
+ e_hwc_presentation_callback_list_merge(&comp_info->presentation_callbacks,
+ &hwc_window->pending_presentation_callbacks);
+
+ if (!hwc_window->on_rendered_target) continue;
+
hwc_window->on_rendered_target = EINA_FALSE;
ec = hwc_window->ec;
rendered_buffers = eina_list_append(rendered_buffers, buffer_ref);
}
- _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, rendered_buffers);
+ rendered_windows = eina_list_clone(target_hwc_window->rendered_windows);
_e_hwc_windows_comp_info_rendered_windows_set(comp_info, rendered_windows);
+ _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, rendered_buffers);
eina_list_free(target_hwc_window->rendered_windows);
target_hwc_window->rendered_windows = NULL;
if (ec && cdata)
e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
&cdata->presentation_container);
+
+ e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
+ &hwc->pp_hwc_window->pending_presentation_callbacks);
}
else
{
if (comp_info)
e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
&comp_info->presentation_container);
+
+ e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
+ &comp_info->presentation_callbacks);
}
}