evas: move watching over destruction of device to custom logic due to high use.

Summary:
This specific EFL_EVENT_DEL handler was registered thousand of time alone on
an Evas device. Potential solution are to improve handling of this kind of large
scale callback logic or just not take that path. I find it easier to have a custom
code in this case to handle the destruction of Evas device and avoid this
thousand of callback.

Depends on D10492

Reviewers: zmike, raster, bu5hm4n, Hermet

Reviewed By: zmike

Subscribers: #reviewers, #committers

Tags: #efl

Maniphest Tasks: T8321

Differential Revision: https://phab.enlightenment.org/D10493
This commit is contained in:
Cedric Bail 2019-10-31 13:20:52 -04:00 committed by Mike Blumenkrantz
parent 21f07b9fa9
commit a9227fd530
4 changed files with 99 additions and 52 deletions

View File

@ -38,6 +38,8 @@ extern "C" {
#include <Efl.h>
typedef struct _Evas_Object_Pointer_Data Evas_Object_Pointer_Data;
EOAPI const Eina_List *efl_input_device_children_get(const Eo *obj);
EOAPI void efl_input_device_evas_set(Eo *obj, Evas *e);
@ -46,6 +48,9 @@ EOAPI Evas *efl_input_device_evas_get(const Eo *obj);
EOAPI void efl_input_device_subclass_set(Eo *obj, Evas_Device_Subclass sub_clas);
EOAPI Evas_Device_Subclass efl_input_device_subclass_get(const Eo *obj);
EOAPI void efl_input_device_grab_register(Eo *obj, Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
EOAPI void efl_input_device_grab_unregister(Eo *obj, Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
typedef struct _Efl_Input_Pointer_Data Efl_Input_Pointer_Data;
typedef struct _Efl_Input_Key_Data Efl_Input_Key_Data;
typedef struct _Efl_Input_Hold_Data Efl_Input_Hold_Data;

View File

@ -5,6 +5,8 @@
#include "Evas.h"
#define EFL_INTERNAL_UNSTABLE
#include "Evas_Internal.h"
#include "evas_common_private.h"
#include "evas_private.h"
#define MY_CLASS EFL_INPUT_DEVICE_CLASS
@ -16,6 +18,9 @@ struct _Efl_Input_Device_Data
Eo *evas; /* Evas */
Efl_Input_Device *source; /* ref */
Eina_List *children; /* ref'ed by efl_parent, not by this list */
Eina_Hash *grabs; /* Hash of all the object that might grab this device.
We expect thousand of them to be registered here,
that is why we use a hash. */
unsigned int id;
Efl_Input_Device_Type klass;
unsigned int subclass; // Evas_Device_Subclass (unused)
@ -71,6 +76,12 @@ _efl_input_device_efl_object_destructor(Eo *obj, Efl_Input_Device_Data *pd)
}
efl_unref(pd->source);
if (pd->grabs)
{
eina_hash_free(pd->grabs);
pd->grabs = NULL;
}
return efl_destructor(efl_super(obj, MY_CLASS));
}
@ -279,11 +290,42 @@ _efl_input_device_subclass_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_subclass_set, EFL_FUNC_CALL(sub_clas), Evas_Device_Subclass sub_clas);
static void
_grab_del(void *data)
{
Evas_Object_Pointer_Data *pdata = data;
evas_object_pointer_grab_del(pdata->obj, pdata);
}
static void
_efl_input_device_grab_register(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata)
{
if (!pd->grabs) pd->grabs = eina_hash_pointer_new(_grab_del);
eina_hash_add(pd->grabs, &grab, pdata);
}
EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_register, EFL_FUNC_CALL(grab, pdata),
Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
static void
_efl_input_device_grab_unregister(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata)
{
eina_hash_del(pd->grabs, &grab, pdata);
}
EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_unregister, EFL_FUNC_CALL(grab, pdata),
Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
#define EFL_INPUT_DEVICE_EXTRA_OPS \
EFL_OBJECT_OP_FUNC(efl_input_device_evas_get, _efl_input_device_evas_get), \
EFL_OBJECT_OP_FUNC(efl_input_device_evas_set, _efl_input_device_evas_set), \
EFL_OBJECT_OP_FUNC(efl_input_device_subclass_get, _efl_input_device_subclass_get), \
EFL_OBJECT_OP_FUNC(efl_input_device_subclass_set, _efl_input_device_subclass_set), \
EFL_OBJECT_OP_FUNC(efl_input_device_children_get, _efl_input_device_children_get), \
EFL_OBJECT_OP_FUNC(efl_input_device_grab_register, _efl_input_device_grab_register), \
EFL_OBJECT_OP_FUNC(efl_input_device_grab_unregister, _efl_input_device_grab_unregister),
#include "efl_input_device.eo.c"

View File

@ -81,9 +81,9 @@ _init_cow(void)
return EINA_TRUE;
}
static Evas_Object_Pointer_Data *
_evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
Efl_Input_Device *pointer)
Evas_Object_Pointer_Data *
evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
Efl_Input_Device *pointer)
{
Evas_Object_Pointer_Data *pdata;
@ -95,22 +95,6 @@ _evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
return NULL;
}
static void
_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, Evas_Object_Pointer_Data *pdata);
static void
_evas_device_del_cb(void *data, const Efl_Event *ev)
{
Evas_Object_Protected_Data *obj;
Evas_Object_Pointer_Data *pdata;
obj = efl_data_scope_safe_get(data, MY_CLASS);
EINA_SAFETY_ON_NULL_RETURN(obj);
pdata = _evas_object_pointer_data_find(obj, ev->object);
if (!pdata) return;
_evas_object_pointer_grab_del(obj, pdata);
}
static void
_evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj,
Evas_Object_Pointer_Data *pdata)
@ -138,9 +122,9 @@ _evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj,
}
}
static void
_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
Evas_Object_Pointer_Data *pdata)
void
evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
Evas_Object_Pointer_Data *pdata)
{
if ((pdata->mouse_grabbed > 0) && (obj->layer) && (obj->layer->evas))
pdata->evas_pdata->seat->mouse_grabbed -= pdata->mouse_grabbed;
@ -151,11 +135,12 @@ _evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
if (obj->proxy->is_proxy && obj->proxy->src_events)
_evas_object_proxy_grab_del(obj, pdata);
}
efl_event_callback_del(pdata->evas_pdata->pointer, EFL_EVENT_DEL,
_evas_device_del_cb, obj->object);
EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events)
events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, EINA_INLIST_GET(pdata));
EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
if (obj->events->pointer_grabs)
{
EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events)
events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, EINA_INLIST_GET(pdata));
EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
}
free(pdata);
}
@ -170,14 +155,13 @@ _evas_object_pointer_data_add(Evas_Pointer_Data *evas_pdata,
EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL);
pdata->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
pdata->evas_pdata = evas_pdata;
pdata->obj = obj;
EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events)
events->pointer_grabs = eina_inlist_append(events->pointer_grabs,
EINA_INLIST_GET(pdata));
EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
efl_event_callback_priority_add(evas_pdata->pointer, EFL_EVENT_DEL,
EFL_CALLBACK_PRIORITY_BEFORE,
_evas_device_del_cb, obj->object);
efl_input_device_grab_register(evas_pdata->pointer, obj->object, pdata);
return pdata;
}
@ -187,7 +171,7 @@ _evas_object_pointer_data_get(Evas_Pointer_Data *evas_pdata,
{
Evas_Object_Pointer_Data *pdata;
pdata = _evas_object_pointer_data_find(obj, evas_pdata->pointer);
pdata = evas_object_pointer_data_find(obj, evas_pdata->pointer);
//The pointer does not exist yet - create one.
if (!pdata)
@ -1068,29 +1052,39 @@ _efl_canvas_object_efl_object_invalidate(Eo *eo_obj, Evas_Object_Protected_Data
evas_object_hide(eo_obj);
if (obj->events)
EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events)
{
Evas_Public_Data *edata = NULL;
{
Eina_Inlist *pointer_grabs;
if (!efl_invalidated_get(evas_object_evas_get(eo_obj)))
edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS);
EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events)
{
Evas_Public_Data *edata = NULL;
EINA_LIST_FREE (events->focused_by_seats, dev)
{
event_id = _evas_event_counter;
efl_event_callback_del(dev, EFL_EVENT_INVALIDATE,
_evas_focus_device_invalidate_cb, obj);
if (edata) eina_hash_del_by_key(edata->focused_objects, &dev);
_evas_focus_dispatch_event(obj, dev, EINA_FALSE);
if ((obj->layer) && (obj->layer->evas))
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas, event_id);
}
EINA_INLIST_FREE(events->pointer_grabs, pdata)
_evas_object_pointer_grab_del(obj, pdata);
EINA_LIST_FREE(events->events_whitelist, dev)
efl_event_callback_del(dev, EFL_EVENT_DEL, _whitelist_events_device_remove_cb, obj);
}
EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
if (!efl_invalidated_get(evas_object_evas_get(eo_obj)))
edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS);
EINA_LIST_FREE (events->focused_by_seats, dev)
{
event_id = _evas_event_counter;
efl_event_callback_del(dev, EFL_EVENT_INVALIDATE,
_evas_focus_device_invalidate_cb, obj);
if (edata) eina_hash_del_by_key(edata->focused_objects, &dev);
_evas_focus_dispatch_event(obj, dev, EINA_FALSE);
if ((obj->layer) && (obj->layer->evas))
_evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas, event_id);
}
pointer_grabs = events->pointer_grabs;
events->pointer_grabs = NULL;
EINA_LIST_FREE(events->events_whitelist, dev)
efl_event_callback_del(dev, EFL_EVENT_DEL, _whitelist_events_device_remove_cb, obj);
}
EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
EINA_INLIST_FREE(pointer_grabs, pdata)
{
pointer_grabs = eina_inlist_remove(pointer_grabs, EINA_INLIST_GET(pdata));
efl_input_device_grab_unregister(pdata->evas_pdata->pointer, eo_obj, pdata);
}
}
event_id = _evas_object_event_new();
evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_DEL, NULL, event_id, NULL);

View File

@ -77,6 +77,7 @@ typedef struct _Evas_Format Evas_Format;
typedef struct _Evas_Map_Point Evas_Map_Point;
typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array;
typedef struct _Evas_Smart_Interfaces_Array Evas_Smart_Interfaces_Array;
typedef enum _Evas_Object_Intercept_Cb_Type Evas_Object_Intercept_Cb_Type;
typedef struct _Evas_Post_Callback Evas_Post_Callback;
typedef struct _Evas_Coord_Touch_Point Evas_Coord_Touch_Point;
typedef struct _Evas_Object_Proxy_Data Evas_Object_Proxy_Data;
@ -1095,6 +1096,7 @@ struct _Evas_Object_Protected_State
struct _Evas_Object_Pointer_Data {
EINA_INLIST;
Evas_Object_Protected_Data *obj;
Evas_Pointer_Data *evas_pdata;
Evas_Object_Pointer_Mode pointer_mode;
int mouse_grabbed;
@ -1679,6 +1681,10 @@ void evas_object_inform_call_image_preloaded(Evas_Object *obj);
void evas_object_inform_call_image_unloaded(Evas_Object *obj);
void evas_object_inform_call_image_resize(Evas_Object *obj);
void evas_object_intercept_cleanup(Evas_Object *obj);
Evas_Object_Pointer_Data *evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
Efl_Input_Device *pointer);
void evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
Evas_Object_Pointer_Data *pdata);
void evas_object_grabs_cleanup(Evas_Object *obj, Evas_Object_Protected_Data *pd);
void evas_key_grab_free(Evas_Object *obj, Evas_Object_Protected_Data *pd, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers);
void evas_object_smart_member_cache_invalidate(Evas_Object *obj, Eina_Bool pass_events, Eina_Bool freeze_events, Eina_Bool source_invisible);