raster pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=5801013ad4be24baf55e88dcd8cefd89ac57f5e6
commit 5801013ad4be24baf55e88dcd8cefd89ac57f5e6 Author: Carsten Haitzler (Rasterman) <[email protected]> Date: Mon Oct 5 18:41:00 2015 +0900 evas - region updates - go back to tiler as its faster the overhead didnt show up in y tests. do show up with certain expedite tests. hmmm. last time i messed with region code it was actually same speed as tiler. bonus was it was fully accurate. --- src/lib/evas/common/evas_tiler.c | 914 +++++++++++++++++++++++++++++ src/lib/evas/include/evas_common_private.h | 62 +- 2 files changed, 974 insertions(+), 2 deletions(-) diff --git a/src/lib/evas/common/evas_tiler.c b/src/lib/evas/common/evas_tiler.c index d645d52..0aff533 100644 --- a/src/lib/evas/common/evas_tiler.c +++ b/src/lib/evas/common/evas_tiler.c @@ -1,6 +1,8 @@ #include "evas_common_private.h" #include "region.h" + +#ifdef NEWTILER EAPI void evas_common_tilebuf_init(void) { @@ -147,3 +149,915 @@ evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects) { free(rects); } + +#else + +#define FUZZ 32 +#define MAXREG 24 +#define MAX_NODES 1024 + +static inline void rect_list_node_pool_flush(void); +static inline list_node_t *rect_list_node_pool_get(void); +static inline void rect_list_node_pool_put(list_node_t *node); +static inline void rect_init(rect_t *r, int x, int y, int w, int h); +static inline void rect_list_append_node(list_t *rects, list_node_t *node); +static inline void rect_list_append(list_t *rects, const rect_t r); +static inline void rect_list_append_xywh(list_t *rects, int x, int y, int w, int h); +static inline void rect_list_concat(list_t *rects, list_t *other); +static inline list_node_t *rect_list_unlink_next(list_t *rects, list_node_t *parent_node); +static inline void rect_list_del_next(list_t *rects, list_node_t *parent_node); +static inline void rect_list_clear(list_t *rects); +static inline void rect_list_del_split_strict(list_t *rects, const rect_t del_r); +static inline list_node_t *rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error); +static inline void rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error); +static inline void rect_list_add_split_fuzzy_and_merge(list_t *rects, list_node_t *node, int split_accepted_error, int merge_accepted_error); + +static const list_node_t list_node_zeroed = { NULL }; +static const list_t list_zeroed = { NULL, NULL }; + +typedef struct list_node_pool +{ + list_node_t *node; + int len; + int max; +} list_node_pool_t; + +static list_node_pool_t list_node_pool = { NULL, 0, MAX_NODES }; + +static inline void +rect_list_node_pool_flush(void) +{ + while (list_node_pool.node) + { + list_node_t *node = list_node_pool.node; + list_node_pool.node = node->next; + list_node_pool.len--; + free(node); + } +} + +static inline list_node_t * +rect_list_node_pool_get(void) +{ + if (list_node_pool.node) + { + list_node_t *node = list_node_pool.node; + list_node_pool.node = node->next; + list_node_pool.len--; + return node; + } + else return (list_node_t *)malloc(sizeof(rect_node_t)); +} + +static inline void +rect_list_node_pool_put(list_node_t *node) +{ + if (list_node_pool.len < list_node_pool.max) + { + node->next = list_node_pool.node; + list_node_pool.node = node; + list_node_pool.len++; + } + else free(node); +} + +static inline void +rect_init(rect_t *r, int x, int y, int w, int h) +{ + r->area = w * h; + r->left = x; + r->top = y; + r->right = x + w; + r->bottom = y + h; + r->width = w; + r->height = h; +} + +static inline void +rect_list_append_node(list_t *rects, list_node_t *node) +{ + if (rects->tail) + { + rects->tail->next = node; + rects->tail = node; + } + else + { + rects->head = node; + rects->tail = node; + } +} + +static inline void +rect_list_append(list_t *rects, const rect_t r) +{ + rect_node_t *rect_node = (rect_node_t *)rect_list_node_pool_get(); + rect_node->rect = r; + rect_node->_lst = list_node_zeroed; + rect_list_append_node(rects, (list_node_t *)rect_node); +} + +static inline void +rect_list_append_xywh(list_t *rects, int x, int y, int w, int h) +{ + rect_t r; + rect_init(&r, x, y, w, h); + rect_list_append(rects, r); +} + +static inline void +rect_list_concat(list_t *rects, list_t *other) +{ + if (!other->head) return; + if (rects->tail) + { + rects->tail->next = other->head; + rects->tail = other->tail; + } + else + { + rects->head = other->head; + rects->tail = other->tail; + } + *other = list_zeroed; +} + +static inline list_node_t * +rect_list_unlink_next(list_t *rects, list_node_t *parent_node) +{ + list_node_t *node; + + if (parent_node) + { + node = parent_node->next; + parent_node->next = node->next; + } + else + { + node = rects->head; + rects->head = node->next; + } + if (rects->tail == node) rects->tail = parent_node; + *node = list_node_zeroed; + return node; +} + +static inline void +rect_list_del_next(list_t *rects, list_node_t *parent_node) +{ + list_node_t *node = rect_list_unlink_next(rects, parent_node); + rect_list_node_pool_put(node); +} + +static inline void +rect_list_clear(list_t *rects) +{ + list_node_t *node = rects->head; + while (node) + { + list_node_t *aux; + + aux = node->next; + rect_list_node_pool_put(node); + node = aux; + } + *rects = list_zeroed; +} + +static inline void +_calc_intra_rect_area(const rect_t a, const rect_t b, int *width, int *height) +{ + int max_left, min_right, max_top, min_bottom; + + if (a.left < b.left) max_left = b.left; + else max_left = a.left; + if (a.right < b.right) min_right = a.right; + else min_right = b.right; + *width = min_right - max_left; + + if (a.top < b.top) max_top = b.top; + else max_top = a.top; + if (a.bottom < b.bottom) min_bottom = a.bottom; + else min_bottom = b.bottom; + *height = min_bottom - max_top; +} + +static inline void +_split_strict(list_t *dirty, const rect_t current, rect_t r) +{ + int h_1, h_2, w_1, w_2; + + h_1 = current.top - r.top; + h_2 = r.bottom - current.bottom; + w_1 = current.left - r.left; + w_2 = r.right - current.right; + if (h_1 > 0) + { + /* .--.r (b) .---.r2 + * | | | | + * .-------.cur (a) .---.r '---' + * | | | | -> | | + + * | `--' | `---' + * `-------' + */ + rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1); + r.height -= h_1; + r.top = current.top; + } + if (h_2 > 0) + { + /* .-------.cur (a) + * | .---. | .---.r + * | | | | -> | | + * `-------' `---' + .---.r2 + * | | | | + * `---'r (b) `---' + */ + rect_list_append_xywh(dirty, r.left, current.bottom, r.width, h_2); + r.height -= h_2; + } + if (w_1 > 0) + { + /* (b) r .----.cur (a) + * .--|-. | .--.r2 .-.r + * | | | | -> | | + | | + * `--|-' | `--' `-' + * `----' + */ + rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height); + /* not necessary to keep these, r (b) will be destroyed */ + /* r.width -= w_1; */ + /* r.left = current.left; */ + } + if (w_2 > 0) + { + /* .----.cur (a) + * | | + * | .-|--.r (b) .-.r .--.r2 + * | | | | -> | | + | | + * | `-|--' `-' `--' + * `----' + */ + rect_list_append_xywh(dirty, current.right, r.top, w_2, r.height); + /* not necessary to keep this, r (b) will be destroyed */ + /* r.width -= w_2; */ + } +} + +static inline void +rect_list_del_split_strict(list_t *rects, const rect_t del_r) +{ + list_t modified = list_zeroed; + list_node_t *cur_node, *prev_node; + int intra_width, intra_height; + rect_t current; + + prev_node = NULL; + cur_node = rects->head; + while (cur_node) + { + current = ((rect_node_t*)cur_node)->rect; + _calc_intra_rect_area(del_r, current, &intra_width, &intra_height); + if ((intra_width <= 0) || (intra_height <= 0)) + { + /* .---.current .---.del_r + * | | | | + * `---+---.del_r `---+---.current + * | | | | + * `---' `---' + * no interception, nothing to do + */ + prev_node = cur_node; + cur_node = cur_node->next; + } + else if ((intra_width == current.width) && + (intra_height == current.height)) + { + /* .-------.del_r + * | .---. | + * | | | | + * | `---'current + * `-------' + * current is contained, remove from rects + */ + cur_node = cur_node->next; + rect_list_del_next(rects, prev_node); + } + else + { + _split_strict(&modified, del_r, current); + cur_node = cur_node->next; + rect_list_del_next(rects, prev_node); + } + } + + rect_list_concat(rects, &modified); +} + +static inline void +_calc_intra_outer_rect_area(const rect_t a, const rect_t b, + rect_t *intra, rect_t *outer) +{ + int min_left, max_left, min_right, max_right; + int min_top, max_top, min_bottom, max_bottom; + + if (a.left < b.left) + { + max_left = b.left; + min_left = a.left; + } + else + { + max_left = a.left; + min_left = b.left; + } + if (a.right < b.right) + { + min_right = a.right; + max_right = b.right; + } + else + { + min_right = b.right; + max_right = a.right; + } + intra->left = max_left; + intra->right = min_right; + intra->width = min_right - max_left; + outer->left = min_left; + outer->right = max_right; + outer->width = max_right - min_left; + if (a.top < b.top) + { + max_top = b.top; + min_top = a.top; + } + else + { + max_top = a.top; + min_top = b.top; + } + if (a.bottom < b.bottom) + { + min_bottom = a.bottom; + max_bottom = b.bottom; + } + else + { + min_bottom = b.bottom; + max_bottom = a.bottom; + } + intra->top = max_top; + intra->bottom = min_bottom; + intra->height = min_bottom - max_top; + if ((intra->width > 0) && (intra->height > 0)) + intra->area = intra->width * intra->height; + else + intra->area = 0; + outer->top = min_top; + outer->bottom = max_bottom; + outer->height = max_bottom - min_top; + outer->area = outer->width * outer->height; +} + +enum +{ + SPLIT_FUZZY_ACTION_NONE, + SPLIT_FUZZY_ACTION_SPLIT, + SPLIT_FUZZY_ACTION_MERGE +}; + +static inline int +_split_fuzzy(list_t *dirty, const rect_t a, rect_t *b) +{ + int h_1, h_2, w_1, w_2, action; + + h_1 = a.top - b->top; + h_2 = b->bottom - a.bottom; + w_1 = a.left - b->left; + w_2 = b->right - a.right; + + action = SPLIT_FUZZY_ACTION_NONE; + if (h_1 > 0) + { + /* .--.r (b) .---.r2 + * | | | | + * .-------.cur (a) .---.r '---' + * | | | | -> | | + + * | `--' | `---' + * `-------' + */ + rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1); + b->height -= h_1; + b->top = a.top; + action = SPLIT_FUZZY_ACTION_SPLIT; + } + if (h_2 > 0) + { + /* .-------.cur (a) + * | .---. | .---.r + * | | | | -> | | + * `-------' `---' + .---.r2 + * | | | | + * `---'r (b) `---' + */ + rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2); + b->height -= h_2; + action = SPLIT_FUZZY_ACTION_SPLIT; + } + if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height)) + return SPLIT_FUZZY_ACTION_MERGE; + if (w_1 > 0) + { + /* (b) r .----.cur (a) + * .--|-. | .--.r2 .-.r + * | | | | -> | | + | | + * `--|-' | `--' `-' + * `----' + */ + rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height); + /* not necessary to keep these, r (b) will be destroyed */ + /* b->width -= w_1; */ + /* b->left = a.left; */ + action = SPLIT_FUZZY_ACTION_SPLIT; + } + if (w_2 > 0) + { + /* .----.cur (a) + * | | + * | .-|--.r (b) .-.r .--.r2 + * | | | | -> | | + | | + * | `-|--' `-' `--' + * `----' + */ + rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height); + /* not necessary to keep these, r (b) will be destroyed */ + /* b->width -= w_2; */ + action = SPLIT_FUZZY_ACTION_SPLIT; + } + return action; +} + +static inline list_node_t * +rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error) +{ + list_t dirty = list_zeroed; + list_node_t *old_last = rects->tail; + + if (!rects->head) + { + rect_list_append_node(rects, node); + return old_last; + } + rect_list_append_node(&dirty, node); + while (dirty.head) + { + list_node_t *d_node, *cur_node, *prev_cur_node; + int keep_dirty; + rect_t r; + + d_node = rect_list_unlink_next(&dirty, NULL); + r = ((rect_node_t *)d_node)->rect; + prev_cur_node = NULL; + cur_node = rects->head; + keep_dirty = 1; + while (cur_node) + { + int area, action; + rect_t current, intra, outer; + + current = ((rect_node_t *)cur_node)->rect; + _calc_intra_outer_rect_area(r, current, &intra, &outer); + area = current.area + r.area - intra.area; + if ((intra.width == r.width) && (intra.height == r.height)) + { + /* .-------.cur + * | .---.r| + * | | | | + * | `---' | + * `-------' + */ + keep_dirty = 0; + break; + } + else if ((intra.width == current.width) && + (intra.height == current.height)) + { + /* .-------.r + * | .---.cur + * | | | | + * | `---' | + * `-------' + */ + if (old_last == cur_node) + old_last = prev_cur_node; + cur_node = cur_node->next; + rect_list_del_next(rects, prev_cur_node); + } + else if ((outer.area - area) <= accepted_error) + { + /* .-----------. bounding box (outer) + * |.---. .---.| + * ||cur| |r || + * || | | || + * |`---' `---'| + * `-----------' + * merge them, remove both and add merged + */ + rect_node_t *n; + + if (old_last == cur_node) + old_last = prev_cur_node; + + n = (rect_node_t *)rect_list_unlink_next(rects, prev_cur_node); + n->rect = outer; + rect_list_append_node(&dirty, (list_node_t *)n); + + keep_dirty = 0; + break; + } + else if ((intra.area - area) <= accepted_error) + { + /* .---.cur .---.r + * | | | | + * `---+---.r `---+---.cur + * | | | | + * `---' `---' + * no split, no merge + */ + prev_cur_node = cur_node; + cur_node = cur_node->next; + } + else + { + /* split is required */ + action = _split_fuzzy(&dirty, current, &r); + if (action == SPLIT_FUZZY_ACTION_MERGE) + { + /* horizontal merge is possible: remove both, add merged */ + rect_node_t *n; + + if (old_last == cur_node) + old_last = prev_cur_node; + + n = (rect_node_t *) + rect_list_unlink_next(rects, prev_cur_node); + + n->rect.left = outer.left; + n->rect.width = outer.width; + n->rect.right = outer.right; + n->rect.area = outer.width * r.height; + rect_list_append_node(&dirty, (list_node_t *)n); + } + else if (action == SPLIT_FUZZY_ACTION_NONE) + { + /* this rect check was totally useless, + * should never happen */ + /* prev_cur_node = cur_node; */ + /* cur_node = cur_node->next; */ + WRN("Should not get here!"); + abort(); + } + keep_dirty = 0; + break; + } + } + if (UNLIKELY(keep_dirty)) rect_list_append_node(rects, d_node); + else rect_list_node_pool_put(d_node); + } + return old_last; +} + +static inline void +_calc_outer_rect_area(const rect_t a, const rect_t b, rect_t *outer) +{ + int min_left, max_right; + int min_top, max_bottom; + + if (a.left < b.left) min_left = a.left; + else min_left = b.left; + if (a.right < b.right) max_right = b.right; + else max_right = a.right; + outer->left = min_left; + outer->right = max_right; + outer->width = max_right - min_left; + if (a.top < b.top) min_top = a.top; + else min_top = b.top; + if (a.bottom < b.bottom) max_bottom = b.bottom; + else max_bottom = a.bottom; + outer->top = min_top; + outer->bottom = max_bottom; + outer->height = max_bottom - min_top; + outer->area = outer->width * outer->height; +} + +static inline void +rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error) +{ + while (to_merge->head) + { + list_node_t *node, *parent_node; + rect_t r1; + int merged; + + r1 = ((rect_node_t *)to_merge->head)->rect; + merged = 0; + parent_node = NULL; + node = rects->head; + while (node) + { + rect_t r2, outer; + int area; + + r2 = ((rect_node_t *)node)->rect; + _calc_outer_rect_area(r1, r2, &outer); + area = r1.area + r2.area; /* intra area is taken as 0 */ + if (outer.area - area <= accepted_error) + { + /* remove both r1 and r2, create r3 + * actually r3 uses r2 instance, saves memory */ + rect_node_t *n; + + n = (rect_node_t *)rect_list_unlink_next(rects, parent_node); + n->rect = outer; + rect_list_append_node(to_merge, (list_node_t *)n); + merged = 1; + break; + } + parent_node = node; + node = node->next; + } + if (!merged) + { + list_node_t *n; + n = rect_list_unlink_next(to_merge, NULL); + rect_list_append_node(rects, n); + } + else + rect_list_del_next(to_merge, NULL); + } +} + +static inline void +rect_list_add_split_fuzzy_and_merge(list_t *rects, + list_node_t *node, + int split_accepted_error, + int merge_accepted_error) +{ + list_node_t *n; + + n = rect_list_add_split_fuzzy(rects, node, split_accepted_error); + if (n && n->next) + { + list_t to_merge; + /* split list into 2 segments, already merged and to merge */ + to_merge.head = n->next; + to_merge.tail = rects->tail; + rects->tail = n; + n->next = NULL; + rect_list_merge_rects(rects, &to_merge, merge_accepted_error); + } +} + +static inline int +_add_redraw(list_t *rects, int x, int y, int w, int h, int fuzz) +{ + rect_node_t *rn; + rn = (rect_node_t *)rect_list_node_pool_get(); + rn->_lst = list_node_zeroed; + rect_init(&rn->rect, x, y, w, h); + rect_list_add_split_fuzzy_and_merge(rects, (list_node_t *)rn, fuzz, fuzz); + return 1; +} + +///////////////////////////////////////////////////////////////// + +EAPI void +evas_common_tilebuf_init(void) +{ +} + +EAPI Tilebuf * +evas_common_tilebuf_new(int w, int h) +{ + Tilebuf *tb; + + tb = calloc(1, sizeof(Tilebuf)); + if (!tb) return NULL; + tb->tile_size.w = 8; + tb->tile_size.h = 8; + tb->outbuf_w = w; + tb->outbuf_h = h; + return tb; +} + +EAPI void +evas_common_tilebuf_free(Tilebuf *tb) +{ + rect_list_clear(&tb->rects); + rect_list_node_pool_flush(); + free(tb); +} + +EAPI void +evas_common_tilebuf_set_tile_size(Tilebuf *tb, int tw, int th) +{ + tb->tile_size.w = tw; + tb->tile_size.h = th; +} + +EAPI void +evas_common_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th) +{ + if (tw) *tw = tb->tile_size.w; + if (th) *th = tb->tile_size.h; +} + +EAPI void +evas_common_tilebuf_tile_strict_set(Tilebuf *tb, Eina_Bool strict) +{ + tb->strict_tiles = strict; +} + +EAPI int +evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) +{ + if ((w <= 0) || (h <= 0)) return 0; + RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); + if ((w <= 0) || (h <= 0)) return 0; + // optimize a common case -> adding the exact same rect 2x in a row + if ((tb->prev_add.x == x) && (tb->prev_add.y == y) && + (tb->prev_add.w == w) && (tb->prev_add.h == h)) return 1; + tb->prev_add.x = x; tb->prev_add.y = y; + tb->prev_add.w = w; tb->prev_add.h = h; + tb->prev_del.w = 0; tb->prev_del.h = 0; + return _add_redraw(&tb->rects, x, y, w, h, FUZZ * FUZZ); +} + +EAPI int +evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h) +{ + rect_t r; + + if (!tb->rects.head) return 0; + if ((w <= 0) || (h <= 0)) return 0; + RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); + if ((w <= 0) || (h <= 0)) return 0; + // optimize a common case -> deleting the exact same rect 2x in a row + if ((tb->prev_del.x == x) && (tb->prev_del.y == y) && + (tb->prev_del.w == w) && (tb->prev_del.h == h)) return 1; + tb->prev_del.x = x; tb->prev_del.y = y; + tb->prev_del.w = w; tb->prev_del.h = h; + tb->prev_add.w = 0; tb->prev_add.h = 0; + rect_init(&r, x, y, w, h); + rect_list_del_split_strict(&tb->rects, r); + tb->need_merge = 1; + return 0; +} + +EAPI int +evas_common_tilebuf_add_motion_vector(Tilebuf *tb EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED, int dx EINA_UNUSED, int dy EINA_UNUSED, int alpha EINA_UNUSED) +{ + return 0; +} + +EAPI void +evas_common_tilebuf_clear(Tilebuf *tb) +{ + tb->prev_add.x = tb->prev_add.y = tb->prev_add.w = tb->prev_add.h = 0; + tb->prev_del.x = tb->prev_del.y = tb->prev_del.w = tb->prev_del.h = 0; + rect_list_clear(&tb->rects); + tb->need_merge = 0; +} + +EAPI Tilebuf_Rect * +evas_common_tilebuf_get_render_rects(Tilebuf *tb) +{ + list_node_t *n; + list_t to_merge; + Tilebuf_Rect *rects = NULL, *rbuf, *r; + int bx1 = 0, bx2 = 0, by1 = 0, by2 = 0, num = 0, x1, x2, y1, y2, i; + +/* don't need this since the below is now always on + if (tb->need_merge) + { + to_merge = tb->rects; + tb->rects = list_zeroed; + rect_list_merge_rects(&tb->rects, &to_merge, 0); + tb->need_merge = 0; + } + */ + if (1) +// always fuzz merge for optimal perf +// if (!tb->strict_tiles) + { + // round up rects to tb->tile_size.w and tb->tile_size.h + to_merge = list_zeroed; + for (n = tb->rects.head; n; n = n->next) + { + x1 = ((rect_node_t *)n)->rect.left; + x2 = x1 + ((rect_node_t *)n)->rect.width; + y1 = ((rect_node_t *)n)->rect.top; + y2 = y1 + ((rect_node_t *)n)->rect.height; + x1 = tb->tile_size.w * (x1 / tb->tile_size.w); + y1 = tb->tile_size.h * (y1 / tb->tile_size.h); + x2 = tb->tile_size.w * ((x2 + tb->tile_size.w - 1) / tb->tile_size.w); + y2 = tb->tile_size.h * ((y2 + tb->tile_size.h - 1) / tb->tile_size.h); + _add_redraw(&to_merge, x1, y1, x2 - x1, y2 - y1, 0); + } + rect_list_clear(&tb->rects); + rect_list_merge_rects(&tb->rects, &to_merge, 0); + } + n = tb->rects.head; + if (n) + { + RECTS_CLIP_TO_RECT(((rect_node_t *)n)->rect.left, + ((rect_node_t *)n)->rect.top, + ((rect_node_t *)n)->rect.width, + ((rect_node_t *)n)->rect.height, + 0, 0, tb->outbuf_w, tb->outbuf_h); + num = 1; + bx1 = ((rect_node_t *)n)->rect.left; + bx2 = bx1 + ((rect_node_t *)n)->rect.width; + by1 = ((rect_node_t *)n)->rect.top; + by2 = by1 + ((rect_node_t *)n)->rect.height; + n = n->next; + for (; n; n = n->next) + { + RECTS_CLIP_TO_RECT(((rect_node_t *)n)->rect.left, + ((rect_node_t *)n)->rect.top, + ((rect_node_t *)n)->rect.width, + ((rect_node_t *)n)->rect.height, + 0, 0, tb->outbuf_w, tb->outbuf_h); + x1 = ((rect_node_t *)n)->rect.left; + if (x1 < bx1) bx1 = x1; + x2 = x1 + ((rect_node_t *)n)->rect.width; + if (x2 > bx2) bx2 = x2; + + y1 = ((rect_node_t *)n)->rect.top; + if (y1 < by1) by1 = y1; + y2 = y1 + ((rect_node_t *)n)->rect.height; + if (y2 > by2) by2 = y2; + num++; + } + } + else + return NULL; + + /* magic number - if we have > MAXREG regions to update, take bounding */ + if (num > MAXREG) + { + r = malloc(sizeof(Tilebuf_Rect)); + if (r) + { + EINA_INLIST_GET(r)->next = NULL; + EINA_INLIST_GET(r)->prev = NULL; + EINA_INLIST_GET(r)->last = NULL; + r->x = bx1; + r->y = by1; + r->w = bx2 - bx1; + r->h = by2 - by1; + rects = (Tilebuf_Rect *) + eina_inlist_append(EINA_INLIST_GET(rects), + EINA_INLIST_GET(r)); + } + return rects; + } + + rbuf = malloc(sizeof(Tilebuf_Rect) * num); + if (!rbuf) return NULL; + + for (i = 0, n = tb->rects.head; n; n = n->next) + { + rect_t cur; + + cur = ((rect_node_t *)n)->rect; + if ((cur.width > 0) && (cur.height > 0)) + { + r = &(rbuf[i]); + EINA_INLIST_GET(r)->next = NULL; + EINA_INLIST_GET(r)->prev = NULL; + EINA_INLIST_GET(r)->last = NULL; + r->x = cur.left; + r->y = cur.top; + r->w = cur.width; + r->h = cur.height; + rects = (Tilebuf_Rect *) + eina_inlist_append(EINA_INLIST_GET(rects), + EINA_INLIST_GET(r)); + i++; + } + } + + // It is possible that due to the clipping we do not return any rectangle here. + if (!rects) free(rbuf); + + return rects; +} + +EAPI void +evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects) +{ + free(rects); +} +#endif diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index 2c42341..632a941 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -244,7 +244,7 @@ extern EAPI int _evas_log_dom_global; /*****************************************************************************/ /* use exact rects for updates not tiles */ -/* #define RECTUPDATE */ +//#define NEWTILER #define TILESIZE 8 #define IMG_MAX_SIZE 65000 @@ -433,7 +433,11 @@ typedef struct _Cutout_Rects Cutout_Rects; typedef struct _Convert_Pal Convert_Pal; typedef struct _Tilebuf Tilebuf; -typedef struct _Tilebuf_Rect Tilebuf_Rect; +typedef struct _Tilebuf_Rect Tilebuf_Rect; + +#ifndef NEWTILER +typedef struct _Tilebuf_Tile Tilebuf_Tile; +#endif typedef struct _Evas_Common_Transform Evas_Common_Transform; @@ -1075,11 +1079,65 @@ struct _RGBA_Gfx_Compositor RGBA_Gfx_Pt_Func (*composite_pixel_mask_pt_get)(Eina_Bool src_alpha, Eina_Bool dst_alpha); }; +#ifndef NEWTILER +typedef struct list_node list_node_t; +typedef struct list list_t; +typedef struct rect rect_t; +typedef struct rect_node rect_node_t; + +struct list_node +{ + struct list_node *next; +}; + +struct list +{ + struct list_node *head; + struct list_node *tail; +}; + +struct rect +{ + int left; + int top; + int right; + int bottom; + int width; + int height; + int area; +}; + +struct rect_node +{ + struct list_node _lst; + struct rect rect; +}; +#endif + struct _Tilebuf { int outbuf_w, outbuf_h; +#ifdef NEWTILER void *region; +#else + struct { + short w, h; + } tile_size; + int need_merge; + list_t rects; + struct { + int x, y, w, h; + } prev_add, prev_del; + Eina_Bool strict_tiles : 1; +#endif +}; + +#ifndef NEWTILER +struct _Tilebuf_Tile +{ + Eina_Bool redraw : 1; }; +#endif struct _Tilebuf_Rect { --
