summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2014-09-27 12:55:03 +0200
committerCedric BAIL <cedric@osg.samsung.com>2014-09-27 12:55:03 +0200
commitafea9e94bb99e0c342c3ba46bd0e281937702b4f (patch)
tree36d4c4168d803f3f10bdb4252f1acf626db6d316
parentfc40591f1195da03766e0e97f3a6559648c80824 (diff)
downloadefl-devs/cedric/evas_tiling.tar.gz
evas: add logic to do limit output tile to fit in L1 cache.devs/cedric/evas_tiling
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.
-rw-r--r--src/modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h4
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c77
2 files changed, 81 insertions, 0 deletions
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;