e_hwc: Add E_Hwc_Presentation_Callback 07/261007/7
authorChangyeon Lee <cyeon.lee@samsung.com>
Thu, 8 Jul 2021 08:29:31 +0000 (17:29 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Thu, 22 Jul 2021 05:35:38 +0000 (05:35 +0000)
this callback for module want to know that timing of displaying(presentation)

if callback is added after frame of client is changed(ex: hide, show),
callback is called when frame is presented on display.

Once callback of E_Hwc_Presentation_Callback is called,
E_Hwc_Presentation_Callback should be destroyed.

Change-Id: Icbe0d7c92f6f3e3fdbce6c40a33a9c823d0f6d68

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

index aacb2dca8f419ae3cfac9759eb0ac46fdd3c9ff1..3bef20bd41cbba9fe53ddfd213006430b0b58691 100644 (file)
@@ -973,3 +973,161 @@ e_hwc_sync_callback_call(E_Hwc_Sync_Callback *sync_callback)
 
    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);
+}
index 574230bc02ac2a7e1677850c391bb04ef742635c..fc68f19c1866547e76c36f1687ee964c7bcccf47 100644 (file)
@@ -2,6 +2,8 @@
 
 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
 
@@ -65,6 +67,12 @@ typedef void (*E_Hwc_Hook_Cb)(void *data, E_Hwc *hwc);
 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
@@ -99,6 +107,16 @@ struct _E_Hwc_Sync_Callback
    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;
@@ -227,5 +245,18 @@ EINTERN Eina_Bool             e_hwc_sync_callback_call(E_Hwc_Sync_Callback *sync
 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
index 82254858b59d60a22ea0f8c4b5ac2fbfe26dcfe0..dee42b411dd86794588cb204c4a6228baff5a0be 100644 (file)
@@ -576,6 +576,8 @@ _e_hwc_window_free(E_Hwc_Window *hwc_window)
    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);
@@ -748,6 +750,8 @@ _e_hwc_window_new(E_Hwc *hwc, E_Client *ec, E_Hwc_Window_State state)
    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,
@@ -2936,3 +2940,55 @@ e_hwc_window_unref(E_Hwc_Window *hwc_window)
 
   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;
+}
index cf3911f1086c724cc25653f099c00dca83482e59..b8b80ab4e816ce37efdc28233552c5fee05b4898 100644 (file)
@@ -155,6 +155,9 @@ struct _E_Hwc_Window
    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
@@ -258,5 +261,9 @@ EINTERN Eina_Bool                 e_hwc_window_pending_update_data_enqueue(E_Hwc
 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
index cf5906a47ef04290d947e585afd72e382bee3a22..d6fc83a0741e3d4dfff9f0fddaf91ff4a21eb46b 100644 (file)
@@ -61,6 +61,7 @@ typedef struct _E_Hwc_Windows_Comp_Info E_Hwc_Windows_Comp_Info;
 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;
@@ -225,6 +226,7 @@ _e_hwc_windows_comp_info_free(void *data EINA_UNUSED, void *event)
    _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);
 }
@@ -255,6 +257,7 @@ _e_hwc_windows_comp_info_get(tbm_surface_h tbm_surface)
    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);
@@ -299,6 +302,32 @@ _e_hwc_windows_presentation_feedback_take(E_Hwc_Window *hwc_window)
    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)
@@ -321,6 +350,7 @@ _e_hwc_windows_commit_data_release(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_c
                                                         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.
@@ -336,6 +366,7 @@ _e_hwc_windows_commit_data_release(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_c
         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)
           {
@@ -431,6 +462,7 @@ _e_hwc_windows_commit_data_acquire(E_Hwc *hwc)
         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);
@@ -467,6 +499,7 @@ _e_hwc_windows_offscreen_commit(E_Hwc *hwc)
    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)
@@ -496,6 +529,7 @@ _e_hwc_windows_offscreen_commit(E_Hwc *hwc)
           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);
      }
@@ -552,8 +586,12 @@ _e_hwc_windows_target_window_buffer_skip(E_Hwc *hwc)
      {
         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)
           {
@@ -632,6 +670,8 @@ _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc)
           {
              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;
           }
@@ -701,8 +741,12 @@ _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc)
 
                   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);
                }
@@ -1451,15 +1495,17 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE
 
    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;
@@ -1505,8 +1551,9 @@ _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSE
         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;
@@ -3314,6 +3361,9 @@ _e_hwc_windows_pp_commit(E_Hwc *hwc)
              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
           {
@@ -3321,6 +3371,9 @@ _e_hwc_windows_pp_commit(E_Hwc *hwc)
              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);
           }
      }