discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=e7bcf0e690e75b13db022adaeeab1ab86c459540

commit e7bcf0e690e75b13db022adaeeab1ab86c459540
Author: Derek Foreman <derek.foreman.sams...@gmail.com>
Date:   Tue Jul 31 17:02:12 2018 -0400

    evas: Defer render post callbacks added during async render
    
    Summary:
    To take screenshots, Enlightenment makes a new snapshot object, performs
    a manual render, and uses the snapshot results.
    
    Turns out if this happens while an async render is in progress, the
    async render's completion triggers a render post callback on the snapshot
    object even though it's never been involved in a render.
    
    We need to defer new render post callbacks until any currently running
    render completes, then add them during that render's post.
    
    Fix T7156
    
    Reviewers: devilhorns, zmike
    
    Reviewed By: devilhorns, zmike
    
    Subscribers: devilhorns, cedric, #committers, zmike
    
    Tags: #efl
    
    Maniphest Tasks: T7156
    
    Differential Revision: https://phab.enlightenment.org/D6711
---
 src/lib/evas/canvas/evas_callbacks.c | 62 ++++++++++++++++++++++++++++++++++--
 src/lib/evas/canvas/evas_render.c    |  1 +
 src/lib/evas/include/evas_private.h  |  3 ++
 3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/src/lib/evas/canvas/evas_callbacks.c 
b/src/lib/evas/canvas/evas_callbacks.c
index 0814b6fa5b..bb4face262 100644
--- a/src/lib/evas/canvas/evas_callbacks.c
+++ b/src/lib/evas/canvas/evas_callbacks.c
@@ -107,6 +107,7 @@ typedef struct
    void                    *data;
    Evas_Callback_Type       type;
    Efl_Event_Info_Type      efl_event_type;
+   Evas_Callback_Priority   priority;
 } Evas_Event_Cb_Wrapper_Info;
 
 static int
@@ -563,6 +564,24 @@ evas_event_callback_add(Evas *eo_e, Evas_Callback_Type 
type, Evas_Event_Cb func,
                                     func, data);
 }
 
+void
+_deferred_callbacks_process(Evas *eo_e, Evas_Public_Data *e)
+{
+   Evas_Event_Cb_Wrapper_Info *cb_info;
+   const Efl_Event_Description *desc;
+
+   while (e->deferred_callbacks)
+     {
+        cb_info = EINA_INLIST_CONTAINER_GET(e->deferred_callbacks,
+                                            Evas_Event_Cb_Wrapper_Info);
+        e->deferred_callbacks = eina_inlist_remove(e->deferred_callbacks,
+                                                   e->deferred_callbacks);
+        desc = _legacy_evas_callback_table(cb_info->type);
+        efl_event_callback_priority_add(eo_e, desc, cb_info->priority, 
_eo_evas_cb, cb_info);
+        e->callbacks = eina_inlist_append(e->callbacks, 
EINA_INLIST_GET(cb_info));
+     }
+}
+
 EAPI void
 evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, 
Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
 {
@@ -581,13 +600,22 @@ evas_event_callback_priority_add(Evas *eo_e, 
Evas_Callback_Type type, Evas_Callb
    cb_info = calloc(1, sizeof(*cb_info));
    cb_info->func.evas_cb = func;
    cb_info->data = (void *)data;
+   cb_info->priority = priority;
    cb_info->type = type;
    cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
 
-   desc = _legacy_evas_callback_table(type);
-   efl_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, cb_info);
+   if ((e->rendering || e->inside_post_render) && type == 
EVAS_CALLBACK_RENDER_POST)
+     {
+        e->deferred_callbacks = eina_inlist_append(e->deferred_callbacks,
+                                                   EINA_INLIST_GET(cb_info));
+     }
+   else
+     {
+        desc = _legacy_evas_callback_table(type);
+        efl_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, 
cb_info);
 
-   e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
+        e->callbacks = eina_inlist_append(e->callbacks, 
EINA_INLIST_GET(cb_info));
+     }
 }
 
 EAPI void *
@@ -604,6 +632,20 @@ evas_event_callback_del(Evas *eo_e, Evas_Callback_Type 
type, Evas_Event_Cb func)
 
    if (!e->callbacks) return NULL;
 
+   if (type == EVAS_CALLBACK_RENDER_POST)
+     EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
+       {
+          if (info->func.evas_cb == func)
+            {
+               void *tmp = info->data;
+
+               e->deferred_callbacks =
+                  eina_inlist_remove(e->deferred_callbacks, 
EINA_INLIST_GET(info));
+               free(info);
+               return tmp;
+            }
+       }
+
    EINA_INLIST_REVERSE_FOREACH(e->callbacks, info)
      {
         if ((info->func.evas_cb == func) && (info->type == type))
@@ -634,6 +676,20 @@ evas_event_callback_del_full(Evas *eo_e, 
Evas_Callback_Type type, Evas_Event_Cb
 
    if (!e->callbacks) return NULL;
 
+   if (type == EVAS_CALLBACK_RENDER_POST)
+     EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
+       {
+          if ((info->func.evas_cb == func) && (info->data == data))
+            {
+               void *tmp = info->data;
+
+               e->deferred_callbacks =
+                  eina_inlist_remove(e->deferred_callbacks, 
EINA_INLIST_GET(info));
+               free(info);
+               return tmp;
+            }
+       }
+
    EINA_INLIST_FOREACH(e->callbacks, info)
      {
         if ((info->func.evas_cb == func) && (info->type == type) && 
(info->data == data))
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index f03a6a5cab..0a915a19df 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -3838,6 +3838,7 @@ evas_render_wakeup(Evas *eo_e)
    post.updated_area = ret_updates;
    _cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
    evas->inside_post_render = EINA_FALSE;
+   _deferred_callbacks_process(eo_e, evas);
 
    evas_render_updates_free(ret_updates);
 
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index bded8892b6..a63194df3f 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -860,6 +860,7 @@ struct _Evas_Public_Data
    Eina_List     *post_events; // free me on evas_free
 
    Eina_Inlist    *callbacks;
+   Eina_Inlist    *deferred_callbacks;
 
    int            delete_grabs;
    int            walking_grabs;
@@ -1914,6 +1915,8 @@ void _efl_canvas_gesture_manager_callback_add_hook(Eo 
*gesture_manager, Eo *targ
 void evas_focus_init(void);
 void evas_focus_shutdown(void);
 
+void _deferred_callbacks_process(Evas *eo_e, Evas_Public_Data *e);
+
 extern Eina_Cow *evas_object_proxy_cow;
 extern Eina_Cow *evas_object_map_cow;
 extern Eina_Cow *evas_object_state_cow;

-- 


Reply via email to