evas: remove render2

Summary:
this is more or less a dead project, having not been actively developed
in over 2 years and instead forcing people to expend more time and energy
to keep it compiling across refactors

fix T7227

Reviewers: stefan_schmidt, Hermet, ManMower, devilhorns

Reviewed By: Hermet, devilhorns

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T7227

Differential Revision: https://phab.enlightenment.org/D6878
This commit is contained in:
Mike Blumenkrantz 2018-08-21 10:36:55 -04:00
parent daaf5ad190
commit 69fae8c7bf
16 changed files with 117 additions and 1401 deletions

View File

@ -246,8 +246,6 @@ lib/evas/canvas/evas_object_grid.c \
lib/evas/canvas/evas_font_dir.c \
lib/evas/canvas/evas_rectangle.c \
lib/evas/canvas/evas_render.c \
lib/evas/canvas/render2/evas_render2.c \
lib/evas/canvas/render2/evas_render2.h \
lib/evas/canvas/evas_smart.c \
lib/evas/canvas/evas_async_events.c \
lib/evas/canvas/evas_stats.c \
@ -288,13 +286,10 @@ lib/evas/gesture/efl_canvas_gesture_recognizer.c \
lib/evas/gesture/efl_canvas_gesture_recognizer_tap.c \
lib/evas/gesture/efl_canvas_gesture_recognizer_long_tap.c \
lib/evas/gesture/efl_canvas_gesture_manager.c \
lib/evas/common/region.c \
lib/evas/common/region.h \
$(NULL)
EXTRA_DIST2 += \
lib/evas/canvas/render2/evas_render2_th_main.c \
lib/evas/canvas/render2/region.c \
lib/evas/canvas/render2/region.h
# Vg
lib_evas_libevas_la_SOURCES += \
lib/evas/vg/evas_vg_cache.c
@ -486,7 +481,6 @@ lib/evas/common/evas_common_generic_cache.c
lib_evas_libevas_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_srcdir)/src/lib/evas/canvas \
-I$(top_srcdir)/src/lib/evas/canvas/render2 \
-I$(top_srcdir)/src/lib/evas/common \
-I$(top_srcdir)/src/lib/evas/common3d/save_load \
-I$(top_srcdir)/src/lib/evas/cserve2 \

View File

@ -385,7 +385,6 @@ void separate_functions(Eolian_Class const* klass, Eolian_Function_Type t, bool
strcmp("inputs_get", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
strcmp("constructor", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
strcmp("render_updates", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
strcmp("render2_updates", ::eolian_function_name_get(function)) != 0 && // TODO: remove this
strcmp("efl_canvas_surface_x11_pixmap_set", ::eolian_function_full_c_name_get(function, t, EINA_FALSE)) != 0 && // TODO: remove this
strcmp("efl_canvas_surface_x11_pixmap_get", ::eolian_function_full_c_name_get(function, t, EINA_FALSE)) != 0 && // TODO: remove this
strcmp("efl_canvas_surface_native_buffer_set", ::eolian_function_full_c_name_get(function, t, EINA_FALSE)) != 0 && // TODO: remove this

View File

@ -460,33 +460,6 @@ class Evas.Canvas (Efl.Object, Efl.Canvas.Scene, Efl.Animator, Efl.Input.Interfa
]]
return: bool; [[$true if the canvas will render, $false otherwise.]]
}
render2 {
[[Render the given Evas canvas using the new rendering infra.
This is experimental and will change over time until noted here.
This function only returns $true when a frame will be rendered.
If the previous frame is still rendering, $false will be
returned so the users know not to wait for the updates
callback and just return to their main loop.
@since 1.14
]]
return: bool; [[$true if the canvas will render, $false otherwise.]]
}
render2_updates {
[[Render the given Evas canvas using the new rendering infra.
This is experimental and will change over time until noted here.
@since 1.15
]]
return: list<ptr(Eina.Rect)> @owned @warn_unused; [[
A newly allocated list of updated rectangles of the canvas
($Eina.Rect structs). Free this list with
\@ref evas_render_updates_free.
]]
}
focus_out {
[[Inform the evas that it lost the focus from the default seat.]]
}

View File

@ -1,8 +1,6 @@
#include "evas_common_private.h"
#include "evas_private.h"
#include "evas_render2.h"
#define MY_CLASS EFL_CANVAS_RECTANGLE_CLASS
/* private magic number for rectangle objects */
@ -43,12 +41,6 @@ static int evas_object_rectangle_was_opaque(Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj,
void *type_private_data);
static void evas_object_rectangle_render2_walk(Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj,
void *type_private_data,
void *updates,
int offx,
int offy);
#if 0 /* usless calls for a rect object. much more useful for images etc. */
static void evas_object_rectangle_store(Evas_Object *eo_obj);
@ -83,7 +75,6 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL, // render_prepare
evas_object_rectangle_render2_walk
};
/* the actual api call to add a rect */
@ -117,66 +108,6 @@ evas_object_rectangle_init(Evas_Object *eo_obj)
obj->type = o_type;
}
static void
evas_object_rectangle_render2_walk(Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj,
void *type_private_data EINA_UNUSED,
void *updates, int offx, int offy)
{
Eina_Bool visible_is, visible_was;
unsigned int col_prev, col_cur;
if (obj->clip.clipees) return;
visible_is = evas_object_is_visible(eo_obj, obj);
if (!obj->changed) goto nochange;
if ((obj->cur->clipper) && (obj->cur->cache.clip.dirty))
evas_object_clip_recalc(obj->cur->clipper);
visible_was = evas_object_was_visible(eo_obj,obj);
// just became visible or invisible
if (visible_is != visible_was)
{
region_rect_add
(updates,
obj->cur->cache.clip.x - offx, obj->cur->cache.clip.y - offy,
obj->cur->cache.clip.w, obj->cur->cache.clip.h);
return;
}
// general change (prev and cur clip geom change)
col_prev = (obj->prev->color.a << 24) | (obj->prev->color.r << 16) |
(obj->prev->color.g << 8) | (obj->prev->color.b );
col_cur = (obj->cur->color.a << 24) | (obj->cur->color.r << 16) |
(obj->cur->color.g << 8) | (obj->cur->color.b );
if ((col_prev != col_cur) ||
((obj->cur->cache.clip.x != obj->prev->cache.clip.x) ||
(obj->cur->cache.clip.y != obj->prev->cache.clip.y) ||
(obj->cur->cache.clip.w != obj->prev->cache.clip.w) ||
(obj->cur->cache.clip.h != obj->prev->cache.clip.h)) ||
(obj->cur->render_op != obj->prev->render_op) ||
(obj->restack)
)
{
region_rect_add
(updates,
obj->prev->cache.clip.x - offx, obj->prev->cache.clip.y - offy,
obj->prev->cache.clip.w, obj->prev->cache.clip.h);
region_rect_add
(updates,
obj->cur->cache.clip.x - offx, obj->cur->cache.clip.y - offy,
obj->cur->cache.clip.w, obj->cur->cache.clip.h);
return;
}
nochange:
// object hasn't really changed
if ((visible_is) && (evas_object_is_opaque(eo_obj, obj)))
{
region_rect_del
(updates,
obj->cur->cache.clip.x - offx, obj->cur->cache.clip.y - offy,
obj->cur->cache.clip.w, obj->cur->cache.clip.h);
}
}
static void
evas_object_rectangle_render(Evas_Object *eo_obj EINA_UNUSED,
Evas_Object_Protected_Data *obj,

View File

@ -10,8 +10,6 @@
#include <sys/time.h>
#endif
#include "evas_render2.h"
// FIXME: Ugly!
#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
#include "efl_canvas_filter_internal.eo.h"
@ -3902,28 +3900,6 @@ evas_render_updates_free(Eina_List *updates)
eina_rectangle_free(r);
}
EOLIAN Eina_Bool
_evas_canvas_render2(Eo *eo_e, Evas_Public_Data *e)
{
Eina_Bool ret;
eina_evlog("+render2", eo_e, 0.0, NULL);
ret = _evas_render2(eo_e, e);
eina_evlog("-render2", eo_e, 0.0, NULL);
return ret;
}
EOLIAN Eina_List *
_evas_canvas_render2_updates(Eo *eo_e, Evas_Public_Data *e)
{
Eina_List *updates = NULL;
eina_evlog("+render2_updates", eo_e, 0.0, NULL);
updates = _evas_render2_updates(eo_e, e);
eina_evlog("-render2_updates", eo_e, 0.0, NULL);
return updates;
}
EOLIAN Eina_Bool
_evas_canvas_render_async(Eo *eo_e, Evas_Public_Data *e)
{
@ -3947,12 +3923,8 @@ evas_render_updates_internal_wait(Evas *eo_e,
Evas_Public_Data *e;
e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
if (e->render2) return _evas_render2_updates_wait(eo_e, e);
else
{
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, EINA_FALSE))
return NULL;
}
if (!evas_render_updates_internal(eo_e, make_updates, do_draw, EINA_FALSE))
return NULL;
eina_spinlock_take(&(e->render.lock));
EINA_LIST_FOREACH(e->outputs, l, out)
@ -4007,20 +3979,16 @@ _evas_canvas_render(Eo *eo_e, Evas_Public_Data *e)
EOLIAN void
_evas_canvas_norender(Eo *eo_e, Evas_Public_Data *e)
{
if (e->render2) _evas_norender2(eo_e, e);
else
{
Eina_List *ret;
Render_Updates *ru;
Eina_List *ret;
Render_Updates *ru;
evas_canvas_async_block(e);
// if (!e->changed) return;
ret = evas_render_updates_internal_wait(eo_e, 0, 0);
EINA_LIST_FREE(ret, ru)
{
eina_rectangle_free(ru->area);
free(ru);
}
evas_canvas_async_block(e);
// if (!e->changed) return;
ret = evas_render_updates_internal_wait(eo_e, 0, 0);
EINA_LIST_FREE(ret, ru)
{
eina_rectangle_free(ru->area);
free(ru);
}
}
@ -4028,36 +3996,32 @@ EOLIAN void
_evas_canvas_render_idle_flush(Eo *eo_e, Evas_Public_Data *evas)
{
eina_evlog("+idle_flush", eo_e, 0.0, NULL);
if (evas->render2) _evas_render2_idle_flush(eo_e, evas);
else
evas_canvas_async_block(evas);
evas_render_rendering_wait(evas);
evas_fonts_zero_pressure();
if (ENFN && ENFN->output_idle_flush)
{
evas_canvas_async_block(evas);
Efl_Canvas_Output *output;
Eina_List *l;
evas_render_rendering_wait(evas);
evas_fonts_zero_pressure();
if (ENFN && ENFN->output_idle_flush)
{
Efl_Canvas_Output *output;
Eina_List *l;
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_idle_flush(ENC, output->output);
}
eina_inarray_flush(&evas->active_objects);
OBJS_ARRAY_FLUSH(&evas->render_objects);
OBJS_ARRAY_FLUSH(&evas->restack_objects);
OBJS_ARRAY_FLUSH(&evas->delete_objects);
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
eina_array_clean(&evas->clip_changes);
evas->invalidate = EINA_TRUE;
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_idle_flush(ENC, output->output);
}
eina_inarray_flush(&evas->active_objects);
OBJS_ARRAY_FLUSH(&evas->render_objects);
OBJS_ARRAY_FLUSH(&evas->restack_objects);
OBJS_ARRAY_FLUSH(&evas->delete_objects);
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
eina_array_clean(&evas->clip_changes);
evas->invalidate = EINA_TRUE;
eina_evlog("-idle_flush", eo_e, 0.0, NULL);
}
@ -4065,12 +4029,8 @@ EOLIAN void
_evas_canvas_sync(Eo *eo_e, Evas_Public_Data *e)
{
eina_evlog("+render_sync", eo_e, 0.0, NULL);
if (e->render2) _evas_render2_sync(eo_e, e);
else
{
evas_canvas_async_block(e);
evas_render_rendering_wait(e);
}
evas_canvas_async_block(e);
evas_render_rendering_wait(e);
eina_evlog("-render_sync", eo_e, 0.0, NULL);
}
@ -4099,91 +4059,87 @@ _evas_render_dump_map_surfaces(Evas_Object *eo_obj)
EOLIAN void
_evas_canvas_render_dump(Eo *eo_e, Evas_Public_Data *evas)
{
if (evas->render2) _evas_render2_dump(eo_e, evas);
else
Evas_Layer *lay;
evas_canvas_async_block(evas);
evas_all_sync();
evas_cache_async_freeze();
EINA_INLIST_FOREACH(evas->layers, lay)
{
Evas_Layer *lay;
Evas_Object_Protected_Data *obj;
evas_canvas_async_block(evas);
evas_all_sync();
evas_cache_async_freeze();
EINA_INLIST_FOREACH(evas->layers, lay)
lay->walking_objects++;
EINA_INLIST_FOREACH(lay->objects, obj)
{
Evas_Object_Protected_Data *obj;
lay->walking_objects++;
EINA_INLIST_FOREACH(lay->objects, obj)
if (obj->proxy->surface)
{
if (obj->proxy->surface)
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
{
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy, Evas_Object_Proxy_Data, proxy_write)
{
ENFN->image_free(ENC, proxy_write->surface);
proxy_write->surface = NULL;
}
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
ENFN->image_free(ENC, proxy_write->surface);
proxy_write->surface = NULL;
}
if (obj->mask->surface)
{
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mdata)
{
ENFN->image_free(ENC, mdata->surface);
mdata->surface = NULL;
}
EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mdata);
}
if ((obj->type) && (!strcmp(obj->type, "image")))
evas_object_inform_call_image_unloaded(obj->object);
_evas_render_dump_map_surfaces(obj->object);
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write);
}
lay->walking_objects--;
_evas_layer_flush_removes(lay);
if (obj->mask->surface)
{
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mdata)
{
ENFN->image_free(ENC, mdata->surface);
mdata->surface = NULL;
}
EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mdata);
}
if ((obj->type) && (!strcmp(obj->type, "image")))
evas_object_inform_call_image_unloaded(obj->object);
_evas_render_dump_map_surfaces(obj->object);
}
if (ENFN && ENFN->output_dump)
{
Efl_Canvas_Output *output;
Eina_List *l;
lay->walking_objects--;
_evas_layer_flush_removes(lay);
}
if (ENFN && ENFN->output_dump)
{
Efl_Canvas_Output *output;
Eina_List *l;
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_dump(ENC, output->output);
}
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_dump(ENC, output->output);
}
#define GC_ALL(Cow) \
if (Cow) while (eina_cow_gc(Cow))
GC_ALL(evas_object_proxy_cow);
GC_ALL(evas_object_map_cow);
GC_ALL(evas_object_image_pixels_cow);
GC_ALL(evas_object_image_load_opts_cow);
GC_ALL(evas_object_image_state_cow);
if (Cow) while (eina_cow_gc(Cow))
GC_ALL(evas_object_proxy_cow);
GC_ALL(evas_object_map_cow);
GC_ALL(evas_object_image_pixels_cow);
GC_ALL(evas_object_image_load_opts_cow);
GC_ALL(evas_object_image_state_cow);
evas_fonts_zero_pressure();
evas_fonts_zero_pressure();
if (ENFN && ENFN->output_idle_flush)
{
Efl_Canvas_Output *output;
Eina_List *l;
if (ENFN && ENFN->output_idle_flush)
{
Efl_Canvas_Output *output;
Eina_List *l;
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_idle_flush(ENC, output->output);
}
eina_inarray_flush(&evas->active_objects);
OBJS_ARRAY_FLUSH(&evas->render_objects);
OBJS_ARRAY_FLUSH(&evas->restack_objects);
OBJS_ARRAY_FLUSH(&evas->delete_objects);
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
eina_array_clean(&evas->clip_changes);
evas->invalidate = EINA_TRUE;
evas_cache_async_thaw();
EINA_LIST_FOREACH(evas->outputs, l, output)
if (output->output)
ENFN->output_idle_flush(ENC, output->output);
}
eina_inarray_flush(&evas->active_objects);
OBJS_ARRAY_FLUSH(&evas->render_objects);
OBJS_ARRAY_FLUSH(&evas->restack_objects);
OBJS_ARRAY_FLUSH(&evas->delete_objects);
OBJS_ARRAY_FLUSH(&evas->obscuring_objects);
OBJS_ARRAY_FLUSH(&evas->temporary_objects);
eina_array_foreach(&evas->clip_changes, _evas_clip_changes_free, NULL);
eina_array_clean(&evas->clip_changes);
evas->invalidate = EINA_TRUE;
evas_cache_async_thaw();
}
void

View File

@ -1,149 +0,0 @@
#include "evas_render2.h"
#include <sys/time.h>
#include "region.c"
Eina_Bool evas_render2_use = EINA_FALSE;
#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 = (t * 100.0) / (1.0 / 60.0);
printf("%1.2f%% / 60fps\n", b);
}
static void
_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
{
int freeze_num = 0, i;
freeze_num = efl_event_freeze_count_get(eo_e);
for (i = 0; i < freeze_num; i++) efl_event_thaw(eo_e);
evas_event_callback_call(eo_e, type, event_info);
for (i = 0; i < freeze_num; i++) efl_event_freeze(eo_e);
}
// a list of canvases currently rendering
static Eina_List *_rendering = NULL;
// just put the thread code inlined here for now as opposed to separate files
#include "evas_render2_th_main.c"
// init all relevant render threads if needed
static void
_evas_render2_th_init(void)
{
static Eina_Bool initted = EINA_FALSE;
if (initted) return;
initted = EINA_TRUE;
_th_main_queue = eina_thread_queue_new();
if (!eina_thread_create(&_th_main, EINA_THREAD_URGENT, -1,
_evas_render2_th_main, NULL))
ERR("Cannot create render2 thread");
}
Eina_Bool
_evas_render2(Eo *eo_e, Evas_Public_Data *e)
{
double t;
// 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
if (e->rendering) return EINA_FALSE;
// mark this canvas as a render2 canvas - not normal render
e->render2 = EINA_TRUE;
evas_render2_use = EINA_TRUE;
// check viewport size is same as output - not allowed to differ
if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
ERR("viewport size != output size!");
// if render threads not initted - init them - maybe move this later?
_evas_render2_th_init();
printf("-------------------------------------------- %p %p\n", eo_e, e);
// wait for any previous render pass to do its thing
t = get_time();
evas_canvas_async_block(e);
t = get_time() - t;
printf("T: block wait: "); out_time(t);
// we have to calculate smare objects before render so do that here
t = get_time();
evas_call_smarts_calculate(eo_e);
t = get_time() - t;
printf("T: smart calc: "); out_time(t);
// call canvas callbacks saying we are in the pre-render state
_always_call(eo_e, EVAS_CALLBACK_RENDER_PRE, NULL);
// bock any susbequent rneders from doing this walk
eina_lock_take(&(e->lock_objects));
// gain a reference
efl_ref(eo_e);
// put into the "i'm rendering" pool
e->rendering = EINA_TRUE;
_rendering = eina_list_append(_rendering, eo_e);
// call our flush pre at this point before rendering begins...
_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
// tell main render thread to wake up and begin processing this canvas
_evas_render2_th_main_msg_render(eo_e, e);
return EINA_FALSE;
}
Eina_List *
_evas_render2_updates(Eo *eo_e, Evas_Public_Data *e)
{
if (!_evas_render2(eo_e, e)) return NULL;
return _evas_render2_updates_wait(eo_e, e);
}
Eina_List *
_evas_render2_updates_wait(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
{
evas_canvas_async_block(e);
while (e->rendering) evas_async_events_process_blocking();
return NULL;
}
void
_evas_norender2(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
{
evas_canvas_async_block(e);
}
void
_evas_render2_idle_flush(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
{
evas_canvas_async_block(e);
}
void
_evas_render2_sync(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
{
evas_canvas_async_block(e);
}
void
_evas_render2_dump(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
{
evas_canvas_async_block(e);
}

View File

@ -1,21 +0,0 @@
#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
#include "region.h"
Eina_Bool _evas_render2(Eo *eo_e, Evas_Public_Data *e);
Eina_List *_evas_render2_updates(Eo *eo_e, Evas_Public_Data *e);
Eina_List *_evas_render2_updates_wait(Eo *eo_e, Evas_Public_Data *e);
void _evas_norender2(Eo *eo_e, Evas_Public_Data *e);
void _evas_render2_idle_flush(Eo *eo_e, Evas_Public_Data *e);
void _evas_render2_sync(Eo *eo_e, Evas_Public_Data *e);
void _evas_render2_dump(Eo *eo_e, Evas_Public_Data *e);
#endif

View File

@ -1,481 +0,0 @@
#include "evas_render2.h"
//////////////////////////////////////////////////////////////////////////////
// this is the start of a rewrite of the evas rendering infra. first port of
// call is to just make it work and still support async rendering with no
// optimizations at all. once it WORKS properly start adding back
// optimizations one at a time very carefully until it is equivalent to where
// evas render was before, THEN... we can consider switching it on by default
// but until then it's off unless you set:
//
// export EVAS_RENDER2=1
//
// at runtime.
//////////////////////////////////////////////////////////////////////////////
// data types
//////////////////////////////////////////////////////////////////////////////
typedef struct _Update Update;
struct _Update
{
Eina_Rectangle *area;
void *surface;
};
typedef struct _Update_Info Update_Info;
struct _Update_Info
{
void *surface;
int ux, uy, uw, uh;
int cx, cy, cw, ch;
};
// funcs
//////////////////////////////////////////////////////////////////////////////
Eina_Bool _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_draw, Eina_Bool do_async);
void _evas_render2_idle_flush(Eo *eo_e);
void _evas_render2_dump(Eo *eo_e);
void _evas_render2_wait(Eo *eo_e);
static void _evas_render2_cow_gc(Eina_Cow *cow, int max);
static void _evas_render2_cow_all_gc(int max);
static void _evas_render2_all_sync(void);
static void _evas_render2_wakeup_cb(void *target, Evas_Callback_Type type, void *event_info);
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, 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, 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);
static void _evas_render2_end(Eo *eo_e);
// global data (for rendering only)
//////////////////////////////////////////////////////////////////////////////
static Eina_List *_rendering = NULL;
// actual helper/internal functions
//////////////////////////////////////////////////////////////////////////////
static void
_evas_render2_cow_gc(Eina_Cow *cow, int max)
{
// gc a single cow type up to max iter or if max <= 0, all of them
int i = 0;
while (eina_cow_gc(cow))
{
if (max < 1) continue;
i++;
if (i > max) break;
}
}
static void
_evas_render2_cow_all_gc(int max)
{
// gc all known cow types
_evas_render2_cow_gc(evas_object_proxy_cow, max);
_evas_render2_cow_gc(evas_object_map_cow, max);
_evas_render2_cow_gc(evas_object_image_pixels_cow, max);
_evas_render2_cow_gc(evas_object_image_load_opts_cow, max);
_evas_render2_cow_gc(evas_object_image_state_cow, max);
}
static void
_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);
}
static void
_evas_render2_wakeup_cb(void *target, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
{
// in mainloop run the rendering end handler
Eo *eo_e = target;
_evas_render2_end(eo_e);
}
static void
_evas_render2_wakeup_send(void *data)
{
// pass an event to the mainloop async event handler in evas so mainloop
// runs wakeup_cb and not in any thread
evas_async_events_put(data, 0, NULL, _evas_render2_wakeup_cb);
}
static void
_evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
{
int freeze_num = 0, i;
freeze_num = efl_event_freeze_count_get(eo_e);
for (i = 0; i < freeze_num; i++) efl_event_thaw(eo_e);
evas_event_callback_call(eo_e, type, event_info);
for (i = 0; i < freeze_num; i++) efl_event_freeze(eo_e);
}
static void
_evas_render2_updates_clean(Evas_Public_Data *e)
{
void *u;
// clean out updates and tmp surfaces we were holding/tracking
EINA_LIST_FREE(e->render.updates, u) eina_rectangle_free(u);
}
static void
_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_async)
{
Evas_Public_Data *e = efl_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
// XXX:
// 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);
}
// clear our previous rendering stuff from the engine
e->engine.func->output_redraws_clear(e->engine.data.output);
// stop tracking canvas as being async rendered
_rendering = eina_list_remove(_rendering, eo_e);
e->rendering = EINA_FALSE;
// call the post render callback with info if appropriate
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
if (!make_updates) _evas_render2_updates_clean(e);
// clean out modules we don't need anymore
evas_module_clean();
}
static void
_evas_render2_stage_explicit_updates(Evas_Public_Data *e)
{
Eina_Rectangle *r;
Eina_List *l;
// XXX: should time this
// if the output size changed, add a full redraw
if ((e->output.changed) || (e->framespace.changed))
{
e->engine.func->output_resize(e->engine.data.output,
e->output.w, e->output.h);
e->engine.func->output_redraws_rect_add(e->engine.data.output, 0, 0,
e->output.w, e->output.h);
}
// if there are explicit update regions - add them
EINA_LIST_FREE(e->damages, r)
{
// if we didnt just do a full redraw if output changed
if ((!e->output.changed) && (!e->framespace.changed))
e->engine.func->output_redraws_rect_add(e->engine.data.output,
r->x, r->y, r->w, r->h);
eina_rectangle_free(r);
}
// remove obscures from rendering - we keep them around
EINA_LIST_FOREACH(e->obscures, l, r)
evas_render_update_del(e, r->x, r->y, r->w, r->h);
}
static void
_evas_render2_stage_main_render_prepare(Evas_Public_Data *e)
{
// XXX:
// XXX: do any preparation work here that is needed for the render
// XXX: threads to do their work, but can't be done in a thread. this
// XXX: also includes doing the pose render and clear of change flag
// XXX:
printf("_evas_render2_stage_main_render_prepare %p\n", e);
}
static void
_evas_render2_object_render(Evas_Public_Data *e, Evas_Object_Protected_Data *obj, Update_Info *uinf, int l)
{
Evas_Object_Protected_Data *obj2;
Evas_Object *eo_obj = obj->object;
if ((!evas_object_is_visible(eo_obj, obj)) ||
(obj->clip.clipees) || (obj->cur->have_clipees)) return;
if (obj->is_smart)
{
EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), obj2)
_evas_render2_object_render(e, obj2, uinf, l + 1);
}
else
{
void *ctx = e->engine.func->context_new(e->engine.data.output);
if (ctx)
{
int offx = uinf->cx - uinf->ux;
int offy = uinf->cy - uinf->uy;
int x, y, w, h;
x = obj->cur->cache.clip.x;
y = obj->cur->cache.clip.y;
w = obj->cur->cache.clip.w;
h = obj->cur->cache.clip.h;
e->engine.func->context_clip_set(e->engine.data.output,
ctx, x + offx, y + offy, w, h);
obj->func->render(eo_obj, obj, obj->private_data,
e->engine.data.output,
ctx, uinf->surface,
offx, offy,
EINA_FALSE);
e->engine.func->context_free(e->engine.data.output, ctx);
}
}
}
static void
_evas_render2_stage_render_do(Evas_Public_Data *e, Eina_Bool do_async EINA_UNUSED)
{
Update_Info uinf;
Eina_Bool alpha;
// XXX: actually render now (either in thread or in mainloop)
// XXX:
printf(" _evas_render2_stage_render_do %p\n", e);
alpha = e->engine.func->canvas_alpha_get(e->engine.data.output);
while ((uinf.surface =
e->engine.func->output_redraws_next_update_get
(e->engine.data.output,
&uinf.ux, &uinf.uy, &uinf.uw, &uinf.uh,
&uinf.cx, &uinf.cy, &uinf.cw, &uinf.ch)))
{
Update *ru = NULL;
Evas_Layer *lay;
Evas_Object_Protected_Data *obj;
// if the canvas has an alpha channel, we must fill the region with
// empty (0 value argb)
if (alpha)
{
void *ctx = e->engine.func->context_new(e->engine.data.output);
if (ctx)
{
e->engine.func->context_render_op_set
(e->engine.data.output, ctx, EVAS_RENDER_COPY);
e->engine.func->context_color_set
(e->engine.data.output, ctx, 0, 0, 0, 0);
e->engine.func->rectangle_draw(e->engine.data.output,
ctx, uinf.surface,
uinf.cx, uinf.cy,
uinf.cw, uinf.ch,
EINA_FALSE);
e->engine.func->context_free(e->engine.data.output, ctx);
}
}
EINA_INLIST_FOREACH(e->layers, lay)
{
EINA_INLIST_FOREACH(lay->objects, obj)
{
_evas_render2_object_render(e, obj, &uinf, 0);
}
}
ru = malloc(sizeof(*ru));
ru->surface = uinf.surface;
NEW_RECT(ru->area, uinf.ux, uinf.uy, uinf.uw, uinf.uh);
e->render.updates = eina_list_append(e->render.updates, ru);
evas_cache_image_ref(uinf.surface);
}
e->engine.func->output_redraws_clear(e->engine.data.output);
}
static void
_evas_render2_stage_reset(Evas_Public_Data *e)
{
// cleanup canvas state after a render
e->changed = EINA_FALSE;
e->viewport.changed = EINA_FALSE;
e->output.changed = EINA_FALSE;
e->framespace.changed = EINA_FALSE;
e->invalidate = EINA_FALSE;
}
static void
_evas_render2_stage_object_cleanup(Evas_Public_Data *e)
{
// cleanup objects no longer needed now they have been scanned
// XXX:
// XXX: delete objects no longer needed here
// XXX:
printf("_evas_render2_stage_object_cleanup %p\n", e);
}
static void
_evas_render2_th_render(void *data)
{
Evas_Public_Data *e = data;
printf(".....................................................%p\n", e);
_evas_render2_stage_render_do(e, EINA_TRUE);
printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%p\n", e);
}
// major functions (called from evas_render.c)
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// BEGIN RENDERING (in mainloop)
///////////////////////////////////////////////////////////////////////
Eina_Bool
_evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
Eina_Bool do_draw, Eina_Bool do_async)
{
Evas_Public_Data *e = efl_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
if (e->rendering && do_async) return EINA_FALSE;
// check viewport size is same as output - not allowed to differ
if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
ERR("viewport size != output size!");
// we have to calculate smare objects before render so do that here
evas_call_smarts_calculate(eo_e);
// call canvas callbacks saying we are in the pre-render state
_evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_PRE, NULL);
// begin out actual rendering bits
_evas_render2_stage_generate_object_updates(e);
_evas_render2_stage_explicit_updates(e);
// we are actually asked to draw not just go through the motions for gc
if (do_draw)
{
// now go through any preparation that needs doing in the mainloop
_evas_render2_stage_main_render_prepare(e);
// send off rendering to primary thread renderer
if (do_async)
{
// ref the canvas so it stays while threads work
efl_ref(eo_e);
// track canvas in list of things going in the background
e->rendering = EINA_TRUE;
_rendering = eina_list_append(_rendering, eo_e);
// queue the render thread command
evas_thread_cmd_enqueue(_evas_render2_th_render, e);
// flush the thread queue and call wakeup_send in the thread
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, 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, EINA_FALSE);
if (!do_draw) _evas_render2_updates_clean(e);
evas_module_clean();
return EINA_TRUE;
}
///////////////////////////////////////////////////////////////////////
// END RENDERING (in mainloop)
///////////////////////////////////////////////////////////////////////
static void
_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, EINA_TRUE);
// release canvas object ref
efl_unref(eo_e);
}
///////////////////////////////////////////////////////////////////////
// IDLE FLUSH (in mainloop)
///////////////////////////////////////////////////////////////////////
void
_evas_render2_idle_flush(Eo *eo_e)
{
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
// wait for rendering to finish so we don't mess up shared resources
_evas_render2_wait(eo_e);
// clean fonts
evas_fonts_zero_pressure();
// call engine idle flush call
if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
(e->engine.data.output))
e->engine.func->output_idle_flush(e->engine.data.output);
// mark as invalidated
e->invalidate = EINA_TRUE;
// garbage collect up to 500 cow segments from our cow types
// not e that we should probably expose a call to do this outside of evas
// so ecore evas can call it in an idler
_evas_render2_cow_all_gc(500);
}
///////////////////////////////////////////////////////////////////////
// DUMP DATA (in mainloop)
///////////////////////////////////////////////////////////////////////
void
_evas_render2_dump(Eo *eo_e)
{
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
// freeze core cache system async work
evas_cache_async_freeze();
// wait for all canvases to render as they may share data we are dumping
_evas_render2_all_sync();
// go through idle flush first
_evas_render2_idle_flush(eo_e);
// also now tell engine to dump too
if ((e->engine.func) && (e->engine.func->output_dump) &&
(e->engine.data.output))
e->engine.func->output_dump(e->engine.data.output);
// clean up all cow sections no matter how many
_evas_render2_cow_all_gc(0);
// unfreeze core cache system
evas_cache_async_thaw();
}
///////////////////////////////////////////////////////////////////////
// WAIT ON CANVAS RENDER (if async, in mainloop)
///////////////////////////////////////////////////////////////////////
void
_evas_render2_wait(Eo *eo_e)
{
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
while (e->rendering) evas_async_events_process_blocking();
}

View File

@ -1,43 +0,0 @@
#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

@ -1,329 +0,0 @@
//#define DBG_OBJTREE 1
#define OBJ_ARRAY_PUSH(array, obj) \
do \
{ \
eina_array_push(array, obj); \
efl_data_ref(obj->object, EFL_CANVAS_OBJECT_CLASS); \
} while (0)
#define OBJS_ARRAY_CLEAN(array) \
do \
{ \
Evas_Object_Protected_Data *item; \
Eina_Array_Iterator iterator; \
unsigned int idx; \
EINA_ARRAY_ITER_NEXT(array, idx, item, iterator) \
efl_data_unref(item->object, item); \
eina_array_clean(array); \
} while (0)
typedef struct _Msg_Main_Render Msg_Main_Render;
typedef struct _Render2_Finish_Data Render2_Finish_Data;
struct _Msg_Main_Render
{
Eina_Thread_Queue_Msg head;
Eo *eo_e;
Evas_Public_Data *e;
};
struct _Render2_Finish_Data
{
Eo *eo_e;
Evas_Public_Data *e;
Eina_List *updates;
};
static Eina_Thread_Queue *_th_main_queue = NULL;
static Eina_Thread _th_main;
#ifdef DBG_OBJTREE
static void
indent(int l)
{
int i; for (i = 0; i < l; i++) printf(" ");
}
#endif
static void
_evas_render2_th_main_delete_objects_clean(Evas_Public_Data *e)
{
Evas_Object_Protected_Data *obj;
unsigned int i;
double t;
// cleanup deferred object deletion
t = get_time();
for (i = 0; i < e->delete_objects.count; ++i)
{
obj = eina_array_data_get(&e->delete_objects, i);
evas_object_free(obj, 1);
}
// OBJS_ARRAY_CLEAN(&e->delete_objects);
eina_array_clean(&e->delete_objects);
t = get_time() - t;
printf("T: object deletion: "); out_time(t);
}
static void
_evas_render2_th_main_mainloop_done(void *data, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
{
Render2_Finish_Data *render_finish_data = data;
Evas_Event_Render_Post post;
Eo *eo_e;
Evas_Public_Data *e;
Eina_Rectangle *rect;
e = render_finish_data->e;
eo_e = render_finish_data->eo_e;
// call the flush post callbacks
_always_call(render_finish_data->eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
// and now call the actual render post callbacks with updates list
post.updated_area = render_finish_data->updates;
_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
EINA_LIST_FREE(render_finish_data->updates, rect) free(rect);
free(render_finish_data);
_evas_render2_th_main_delete_objects_clean(e);
}
static Eina_Bool
_evas_render2_th_main_obj_del_handle(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj)
{
if (obj->delete_me == 2)
{
OBJ_ARRAY_PUSH(&e->delete_objects, obj);
obj->delete_me++;
return EINA_FALSE;
}
else if (obj->delete_me != 0) obj->delete_me++;
return EINA_TRUE;
}
static void
_evas_render2_th_main_obj_basic_walk_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj,
void *updates,
int offx,
int offy,
int l EINA_UNUSED)
{
Evas_Object *eo_obj = obj->object;
if (!_evas_render2_th_main_obj_del_handle(e, obj)) return;
evas_object_clip_recalc(obj);
#ifdef DBG_OBJTREE
indent(l); printf("BASIC %p %p [%10s]\n", e, eo_obj, obj->type);
#endif
if (obj->func->render2_walk)
obj->func->render2_walk(eo_obj, obj, obj->private_data,
updates, offx, offy);
if (obj->changed)
{
evas_object_clip_changes_clean(obj);
evas_object_cur_prev(obj);
evas_object_change_reset(obj);
}
}
static void
_evas_render2_th_main_obj_walk_process(Evas_Public_Data *e,
Evas_Object_Protected_Data *obj,
void *updates,
int offx,
int offy,
int l EINA_UNUSED)
{
// process object OR walk through child objects if smart and process those
Evas_Object_Protected_Data *obj2;
Evas_Object *eo_obj = obj->object;
const Eina_Inlist *il;
il = obj->is_smart ? evas_object_smart_members_get_direct(eo_obj) : NULL;
if (il)
{
if (!_evas_render2_th_main_obj_del_handle(e, obj)) return;
evas_object_clip_recalc(obj);
#ifdef DBG_OBJTREE
indent(l); printf("SMART %p %p [%10s] ch %i\n", e, eo_obj, obj->type, obj->changed);
#endif
if (obj->func->render2_walk)
obj->func->render2_walk(eo_obj, obj, obj->private_data,
updates, offx, offy);
EINA_INLIST_FOREACH(il, obj2)
_evas_render2_th_main_obj_walk_process(e, obj2, updates,
offx, offy, l + 1);
if (obj->changed)
{
evas_object_clip_changes_clean(obj);
evas_object_cur_prev(obj);
evas_object_change_reset(obj);
}
}
else _evas_render2_th_main_obj_basic_walk_process(e, obj, updates,
offx, offy, l);
}
static Region *
_evas_render2_regions_merge(Region *region)
{
Region *region2;
Box *rects;
int num, i, w, h;
int tsize = 16;
region_size_get(region, &w, &h);
region2 = region_new(w, h);
rects = region_rects(region);
num = region_rects_num(region);
for (i = 0; i < num; i++)
{
int x1, y1, x2, y2;
x1 = (rects[i].x1 / tsize) * tsize;
y1 = (rects[i].y1 / tsize) * tsize;
x2 = ((rects[i].x2 + tsize - 1) / tsize) * tsize;
y2 = ((rects[i].y2 + tsize - 1) / tsize) * tsize;
region_rect_add(region2, x1, y1, x2 - x1, y2 - y1);
}
region_free(region);
return region2;
}
static void
_evas_render2_th_main_do(Eo *eo_e, Evas_Public_Data *e)
{
Render2_Finish_Data *render_finish_data;
Evas_Layer *lay;
Evas_Object_Protected_Data *obj;
Eina_List *updates_list = NULL, *l;
double t;
Eina_Rectangle *rect;
Region *updates;
Box *rects;
int rects_num, i;
static int num = 0;
updates = region_new(e->output.w, e->output.h);
printf("........... updates # %i\n", num++);
t = get_time();
EINA_INLIST_FOREACH(e->layers, lay)
{
EINA_INLIST_FOREACH(lay->objects, obj)
{
_evas_render2_th_main_obj_walk_process(e, obj,
updates, 0, 0,
0);
}
}
// add explicitly exposed/damaged regions of the canvas
EINA_LIST_FREE(e->damages, rect)
{
region_rect_add(updates, rect->x, rect->y, rect->w, rect->h);
eina_rectangle_free(rect);
}
// build obscure objects list of active objects that obscure
EINA_LIST_FOREACH(e->obscures, l, rect)
{
region_rect_del(updates, rect->x, rect->y, rect->w, rect->h);
}
t = get_time() - t;
printf("T: update generation: "); out_time(t);
t = get_time();
updates = _evas_render2_regions_merge(updates);
rects = region_rects(updates);
rects_num = region_rects_num(updates);
for (i = 0; i < rects_num; i++)
{
rect = malloc(sizeof(Eina_Rectangle));
if (rect)
{
if (rects[i].x2 > e->output.w) rects[i].x2 = e->output.w;
if (rects[i].y2 > e->output.h) rects[i].y2 = e->output.h;
rect->x = rects[i].x1;
rect->y = rects[i].y1;
rect->w = rects[i].x2 - rects[i].x1;
rect->h = rects[i].y2 - rects[i].y1;
printf(" Render Region [ %4i %4i %4ix%4i ]\n",
rect->x, rect->y, rect->w, rect->h);
updates_list = eina_list_append(updates_list, rect);
}
}
t = get_time() - t;
printf("T: merge updates: "); out_time(t);
// ... now render every update region
EINA_LIST_FOREACH(updates_list, l, rect)
{
// XXX: create update buffer
EINA_INLIST_FOREACH(e->layers, lay)
{
EINA_INLIST_FOREACH(lay->objects, obj)
{
// render to update buffer
// _evas_render2_th_main_obj_render_process(e, obj,
// updates, 0, 0,
// 0);
}
}
// delete update buffer
}
// free up updates we don't need anymore
region_free(updates);
e->changed = EINA_FALSE;
// remove from the "i'm rendering" pool - do back in mainloop
e->rendering = EINA_FALSE;
_rendering = eina_list_remove(_rendering, eo_e);
// unblock mainlopp that may be waiting on the render thread
eina_lock_release(&(e->lock_objects));
// send back
render_finish_data = calloc(1, sizeof(Render2_Finish_Data));
if (render_finish_data)
{
render_finish_data->eo_e = eo_e;
render_finish_data->e = e;
render_finish_data->updates = updates_list;
evas_async_events_put(render_finish_data, 0, NULL,
_evas_render2_th_main_mainloop_done);
}
else
{
EINA_LIST_FREE(updates_list, rect) free(rect);
}
efl_unref(eo_e);
}
static void *
_evas_render2_th_main(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
{
void *ref = NULL;
Msg_Main_Render *msg;
eina_thread_name_set(eina_thread_self(), "Eevas-render2");
for (;;)
{
msg = eina_thread_queue_wait(_th_main_queue, &ref);
if (msg)
_evas_render2_th_main_do(msg->eo_e, msg->e);
eina_thread_queue_wait_done(_th_main_queue, ref);
}
return NULL;
}
static void
_evas_render2_th_main_msg_render(Eo *eo_e, Evas_Public_Data *e)
{
void *ref;
Msg_Main_Render *msg =
eina_thread_queue_send(_th_main_queue, sizeof(Msg_Main_Render), &ref);
msg->eo_e = eo_e;
msg->e = e;
eina_thread_queue_send_done(_th_main_queue, ref);
}

View File

@ -1,78 +0,0 @@
#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 [%10s]\n", e, eo_obj, obj->type);
obj->func->render_post(eo_obj, obj, obj->private_data);
obj->restack = EINA_FALSE;
obj->pre_render_done = EINA_FALSE;
evas_object_change_reset(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;
const Eina_Inlist *il;
if (!obj->changed) return;
il = obj->is_smart ? evas_object_smart_members_get_direct(eo_obj) : NULL;
if (il)
{
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 [%10s] ch %i\n", e, eo_obj, obj->type, obj->changed);
EINA_INLIST_FOREACH(il, 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(obj);
}
else _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;
static int num = 0;
printf("........... updates # %i\n", num++);
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);
}

View File

@ -51,7 +51,8 @@ SOFTWARE.
#include <string.h>
#include "region.h"
#include "Eina.h"
#include "evas_macros.h"
typedef struct _Region_Data Region_Data;
typedef Eina_Bool (*Overlap_Func) (Region *region, Box *r1, Box *r1end, Box *r2, Box *r2end, int y1, int y2, Eina_Bool *overlap_ret);

View File

@ -52,7 +52,7 @@ SOFTWARE.
/* pixregion.h */
////////////////////////////////////////////////////////////////////////////
#include "Eina.h"
typedef struct _Region Region;
typedef struct _Box Box;

View File

@ -291,12 +291,9 @@ evas_object_clip_dirty(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Da
evas_object_clip_dirty_do(obj);
}
extern Eina_Bool evas_render2_use;
static inline void
evas_object_async_block(Evas_Object_Protected_Data *obj)
{
if (!evas_render2_use) return ;
if (EVAS_OBJECT_DATA_VALID(obj))
{
eina_lock_take(&(obj->layer->evas->lock_objects));
@ -307,7 +304,6 @@ evas_object_async_block(Evas_Object_Protected_Data *obj)
static inline void
evas_canvas_async_block(Evas_Public_Data *e)
{
if (!evas_render2_use) return ;
if (e)
{
eina_lock_take(&(e->lock_objects));

View File

@ -906,7 +906,6 @@ struct _Evas_Public_Data
unsigned char cleanup : 1;
Eina_Bool is_frozen : 1;
Eina_Bool rendering : 1;
Eina_Bool render2 : 1;
Eina_Bool inside_post_render : 1;
Eina_Bool devices_modified : 1;
};
@ -1276,15 +1275,6 @@ struct _Evas_Object_Func
// preparation - may include rendering content to buffer or loading data
// from disk or uploading to texture etc.
void (*render_prepare) (Evas_Object *obj, Evas_Object_Protected_Data *pd, Eina_Bool do_async);
// new render2 functions
void (*render2_walk) (Evas_Object *obj, Evas_Object_Protected_Data *pd,
void *type_private_data, void *updates,
int offx, int offy);
// void (*render2) (Evas_Object *obj, Evas_Object_Protected_Data *pd,
// void *type_private_data, void *output, void *context,
// void *surface, int x, int y);
};
struct _Evas_Func

View File

@ -767,7 +767,6 @@ _ecore_evas_x_render(Ecore_Evas *ee)
{
int rend = 0;
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
static int render2 = -1;
if ((!ee->no_comp_sync) && (_ecore_evas_app_comp_sync) &&
(edata->sync_counter) && (!edata->sync_began) &&
@ -782,42 +781,20 @@ _ecore_evas_x_render(Ecore_Evas *ee)
rend = ecore_evas_render_prepare(ee);
if (render2 == -1)
if (!ee->can_async_render)
{
if (getenv("RENDER2")) render2 = 1;
else render2 = 0;
Eina_List *updates = evas_render_updates(ee->evas);
rend = _render_updates_process(ee, updates);
evas_render_updates_free(updates);
}
if (render2)
else if (evas_render_async(ee->evas))
{
if (!ee->can_async_render)
{
Eina_List *updates = evas_render2_updates(ee->evas);
rend = _render_updates_process(ee, updates);
evas_render_updates_free(updates);
}
else
{
ee->in_async_render = EINA_TRUE;
if (evas_render2(ee->evas)) rend = 1;
else ee->in_async_render = EINA_FALSE;
}
}
else
{
if (!ee->can_async_render)
{
Eina_List *updates = evas_render_updates(ee->evas);
rend = _render_updates_process(ee, updates);
evas_render_updates_free(updates);
}
else if (evas_render_async(ee->evas))
{
EDBG("ee=%p started asynchronous render.", ee);
ee->in_async_render = EINA_TRUE;
rend = 1;
}
else if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
EDBG("ee=%p started asynchronous render.", ee);
ee->in_async_render = EINA_TRUE;
rend = 1;
}
else if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
return rend;
}