forked from enlightenment/efl
parent
645dcff9d2
commit
a7b4a3c12d
|
@ -1670,6 +1670,31 @@ EAPI void evas_obscured_rectangle_add(Evas *e, int x, int y, int w,
|
|||
*/
|
||||
EAPI void evas_obscured_clear(Evas *e) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Render the given Evas canvas asynchronously.
|
||||
*
|
||||
* @param e The canvas to render.
|
||||
* @param func Optional function to call with the list of updated areas.
|
||||
* @param data User data to pass to @p func.
|
||||
*
|
||||
* @return EINA_TRUE if the canvas will render, EINA_FALSE otherwise.
|
||||
*
|
||||
* This function only returns EINA_TRUE whne a frame will be rendered. If the
|
||||
* previous frame is still rendering, EINA_FALSE will be returned so the users
|
||||
* know not to wait for the updates callback and just return to their main
|
||||
* loop.
|
||||
*
|
||||
* If a @p func callback is given, a list of updated areas will be generated
|
||||
* and the function will be called from the main thread after the rendered
|
||||
* frame is flushed to the screen. The resulting list should be freed with
|
||||
* @f evas_render_updates_free().
|
||||
* The list is given in the @p event_info parameter of the callback function.
|
||||
*
|
||||
* @ingroup Evas_Canvas
|
||||
* @since 1.8
|
||||
*/
|
||||
EAPI Eina_Bool evas_render_async(Evas *e, Evas_Event_Cb func, void *data) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Force immediate renderization of the given Evas canvas.
|
||||
*
|
||||
|
@ -2425,6 +2450,7 @@ enum
|
|||
EVAS_CANVAS_SUB_ID_OBJECTS_IN_RECTANGLE_GET,
|
||||
EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE,
|
||||
EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE_COUNT_GET,
|
||||
EVAS_CANVAS_SUB_ID_RENDER_ASYNC,
|
||||
EVAS_CANVAS_SUB_ID_LAST
|
||||
};
|
||||
|
||||
|
@ -3692,6 +3718,19 @@ enum
|
|||
*/
|
||||
#define evas_canvas_smart_objects_calculate_count_get(ret) EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE_COUNT_GET), EO_TYPECHECK(int *, ret)
|
||||
|
||||
/**
|
||||
* @def evas_canvas_render_async
|
||||
* @since 1.8
|
||||
*
|
||||
* Render canvas asynchronously
|
||||
*
|
||||
* @param[in] func Callback function for list of updates
|
||||
* @param[in] data User data pointer to pass to func
|
||||
* @param[out] ret Whether or not a frame will get rendered after the call
|
||||
*
|
||||
* @see evas_render_async
|
||||
*/
|
||||
#define evas_canvas_render_async(func, data, ret) EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_RENDER_ASYNC), EO_TYPECHECK(Evas_Event_Cb, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(Eina_Bool *, ret)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -105,33 +105,20 @@ evas_async_events_fd_get(void)
|
|||
return _fd_read;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
evas_async_events_process(void)
|
||||
static int
|
||||
_evas_async_events_process_single(void)
|
||||
{
|
||||
Evas_Event_Async *ev;
|
||||
int check;
|
||||
int count = 0;
|
||||
int ret;
|
||||
|
||||
if (_fd_read == -1) return 0;
|
||||
|
||||
_evas_async_events_fork_handle();
|
||||
|
||||
do
|
||||
ret = read(_fd_read, &ev, sizeof(Evas_Event_Async *));
|
||||
if (ret == sizeof(Evas_Event_Async *))
|
||||
{
|
||||
check = read(_fd_read, &ev, sizeof (Evas_Event_Async *));
|
||||
|
||||
if (check == sizeof (Evas_Event_Async *))
|
||||
{
|
||||
if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
|
||||
free(ev);
|
||||
count++;
|
||||
}
|
||||
if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
|
||||
free(ev);
|
||||
return 1;
|
||||
}
|
||||
while (check > 0);
|
||||
|
||||
evas_cache_image_wakeup();
|
||||
|
||||
if (check < 0)
|
||||
else if (ret < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
|
@ -139,13 +126,55 @@ evas_async_events_process(void)
|
|||
case EINVAL:
|
||||
case EIO:
|
||||
case EISDIR:
|
||||
_fd_read = -1;
|
||||
_fd_read = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
evas_async_events_process(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (_fd_read == -1) return 0;
|
||||
|
||||
_evas_async_events_fork_handle();
|
||||
|
||||
while (_evas_async_events_process_single() > 0) count++;
|
||||
|
||||
evas_cache_image_wakeup();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_async_events_fd_blocking_set(Eina_Bool blocking)
|
||||
{
|
||||
long flags = fcntl(_fd_read, F_GETFL);
|
||||
|
||||
if (blocking) flags &= ~O_NONBLOCK;
|
||||
else flags |= O_NONBLOCK;
|
||||
|
||||
fcntl(_fd_read, F_SETFL, flags);
|
||||
}
|
||||
|
||||
int
|
||||
evas_async_events_process_blocking(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
_evas_async_events_fork_handle();
|
||||
|
||||
_evas_async_events_fd_blocking_set(EINA_TRUE);
|
||||
ret = _evas_async_events_process_single();
|
||||
evas_cache_image_wakeup(); /* FIXME: is this needed ? */
|
||||
_evas_async_events_fd_blocking_set(EINA_FALSE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_info, Evas_Async_Events_Put_Cb func)
|
||||
{
|
||||
|
|
|
@ -152,6 +152,8 @@ evas_free(Evas *eo_e)
|
|||
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
|
||||
return;
|
||||
MAGIC_CHECK_END();
|
||||
Evas_Public_Data *e = eo_data_get(eo_e, EVAS_CLASS);
|
||||
e->requested_free = EINA_TRUE;
|
||||
eo_unref(eo_e);
|
||||
}
|
||||
|
||||
|
@ -1064,6 +1066,7 @@ _class_constructor(Eo_Class *klass)
|
|||
EO_OP_FUNC(EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_OBJECTS_IN_RECTANGLE_GET), _canvas_objects_in_rectangle_get),
|
||||
EO_OP_FUNC(EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE), _canvas_smart_objects_calculate),
|
||||
EO_OP_FUNC(EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE_COUNT_GET), _canvas_smart_objects_calculate_count_get),
|
||||
EO_OP_FUNC(EVAS_CANVAS_ID(EVAS_CANVAS_SUB_ID_RENDER_ASYNC), _canvas_render_async),
|
||||
EO_OP_FUNC_SENTINEL
|
||||
};
|
||||
|
||||
|
@ -1163,6 +1166,7 @@ static const Eo_Op_Description op_desc[] = {
|
|||
EO_OP_DESCRIPTION(EVAS_CANVAS_SUB_ID_OBJECTS_IN_RECTANGLE_GET, "Retrieves the objects in the given rectangle region."),
|
||||
EO_OP_DESCRIPTION(EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE, "Call user-provided calculate() smart functions."),
|
||||
EO_OP_DESCRIPTION(EVAS_CANVAS_SUB_ID_SMART_OBJECTS_CALCULATE_COUNT_GET, "Get the internal counter that counts the number of smart calculations."),
|
||||
EO_OP_DESCRIPTION(EVAS_CANVAS_SUB_ID_RENDER_ASYNC, "Renders the canvas asynchronously."),
|
||||
EO_OP_DESCRIPTION_SENTINEL
|
||||
};
|
||||
|
||||
|
|
|
@ -1291,15 +1291,23 @@ _evas_render_cutout_add(Evas *eo_e, Evas_Object *eo_obj, int off_x, int off_y)
|
|||
}
|
||||
}
|
||||
|
||||
static Eina_List *
|
||||
void
|
||||
evas_render_rendering_wait(Evas_Public_Data *evas)
|
||||
{
|
||||
while (evas->rendering) evas_async_events_process_blocking();
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
evas_render_updates_internal(Evas *eo_e,
|
||||
unsigned char make_updates,
|
||||
unsigned char do_draw)
|
||||
unsigned char do_draw,
|
||||
Evas_Render_Done_Cb done_func,
|
||||
void *done_data,
|
||||
Eina_Bool do_async)
|
||||
{
|
||||
Evas_Object *eo_obj;
|
||||
Evas_Object_Protected_Data *obj;
|
||||
Evas_Public_Data *e;
|
||||
Eina_List *updates = NULL;
|
||||
Eina_List *ll;
|
||||
void *surface;
|
||||
Eina_Bool clean_them = EINA_FALSE;
|
||||
|
@ -1312,11 +1320,16 @@ evas_render_updates_internal(Evas *eo_e,
|
|||
Eina_Bool haveup = 0;
|
||||
|
||||
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
|
||||
return NULL;
|
||||
return EINA_FALSE;
|
||||
MAGIC_CHECK_END();
|
||||
|
||||
e = eo_data_get(eo_e, EVAS_CLASS);
|
||||
if (!e->changed) return NULL;
|
||||
if (!e->changed) return EINA_FALSE;
|
||||
|
||||
if (e->rendering) return EINA_FALSE;
|
||||
e->rendering = EINA_TRUE;
|
||||
|
||||
if (do_async) eo_ref(eo_e);
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
|
@ -1537,15 +1550,25 @@ evas_render_updates_internal(Evas *eo_e,
|
|||
&cx, &cy, &cw, &ch)))
|
||||
{
|
||||
int off_x, off_y;
|
||||
Render_Updates *ru;
|
||||
|
||||
RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
|
||||
if (make_updates)
|
||||
if (do_async)
|
||||
{
|
||||
ru = malloc(sizeof(*ru));
|
||||
ru->surface = surface;
|
||||
NEW_RECT(ru->area, ux, uy, uw, uh);
|
||||
e->render.updates = eina_list_append(e->render.updates, ru);
|
||||
evas_cache_image_ref(surface);
|
||||
}
|
||||
else if (make_updates)
|
||||
{
|
||||
Eina_Rectangle *rect;
|
||||
|
||||
NEW_RECT(rect, ux, uy, uw, uh);
|
||||
if (rect)
|
||||
updates = eina_list_append(updates, rect);
|
||||
e->render.updates = eina_list_append(e->render.updates,
|
||||
rect);
|
||||
}
|
||||
haveup = EINA_TRUE;
|
||||
off_x = cx - ux;
|
||||
|
@ -1647,30 +1670,41 @@ evas_render_updates_internal(Evas *eo_e,
|
|||
#ifdef REND_DBG
|
||||
, 1
|
||||
#endif
|
||||
);
|
||||
, do_async);
|
||||
e->engine.func->context_cutout_clear(e->engine.data.output,
|
||||
e->engine.data.context);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* punch rect out */
|
||||
e->engine.func->output_redraws_next_update_push(e->engine.data.output,
|
||||
surface,
|
||||
ux, uy, uw, uh);
|
||||
|
||||
if (!do_async)
|
||||
e->engine.func->output_redraws_next_update_push(e->engine.data.output,
|
||||
surface,
|
||||
ux, uy, uw, uh);
|
||||
|
||||
/* free obscuring objects list */
|
||||
eina_array_clean(&e->temporary_objects);
|
||||
RD(" ---]\n");
|
||||
}
|
||||
/* flush redraws */
|
||||
if (haveup)
|
||||
|
||||
if (do_async)
|
||||
{
|
||||
evas_thread_queue_flush((Evas_Thread_Command_Cb)done_func, done_data, 0);
|
||||
}
|
||||
else if (haveup)
|
||||
{
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
|
||||
e->engine.func->output_flush(e->engine.data.output);
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
|
||||
}
|
||||
}
|
||||
/* clear redraws */
|
||||
e->engine.func->output_redraws_clear(e->engine.data.output);
|
||||
|
||||
if (!do_async)
|
||||
{
|
||||
/* clear redraws */
|
||||
e->engine.func->output_redraws_clear(e->engine.data.output);
|
||||
}
|
||||
|
||||
/* and do a post render pass */
|
||||
for (i = 0; i < e->active_objects.count; ++i)
|
||||
{
|
||||
|
@ -1753,11 +1787,85 @@ evas_render_updates_internal(Evas *eo_e,
|
|||
|
||||
evas_module_clean();
|
||||
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
|
||||
if (!do_async)
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
|
||||
|
||||
RD("---]\n");
|
||||
|
||||
return updates;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
evas_render_wakeup(Evas *eo_e)
|
||||
{
|
||||
Render_Updates *ru;
|
||||
Eina_Bool haveup = EINA_FALSE;
|
||||
Eina_List *ret_updates = NULL;
|
||||
Evas_Public_Data *e = eo_data_get(eo_e, EVAS_CLASS);
|
||||
|
||||
if (e->requested_free)
|
||||
{
|
||||
EINA_LIST_FREE(e->render.updates, ru)
|
||||
{
|
||||
eina_rectangle_free(ru->area);
|
||||
free(ru);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
EINA_LIST_FREE(e->render.updates, ru)
|
||||
{
|
||||
/* punch rect out */
|
||||
e->engine.func->output_redraws_next_update_push(e->engine.data.output,
|
||||
ru->surface,
|
||||
ru->area->x,
|
||||
ru->area->y,
|
||||
ru->area->w,
|
||||
ru->area->h);
|
||||
if (e->render.updates_cb)
|
||||
ret_updates = eina_list_append(ret_updates, ru->area);
|
||||
else
|
||||
eina_rectangle_free(ru->area);
|
||||
evas_cache_image_drop(ru->surface);
|
||||
free(ru);
|
||||
haveup = EINA_TRUE;
|
||||
}
|
||||
|
||||
/* flush redraws */
|
||||
if (haveup)
|
||||
{
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
|
||||
e->engine.func->output_flush(e->engine.data.output);
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
|
||||
}
|
||||
|
||||
/* clear redraws */
|
||||
e->engine.func->output_redraws_clear(e->engine.data.output);
|
||||
|
||||
evas_event_callback_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
|
||||
|
||||
if (e->render.updates_cb)
|
||||
e->render.updates_cb(e->render.data, eo_e, ret_updates);
|
||||
|
||||
e->rendering = EINA_FALSE;
|
||||
e->render.updates_cb = NULL;
|
||||
e->render.data = NULL;
|
||||
|
||||
end:
|
||||
eo_unref(eo_e);
|
||||
}
|
||||
|
||||
static void
|
||||
evas_render_async_wakeup(void *target, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
Evas_Public_Data *e = target;
|
||||
evas_render_wakeup(e->evas);
|
||||
}
|
||||
|
||||
static void
|
||||
evas_render_pipe_wakeup(void *data)
|
||||
{
|
||||
evas_async_events_put(data, 0, NULL, evas_render_async_wakeup);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1769,6 +1877,30 @@ evas_render_updates_free(Eina_List *updates)
|
|||
eina_rectangle_free(r);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_render_async(Evas *eo_e, Evas_Event_Cb func, void *data)
|
||||
{
|
||||
MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
|
||||
return EINA_FALSE;
|
||||
MAGIC_CHECK_END();
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
eo_do(eo_e, evas_canvas_render_async(func, data, &ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_canvas_render_async(Eo *eo_e, void *_pd, va_list *list)
|
||||
{
|
||||
Evas_Event_Cb func = va_arg(*list, Evas_Event_Cb);
|
||||
void *data = va_arg(*list, void *);
|
||||
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
|
||||
Evas_Public_Data *e = _pd;
|
||||
|
||||
e->render.updates_cb = func;
|
||||
e->render.data = data;
|
||||
*ret = evas_render_updates_internal(eo_e, 1, 1, evas_render_pipe_wakeup, e, EINA_TRUE);
|
||||
}
|
||||
|
||||
EAPI Eina_List *
|
||||
evas_render_updates(Evas *eo_e)
|
||||
{
|
||||
|
@ -1780,6 +1912,25 @@ evas_render_updates(Evas *eo_e)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static Eina_List *
|
||||
evas_render_updates_internal_wait(Evas *eo_e,
|
||||
unsigned char make_updates,
|
||||
unsigned char do_draw)
|
||||
{
|
||||
Eina_List *ret = NULL;
|
||||
Evas_Public_Data *e = eo_data_get(eo_e, EVAS_CLASS);
|
||||
|
||||
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, NULL, NULL,
|
||||
EINA_FALSE))
|
||||
return NULL;
|
||||
|
||||
ret = e->render.updates;
|
||||
e->render.updates = NULL;
|
||||
e->rendering = EINA_FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_canvas_render_updates(Eo *eo_e, void *_pd, va_list *list)
|
||||
{
|
||||
|
@ -1792,7 +1943,7 @@ _canvas_render_updates(Eo *eo_e, void *_pd, va_list *list)
|
|||
*ret = NULL;
|
||||
return;
|
||||
}
|
||||
*ret = evas_render_updates_internal(eo_e, 1, 1);
|
||||
*ret = evas_render_updates_internal_wait(eo_e, 1, 1);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1810,7 +1961,7 @@ _canvas_render(Eo *eo_e, void *_pd, va_list *list EINA_UNUSED)
|
|||
Evas_Public_Data *e = _pd;
|
||||
|
||||
if (!e->changed) return;
|
||||
evas_render_updates_internal(eo_e, 0, 1);
|
||||
evas_render_updates_internal_wait(eo_e, 0, 1);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1826,7 +1977,7 @@ void
|
|||
_canvas_norender(Eo *eo_e, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
|
||||
{
|
||||
// if (!e->changed) return;
|
||||
evas_render_updates_internal(eo_e, 0, 0);
|
||||
evas_render_updates_internal_wait(eo_e, 0, 0);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
|
|
@ -1264,6 +1264,9 @@ Tilebuf_Rect *evas_common_regionbuf_rects_get (Regionbuf *rb);
|
|||
|
||||
void evas_font_dir_cache_free(void);
|
||||
|
||||
int evas_async_events_process_blocking(void);
|
||||
void evas_render_rendering_wait(Evas_Public_Data *evas);
|
||||
|
||||
void evas_thread_init(void);
|
||||
void evas_thread_shutdown(void);
|
||||
EAPI void evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data, size_t size);
|
||||
|
|
|
@ -371,6 +371,12 @@ struct _Evas_Public_Data
|
|||
int info_magic;
|
||||
} engine;
|
||||
|
||||
struct {
|
||||
Eina_List *updates;
|
||||
Evas_Event_Cb updates_cb;
|
||||
void *data;
|
||||
} render;
|
||||
|
||||
Eina_Array delete_objects;
|
||||
Eina_Array active_objects;
|
||||
Eina_Array restack_objects;
|
||||
|
@ -414,6 +420,8 @@ struct _Evas_Public_Data
|
|||
unsigned char cleanup : 1;
|
||||
unsigned char focus : 1;
|
||||
Eina_Bool is_frozen : 1;
|
||||
Eina_Bool rendering : 1;
|
||||
Eina_Bool requested_free : 1;
|
||||
|
||||
Eina_List *touch_points;
|
||||
Eina_List *devices;
|
||||
|
@ -718,7 +726,7 @@ struct _Evas_Device
|
|||
struct _Evas_Object_Func
|
||||
{
|
||||
void (*free) (Evas_Object *obj, Evas_Object_Protected_Data *pd);
|
||||
void (*render) (Evas_Object *obj, Evas_Object_Protected_Data *pd, void *output, void *context, void *surface, int x, int y);
|
||||
void (*render) (Evas_Object *obj, Evas_Object_Protected_Data *pd, void *output, void *context, void *surface, int x, int y, Eina_Bool do_async);
|
||||
void (*render_pre) (Evas_Object *obj, Evas_Object_Protected_Data *pd);
|
||||
void (*render_post) (Evas_Object *obj, Evas_Object_Protected_Data *pd);
|
||||
|
||||
|
@ -1127,6 +1135,7 @@ void _canvas_key_modifier_mask_get(Eo *e, void *_pd, va_list *list);
|
|||
void _canvas_damage_rectangle_add(Eo *obj, void *_pd, va_list *list);
|
||||
void _canvas_obscured_rectangle_add(Eo *obj, void *_pd, va_list *list);
|
||||
void _canvas_obscured_clear(Eo *obj, void *_pd, va_list *list);
|
||||
void _canvas_render_async(Eo *obj, void *_pd, va_list *list);
|
||||
void _canvas_render_updates(Eo *obj, void *_pd, va_list *list);
|
||||
void _canvas_render(Eo *e, void *_pd, va_list *list);
|
||||
void _canvas_norender(Eo *e, void *_pd, va_list *list);
|
||||
|
|
Loading…
Reference in New Issue