evas - work on evas render2 and begin making it work at all

This commit is contained in:
Carsten Haitzler 2014-07-16 20:42:34 +09:00
parent 45f01bd11c
commit f5221b9cfb
5 changed files with 205 additions and 82 deletions

View File

@ -240,6 +240,8 @@ lib/evas/canvas/evas_font_dir.c \
lib/evas/canvas/evas_rectangle.c \
lib/evas/canvas/evas_render.c \
lib/evas/canvas/evas_render2.c \
lib/evas/canvas/evas_render2.h \
lib/evas/canvas/evas_render2_updates.c \
lib/evas/canvas/evas_smart.c \
lib/evas/canvas/evas_stack.c \
lib/evas/canvas/evas_async_events.c \

View File

@ -224,6 +224,7 @@ evas_object_change(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
obj->changed_move = EINA_FALSE;
}
if (obj->smart.smart) printf("change smart %p %i\n", obj, obj->changed);
if (obj->changed) return;
evas_render_object_recalc(eo_obj);

View File

@ -1,14 +1,4 @@
#include "evas_common_private.h"
#include "evas_private.h"
#include <math.h>
#include <assert.h>
#ifdef EVAS_CSERVE2
#include "evas_cs2_private.h"
#endif
#ifdef EVAS_RENDER_DEBUG_TIMING
#include <sys/time.h>
#endif
#include "evas_render2.h"
//////////////////////////////////////////////////////////////////////////////
// this is the start of a rewrite of the evas rendering infra. first port of
@ -25,11 +15,11 @@
// data types
//////////////////////////////////////////////////////////////////////////////
typedef struct Update Update;
typedef struct _Update Update;
struct _Update
{
Eina_Rectangle area;
Eina_Rectangle *area;
void *surface;
};
@ -47,11 +37,10 @@ static void _evas_render2_wakeup_cb(void *target, Evas_Callback_Type type, void
static void _evas_render2_wakeup_send(void *data);
static void _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info);
static void _evas_render2_updates_clean(Evas_Public_Data *e);
static void _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates);
static void _evas_render2_stage_generate_object_updates(Evas_Public_Data *e);
static void _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_async);
static void _evas_render2_stage_explicit_updates(Evas_Public_Data *e);
static void _evas_render2_stage_main_render_prepare(Evas_Public_Data *e);
static void _evas_render2_stage_render_do(Evas_Public_Data *e);
static void _evas_render2_stage_render_do(Evas_Public_Data *e, Eina_Bool do_async);
static void _evas_render2_stage_reset(Evas_Public_Data *e);
static void _evas_render2_stage_object_cleanup(Evas_Public_Data *e);
static void _evas_render2_th_render(void *data);
@ -93,7 +82,7 @@ _evas_render2_all_sync(void)
{
// wait for ALL canvases to stop rendering
Eo *eo_e;
if (!_rendering) return;
eo_e = eina_list_data_get(eina_list_last(_rendering));
_evas_render2_wait(eo_e);
@ -120,7 +109,7 @@ static void
_evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
{
int freeze_num = 0, i;
eo_do(eo_e, freeze_num = eo_event_freeze_count_get());
for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_thaw());
evas_event_callback_call(eo_e, type, event_info);
@ -130,21 +119,19 @@ _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
static void
_evas_render2_updates_clean(Evas_Public_Data *e)
{
Update *u;
void *u;
// clean out updates and tmp surfaces we were holding/tracking
EINA_LIST_FREE(e->render.updates, u)
{
//evas_cache_image_drop(u->surface);
free(u);
}
EINA_LIST_FREE(e->render.updates, u) eina_rectangle_free(u);
}
static void
_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_async)
{
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
Eina_List *ret_updates = NULL;
Evas_Event_Render_Post post;
// XXX:
// XXX: actually update screen from mainloop here if needed - eg software
// XXX: engine needs to xshmputimage here - engine func does this
@ -153,7 +140,22 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
// if we did do rendering flush output to target and call callbacks
if (e->render.updates)
{
Update *ru;
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
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,
EVAS_RENDER_MODE_ASYNC_END);
ret_updates = eina_list_append(ret_updates, ru->area);
evas_cache_image_drop(ru->surface);
free(ru);
}
if (do_async) post.updated_area = ret_updates;
else e->render.updates = ret_updates;
e->engine.func->output_flush(e->engine.data.output,
EVAS_RENDER_MODE_ASYNC_END);
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
@ -164,13 +166,8 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
_rendering = eina_list_remove(_rendering, eo_e);
e->rendering = EINA_FALSE;
// call the post render callback with info if appropriate
if ((1) || (e->render.updates))
{
Evas_Event_Render_Post post;
post.updated_area = e->render.updates;
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
}
if (do_async)
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
else
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
// if we don't want to keep updates after this
@ -179,47 +176,6 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
evas_module_clean();
}
static void
_evas_render2_object_basic_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj)
{
printf("_evas_render2_object_basic_process %p %p\n", e, obj);
}
static void
_evas_render2_object_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj)
{
// process object OR walk through child objects if smart and process those
Evas_Object_Protected_Data *obj2;
// XXX: this needs to become parallel, BUT we need new object methods to
// call to make that possible as the current ones work on a single global
// engine handle and single orderted redraw queue.
if (obj->smart.smart)
{
EINA_INLIST_FOREACH
(evas_object_smart_members_get_direct(obj->object), obj2)
_evas_render2_object_process(e, obj2);
}
else _evas_render2_object_basic_process(e, obj);
}
static void
_evas_render2_stage_generate_object_updates(Evas_Public_Data *e)
{
Evas_Layer *lay;
// XXX: should time this
EINA_INLIST_FOREACH(e->layers, lay)
{
Evas_Object_Protected_Data *obj;
EINA_INLIST_FOREACH(lay->objects, obj)
_evas_render2_object_process(e, obj);
}
}
static void
_evas_render2_stage_explicit_updates(Evas_Public_Data *e)
{
@ -262,12 +218,48 @@ _evas_render2_stage_main_render_prepare(Evas_Public_Data *e)
}
static void
_evas_render2_stage_render_do(Evas_Public_Data *e)
_evas_render2_stage_render_do(Evas_Public_Data *e, Eina_Bool do_async EINA_UNUSED)
{
// XXX:
void *surface;
int ux, uy, uw, uh;
int cx, cy, cw, ch;
// Evas_Render_Mode render_mode = EVAS_RENDER_MODE_UNDEF;
// if (!do_async) render_mode = EVAS_RENDER_MODE_SYNC;
// else render_mode = EVAS_RENDER_MODE_ASYNC_INIT;// XXX:
// XXX: actually render now (either in thread or in mainloop)
// XXX:
printf("_evas_render2_stage_render_do %p\n", e);
while ((surface =
e->engine.func->output_redraws_next_update_get
(e->engine.data.output,
&ux, &uy, &uw, &uh,
&cx, &cy, &cw, &ch)))
{
Update *ru = NULL;
void *ctx;
ctx = e->engine.func->context_new(e->engine.data.output);
e->engine.func->context_color_set
(e->engine.data.output, ctx,
rand() & 0xff, rand() & 0xff, rand() & 0xff, 0xff);
printf("%i %i %i %i\n", cx, cy, cw, ch);
e->engine.func->rectangle_draw(e->engine.data.output,
ctx, surface,
cx, cy, cw, ch,
EINA_FALSE);
e->engine.func->context_free(e->engine.data.output, ctx);
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);
// e->engine.func->output_redraws_next_update_push(e->engine.data.output,
// surface,
// ux, uy, uw, uh,
// render_mode);
}
e->engine.func->output_redraws_clear(e->engine.data.output);
}
static void
@ -295,8 +287,8 @@ static void
_evas_render2_th_render(void *data)
{
Evas_Public_Data *e = data;
printf("th rend %p\n", e);
_evas_render2_stage_render_do(e);
printf("th rend %p ......................................\n", e);
_evas_render2_stage_render_do(e, EINA_TRUE);
}
// major functions (called from evas_render.c)
@ -310,7 +302,7 @@ _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
Eina_Bool do_draw, Eina_Bool do_async)
{
Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
// if nothing changed at all since last render - skip this frame
if (!e->changed) return EINA_FALSE;
// we are still rendering while being asked to render - skip this frame
@ -344,15 +336,23 @@ _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
evas_thread_queue_flush(_evas_render2_wakeup_send, eo_e);
}
// or if not async, do rendering inline now
else _evas_render2_stage_render_do(e);
else _evas_render2_stage_render_do(e, EINA_FALSE);
}
// reset flags since rendering is processed now
_evas_render2_stage_reset(e);
// clean/delete/gc objects here
_evas_render2_stage_object_cleanup(e);
// if we are not going to be async then do last render stage here
if (!do_async) _evas_render2_stage_last(eo_e, make_updates);
if (!do_async) _evas_render2_stage_last(eo_e, make_updates, EINA_FALSE);
if (!do_draw) _evas_render2_updates_clean(e);
e->changed = EINA_FALSE;
e->viewport.changed = EINA_FALSE;
e->output.changed = EINA_FALSE;
e->framespace.changed = EINA_FALSE;
e->invalidate = EINA_FALSE;
evas_module_clean();
return EINA_TRUE;
}
@ -365,7 +365,7 @@ _evas_render2_end(Eo *eo_e)
// this is actually called if rendering was async and is done. this is
// run in the mainloop where rendering began and may handle any cleanup
// or pixel upload if needed here
_evas_render2_stage_last(eo_e, EINA_TRUE);
_evas_render2_stage_last(eo_e, EINA_TRUE, EINA_TRUE);
// release canvas object ref
eo_unref(eo_e);
}

View File

@ -0,0 +1,43 @@
#ifndef EVAS_RENDER2_H
#define EVAS_RENDER2_H
#include "evas_common_private.h"
#include "evas_private.h"
#include <math.h>
#include <assert.h>
#ifdef EVAS_CSERVE2
#include "evas_cs2_private.h"
#endif
#ifdef EVAS_RENDER_DEBUG_TIMING
#include <sys/time.h>
#endif
/* render stuff here */
void _evas_render2_stage_generate_object_updates(Evas_Public_Data *e);
#ifndef _WIN32
static inline double
get_time(void)
{
struct timeval timev;
gettimeofday(&timev, NULL);
return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
}
#else
static inline double
get_time(void)
{
return (double)GetTickCount()/1000.0;
}
#endif
static inline void
out_time(double t)
{
double b;
b = (t * 100.0) / (1.0 / 60.0);
printf("%1.8fs (%1.2f%% 60fps budget)\n", t, b);
}
#endif

View File

@ -0,0 +1,77 @@
#include "evas_render2.h"
static void
_obj_basic_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj, int l)
{
Evas_Object *eo_obj = obj->object;
obj->rect_del = EINA_FALSE;
obj->render_pre = EINA_FALSE;
if (obj->delete_me == 2) return;
else if (obj->delete_me != 0) obj->delete_me++;
evas_object_clip_recalc(obj);
obj->is_active = 1;
obj->func->render_pre(eo_obj, obj, obj->private_data);
obj->pre_render_done = EINA_TRUE;
int i; for (i = 0; i < l; i++) printf(" ");
printf("BASIC %p %p\n", e, obj);
obj->func->render_post(eo_obj, obj, obj->private_data);
obj->restack = EINA_FALSE;
obj->pre_render_done = EINA_FALSE;
evas_object_change_reset(eo_obj);
}
static void
_obj_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj, int l)
{
// process object OR walk through child objects if smart and process those
Evas_Object_Protected_Data *obj2;
Evas_Object *eo_obj = obj->object;
if (obj->smart.smart)
{
if (!evas_object_smart_changed_get(eo_obj)) return;
obj->rect_del = EINA_FALSE;
obj->render_pre = EINA_FALSE;
if (obj->delete_me == 2) return;
else if (obj->delete_me != 0) obj->delete_me++;
evas_object_clip_recalc(obj);
obj->is_active = 1;
obj->func->render_pre(eo_obj, obj, obj->private_data);
obj->pre_render_done = EINA_TRUE;
int i; for (i = 0; i < l; i++) printf(" ");
printf("SMART %p %p\n", e, obj);
EINA_INLIST_FOREACH
(evas_object_smart_members_get_direct(obj->object), obj2)
_obj_process(e, obj2, l + 1);
obj->func->render_post(eo_obj, obj, obj->private_data);
obj->restack = EINA_FALSE;
obj->pre_render_done = EINA_FALSE;
evas_object_change_reset(eo_obj);
}
else
{
if (!obj->changed) return;
_obj_basic_process(e, obj, l);
}
}
void
_evas_render2_stage_generate_object_updates(Evas_Public_Data *e)
{
Evas_Layer *lay;
Evas_Object_Protected_Data *obj;
double t;
t = get_time();
EINA_INLIST_FOREACH(e->layers, lay)
{
EINA_INLIST_FOREACH(lay->objects, obj) _obj_process(e, obj, 0);
}
t = get_time() - t;
printf("T: update generation: "); out_time(t);
}