From afea9e94bb99e0c342c3ba46bd0e281937702b4f Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Sat, 27 Sep 2014 12:55:03 +0200 Subject: evas: add logic to do limit output tile to fit in L1 cache. This code is not turned on by default at the moment as it expose the cost of walking over and over again Evas_Object stack. We need to seriously optimize this or maybe i should do it another way. Instead we could replay the command list in the asynchronous pipe by adding cliping and replay as many time as needed. Worth exploring that option to. --- .../Evas_Engine_Software_Generic.h | 4 ++ .../evas/engines/software_generic/evas_engine.c | 77 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h b/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h index 8369f02178..66566c1592 100644 --- a/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h +++ b/src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h @@ -80,6 +80,7 @@ struct _Render_Engine_Software_Generic unsigned char end : 1; unsigned char lost_back : 1; unsigned char tile_strict : 1; + unsigned char tiling : 1; }; static inline Eina_Bool @@ -124,6 +125,9 @@ evas_render_engine_software_generic_init(Render_Engine_Software_Generic *re, re->lost_back = 0; re->tile_strict = 0; + if (getenv("EVAS_TILING_ENABLE")) + re->tiling = 1; + re->tb = evas_common_tilebuf_new(w, h); if (!re->tb) return EINA_FALSE; diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index a2f60213c6..610051c715 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -2701,6 +2701,37 @@ _merge_rects(Render_Engine_Merge_Mode merge_mode, return rects; } +static inline Tilebuf_Rect * +_split_rect_horizontaly(Tilebuf_Rect *it) +{ + Tilebuf_Rect *tmp; + + tmp = calloc(1, sizeof(Tilebuf_Rect)); + if (!tmp) return NULL; + tmp->x = it->x + it->w / 2; + tmp->w = it->w / 2 + it->w % 2; + tmp->y = it->y; + tmp->h = it->h; + it->w = it->w / 2; + + return tmp; +} + +static inline Tilebuf_Rect * +_split_rect_verticaly(Tilebuf_Rect *it) +{ + Tilebuf_Rect *tmp; + + tmp = calloc(1, sizeof(Tilebuf_Rect)); + if (!tmp) return NULL; + tmp->y = it->y + it->h / 2; + tmp->h = it->h / 2 + it->h % 2; + tmp->x = it->x; + tmp->w = it->w; + it->h = it->h / 2; + + return tmp; +} static void * eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) @@ -2775,6 +2806,52 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i } evas_common_tilebuf_clear(re->tb); re->cur_rect = EINA_INLIST_GET(re->rects); + + if (re->tiling) + { + /* We will limit each rect to be fiting inside 16KB */ + Tilebuf_Rect *it; + + EINA_INLIST_FOREACH(re->cur_rect, it) + { + while ((it->w * it->h * sizeof (int)) > (16 * 1024)) + { + Tilebuf_Rect *tmp; + + /* Split the largest side first */ + if (it->w > it->h) + { + /* Let's try to divide it horizontaly */ + tmp = _split_rect_horizontaly(it); + if (!tmp) break; + re->cur_rect = eina_inlist_append(re->cur_rect, EINA_INLIST_GET(tmp)); + + if ((it->w * it->h * sizeof (int)) <= (16 * 1024)) + break; + + /* Let's try to divide it verticaly */ + tmp = _split_rect_verticaly(it); + if (!tmp) break; + re->cur_rect = eina_inlist_append(re->cur_rect, EINA_INLIST_GET(tmp)); + } + else + { + /* Let's try to divide it verticaly */ + tmp = _split_rect_verticaly(it); + if (!tmp) break; + re->cur_rect = eina_inlist_append(re->cur_rect, EINA_INLIST_GET(tmp)); + + if ((it->w * it->h * sizeof (int)) <= (16 * 1024)) + break; + + /* Let's try to divide it horizontaly */ + tmp = _split_rect_horizontaly(it); + if (!tmp) break; + re->cur_rect = eina_inlist_append(re->cur_rect, EINA_INLIST_GET(tmp)); + } + } + } + } } if (!re->cur_rect) return NULL; rect = (Tilebuf_Rect *)re->cur_rect; -- cgit v1.2.1