raster pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=49adf8aa47f37c41ee1fed288c828737104f1c5f
commit 49adf8aa47f37c41ee1fed288c828737104f1c5f Author: Carsten Haitzler (Rasterman) <[email protected]> Date: Wed Sep 23 22:22:27 2015 +0900 evas tiler update handler - move to region code to be accurate and fast this move evas tiler that does update handling to use fully correct regions using region.[xh]. this also removed old unused regionbuf code and a bunch of commented out code no longer needed. much simpler now and easier to maintain. --- src/Makefile_Evas.am | 1 - src/lib/evas/common/evas_regionbuf.c | 357 ------------ src/lib/evas/common/evas_tiler.c | 878 ++--------------------------- src/lib/evas/include/evas_common_private.h | 93 +-- 4 files changed, 39 insertions(+), 1290 deletions(-) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 2fe051b..518c80a 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -298,7 +298,6 @@ lib/evas/common/evas_scale_smooth.c \ lib/evas/common/evas_scale_span.c \ lib/evas/common/evas_thread_render.c \ lib/evas/common/evas_tiler.c \ -lib/evas/common/evas_regionbuf.c \ lib/evas/common/evas_pipe.c \ lib/evas/common/language/evas_bidi_utils.c \ lib/evas/common/language/evas_language_utils.c \ diff --git a/src/lib/evas/common/evas_regionbuf.c b/src/lib/evas/common/evas_regionbuf.c deleted file mode 100644 index 3b14af8..0000000 --- a/src/lib/evas/common/evas_regionbuf.c +++ /dev/null @@ -1,357 +0,0 @@ -#include "evas_common_private.h" - -#if 0 -Regionbuf * -evas_common_regionbuf_new(int w, int h) -{ - Regionbuf *rb; - - rb = calloc(1, sizeof(Regionbuf) + (h * sizeof(Regionspan))); - if (!rb) return NULL; - rb->spans = (Regionspan **)(rb + sizeof(Regionbuf)); - rb->w = w; - rb->h = h; - return rb; -} - -void -evas_common_regionbuf_free(Regionbuf *rb) -{ - evas_common_regionbuf_clear(rb); - free(rb); -} - -void -evas_common_regionbuf_clear(Regionbuf *rb) -{ - int y; - - for (y = 0; y < rb->h; y++) - { - while (rb->spans[y]) - { - Regionspan *span; - - span = rb->spans[y]; - rb->spans[y] = eina_inlist_remove(rb->spans[y], rb->spans[y]); - free(span); - } - } -} - -void -evas_common_regionbuf_span_add(Regionbuf *rb, int x1, int x2, int y) -{ - Regionspan *span, *span2, *nspan, *sp_start, *sp_stop; - - /* abort if outside */ - if ((y < 0) || - (y >= rb->h) || - (x2 < 0) || - (x1 >= rb->w)) return; - /* clip to horiz bounds */ - if (x1 < 0) x1 = 0; - if (x2 < (rb->w - 1)) x2 = rb->w - 1; - sp_start = NULL; - sp_stop = NULL; - EINA_INLIST_FOREACH(rb->spans[y], span) - { - nspan = (Regionspan *)(EINA_INLIST_GET(span))->next; - /* we dont know what t do with the span yet */ - if (!sp_start) - { - /* if new span starts before or on this span or just after - * with no gap */ - if (x1 <= (span->x2 + 1)) - sp_start = span; - /* if there is no next span */ - if (!nspan) - { - sp_stop = span; - break; - } - /* if new span ends before the next span starts with a gap of - * 1 pixel (or more) */ - else if (x2 < (nspan->x1 - 1)) - { - sp_stop = span; - break; - } - } - /* we already know it already starts before or in sp_start */ - else - { - /* there is no span after this one, so this has to be the stop */ - if (!nspan) - { - sp_stop = span; - break; - } - /* if new span ends before the next span starts with a gap of - * 1 pixel (or more) */ - else if (x2 < (nspan->x1 - 1)) - { - sp_stop = span; - break; - } - } - } - /* sp_start is where the new span starts in or before */ - /* sp_stop is where the new span stops in or after */ - if ((sp_start) && (sp_stop)) - { - /* same start and stop */ - if (sp_start == sp_stop) - { - if (x2 < (sp_start->x1 - 1)) - { - span2 = calloc(1, sizeof(Regionspan)); - span2->x1 = x1; - span2->x2 = x2; - rb->spans[y] = eina_inlist_prepend_relative(rb->spans[y], span2, sp_start); - return; - } - if (x1 < sp_start->x1) - sp_start->x1 = x1; - if (x2 > sp_start->x2) - sp_start->x2 = x2; - return; - } - else - { - Eina_Inlist *l; - - /* remove all nodes after sp_start and before_sp_stop because - * the new */ - for (l = (EINA_INLIST_GET(sp_start))->next; l != EINA_INLIST_GET(sp_stop);) - { - span = (Regionspan *)l; - l = l->next; - rb->spans[y] = eina_inlist_remove(rb->spans[y], span); - free(span); - } - /* remove the end span */ - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_stop); - /* if the new span is before the start span - extend */ - if (x1 < sp_start->x1) - sp_start->x1 = x1; - /* if it goes beyond the stop span - extend stop span */ - if (x2 > sp_stop->x2) - sp_stop->x2 = x2; - /* extend start span to stop span */ - sp_start->x2 = sp_stop->x2; - /* don't need stop span anymore */ - free(sp_stop); - return; - } - } - /* no start AND stop... just append */ - span2 = calloc(1, sizeof(Regionspan)); - span2->x1 = x1; - span2->x2 = x2; - rb->spans[y] = eina_inlist_append(rb->spans[y], span2); -} - -void -evas_common_regionbuf_span_del(Regionbuf *rb, int x1, int x2, int y) -{ - /* FIXME: del span */ - Regionspan *span, *span2, *nspan, *sp_start, *sp_stop; - - /* abort if outside */ - if ((y < 0) || - (y >= rb->h) || - (x2 < 0) || - (x1 >= rb->w)) return; - /* clip to horiz bounds */ - if (x1 < 0) x1 = 0; - if (x2 < (rb->w - 1)) x2 = rb->w - 1; - sp_start = NULL; - sp_stop = NULL; - EINA_INLIST_FOREACH(rb->spans[y], span) - { - nspan = (Regionspan *)(EINA_INLIST_GET(l))->next; - /* we dont know what t do with the span yet */ - if (!sp_start) - { - /* if new span starts before or on this span or just after - * with no gap */ - if (x1 <= (span->x2)) - sp_start = span; - /* if there is no next span */ - if (!nspan) - { - sp_stop = span; - break; - } - /* if new span ends before the next span starts with a gap of - * 1 pixel (or more) */ - else if (x2 < nspan->x1) - { - sp_stop = span; - break; - } - } - /* we already know it already starts before or in sp_start */ - else - { - /* there is no span after this one, so this has to be the stop */ - if (!nspan) - { - sp_stop = span; - break; - } - /* if new span ends before the next span starts with a gap of - * 1 pixel (or more) */ - else if (x2 < nspan->x1) - { - sp_stop = span; - break; - } - } - } - /* sp_start is where the new span starts in or before */ - /* sp_stop is where the new span stops in or after */ - if ((sp_start) && (sp_stop)) - { - /* same start and stop */ - if (sp_start == sp_stop) - { - /* if it ends before this the span start starts... return */ - if (x2 < sp_start->x1) - return; - /* it starts on or before this span */ - else if (x1 <= sp_start->x1) - { - /* right edge is within the span */ - if (x2 < sp_start->x2) - { - sp_start->x2 = x2; - return; - } - else - { - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_start); - return; - } - } - /* it ends on or after the end of this span */ - else if (x2 >= sp_start->x2) - { - /* it starts after the start */ - if (x1 > sp_start->x1) - { - sp_start->x1 = x1; - return; - } - /* remove it all */ - else - { - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_start); - return; - } - return; - } - /* this breaks the span into 2 */ - else - { - span2 = calloc(1, sizeof(Regionspan)); - span2->x1 = sp_start->x1; - span2->x2 = x1 - 1; - rb->spans[y] = eina_inlist_prepend_relative(rb->spans[y], span2, sp_start); - sp_start->x1 = x2 + 1; - return; - } - } - else - { - Eina_Inlist *l; - - /* remove all nodes after sp_start and before_sp_stop because - * the new */ - for (l = (EINA_INLIST_GET(sp_start))->next; l != EINA_INLIST_GET(sp_stop);) - { - span = (Regionspan *)l; - l = l->next; - rb->spans[y] = eina_inlist_remove(rb->spans[y], span); - free(span); - } - /* all of the start span is cut out */ - if (x1 <= sp_start->x1) - { - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_start); - free(sp_start); - } - /* chup it off at the new span start */ - else - sp_start->x2 = x1 - 1; - /* all of the end span is cut out */ - if (x2 >= sp_stop->x2) - { - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_stop); - free(sp_stop); - } - /* chop it up at the end */ - else - sp_stop->x1 = x2 + 1; - return; - } - } -} - -Tilebuf_Rect * -evas_common_regionbuf_rects_get(Regionbuf *rb) -{ - Tilebuf_Rect *rects = NULL, *r; - int y; - - /* FIXME: take spans, make rects */ - for (y = 0; y < rb->h; y++) - { - Regionspan *sp_start; - Eina_Inlist *l, *ll; - - for (l = EINA_INLIST_GET(rb->spans[y]); l;) - { - Regionspan *span; - int yy; - - sp_start = (Regionspan *)l; - l = l->next; - rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_start); - for (yy = y + 1; yy < rb->h; yy++) - { - int match = 0; - - for (ll = EINA_INLIST_GET(rb->spans[yy]); ll;) - { - span = (Regionspan *)ll; - ll = ll->next; - if (span->x1 == sp_start->x1) - { - if ((span->x1 != sp_start->x1) || - (span->x2 != sp_start->x2)) - { - goto coallate; - } - match = 1; - rb->spans[yy] = eina_inlist_remove(rb->spans[yy], span); - free(span); - } - } - if (!match) goto coallate; - } - coallate: - r = calloc(1, sizeof(Tilebuf_Rect)); - r->x = sp_start->x1; - r->y = y; - r->w = sp_start->x2 - sp_start->x1 + 1; - r->h = yy - y; - rects = eina_inlist_append(rects, r); - free(sp_start); - } - } - evas_common_regionbuf_clear(rb); - return rects; -} -#endif diff --git a/src/lib/evas/common/evas_tiler.c b/src/lib/evas/common/evas_tiler.c index 2dbe9fd..74f5d18 100644 --- a/src/lib/evas/common/evas_tiler.c +++ b/src/lib/evas/common/evas_tiler.c @@ -1,684 +1,5 @@ #include "evas_common_private.h" - -#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; -} - -///////////////////////////////////////////////////////////////// +#include "region.h" EAPI void evas_common_tilebuf_init(void) @@ -688,79 +9,49 @@ 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; + Tilebuf *tb = malloc(sizeof(Tilebuf)); tb->outbuf_w = w; tb->outbuf_h = h; + tb->region = region_new(tb->outbuf_w, tb->outbuf_h); return tb; } EAPI void evas_common_tilebuf_free(Tilebuf *tb) { - rect_list_clear(&tb->rects); - rect_list_node_pool_flush(); + region_free(tb->region); free(tb); } EAPI void -evas_common_tilebuf_set_tile_size(Tilebuf *tb, int tw, int th) +evas_common_tilebuf_set_tile_size(Tilebuf *tb EINA_UNUSED, int tw EINA_UNUSED, int th EINA_UNUSED) { - tb->tile_size.w = tw; - tb->tile_size.h = th; } EAPI void -evas_common_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th) +evas_common_tilebuf_get_tile_size(Tilebuf *tb EINA_UNUSED, int *tw, int *th) { - if (tw) *tw = tb->tile_size.w; - if (th) *th = tb->tile_size.h; + if (tw) *tw = 1; + if (th) *th = 1; } EAPI void -evas_common_tilebuf_tile_strict_set(Tilebuf *tb, Eina_Bool strict) +evas_common_tilebuf_tile_strict_set(Tilebuf *tb EINA_UNUSED, Eina_Bool strict EINA_UNUSED) { - 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); + region_rect_add(tb->region, x, y, w, h); + return 1; } 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; + region_rect_del(tb->region, x, y, w, h); + return 1; } EAPI int @@ -772,134 +63,41 @@ evas_common_tilebuf_add_motion_vector(Tilebuf *tb EINA_UNUSED, int x EINA_UNUSED 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; + region_free(tb->region); + tb->region = region_new(tb->outbuf_w, tb->outbuf_h); } 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; + Tilebuf_Rect *rects = NULL, *r, *rend, *rbuf; + Box *rects2, *rs; + int n; -/* 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; - } + rects2 = region_rects(tb->region); + if (!rects2) return NULL; + n = region_rects_num(tb->region); + if (n <= 0) return NULL; - rbuf = malloc(sizeof(Tilebuf_Rect) * num); + rbuf = malloc(n * sizeof(Tilebuf_Rect)); 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++; - } + rend = rbuf + n; + rs = rects2; + for (r = rbuf; r < rend; r++) + { + EINA_INLIST_GET(r)->next = NULL; + EINA_INLIST_GET(r)->prev = NULL; + EINA_INLIST_GET(r)->last = NULL; + r->x = rs->x1; + r->y = rs->y1; + r->w = rs->x2 - rs->x1; + r->h = rs->y2 - rs->y1; + rs++; + rects = (Tilebuf_Rect *) + eina_inlist_append(EINA_INLIST_GET(rects), + EINA_INLIST_GET(r)); } - - // It is possible that due to the clipping we do not return any rectangle here. - if (!rects) free(rbuf); - return rects; } diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index 52c6b26..c7ab1ba 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -433,7 +433,6 @@ typedef struct _Cutout_Rects Cutout_Rects; typedef struct _Convert_Pal Convert_Pal; typedef struct _Tilebuf Tilebuf; -typedef struct _Tilebuf_Tile Tilebuf_Tile; typedef struct _Tilebuf_Rect Tilebuf_Rect; typedef struct _Evas_Common_Transform Evas_Common_Transform; @@ -449,11 +448,6 @@ typedef int FPc; // one fp unit #define FP1 (1 << (FP)) -/* -typedef struct _Regionbuf Regionbuf; -typedef struct _Regionspan Regionspan; -*/ - typedef void (*RGBA_Gfx_Func) (DATA32 *src, DATA8 *mask, DATA32 col, DATA32 *dst, int len); typedef void (*RGBA_Gfx_Pt_Func) (DATA32 src, DATA8 mask, DATA32 col, DATA32 *dst); typedef void (*Gfx_Func_Copy) (DATA32 *src, DATA32 *dst, int len); @@ -1078,82 +1072,10 @@ struct _RGBA_Gfx_Compositor RGBA_Gfx_Pt_Func (*composite_pixel_mask_pt_get)(Eina_Bool src_alpha, Eina_Bool dst_alpha); }; -#define EVAS_RECT_SPLIT 1 -#ifdef EVAS_RECT_SPLIT -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 /* EVAS_RECT_SPLIT */ - struct _Tilebuf { int outbuf_w, outbuf_h; - struct { - short w, h; - } tile_size; -#ifdef RECTUPDATE -/* - Regionbuf *rb; - */ -#elif defined(EVAS_RECT_SPLIT) - int need_merge; - list_t rects; -#else -/* - struct { - int w, h; - Tilebuf_Tile *tiles; - } tiles; - */ -#endif - struct { - int x, y, w, h; - } prev_add, prev_del; - Eina_Bool strict_tiles : 1; -}; - -struct _Tilebuf_Tile -{ - Eina_Bool redraw : 1; -/* FIXME: need these flags later - but not now */ -/* - Eina_Bool done : 1; - Eina_Bool edge : 1; - Eina_Bool from : 1; - - struct { - int dx, dy; - } vector; - */ + void *region; }; struct _Tilebuf_Rect @@ -1161,19 +1083,6 @@ struct _Tilebuf_Rect EINA_INLIST; int x, y, w, h; }; -/* -struct _Regionbuf -{ - int w, h; - Regionspan **spans; -}; - -struct _Regionspan -{ - EINA_INLIST; - int x1, x2; -}; -*/ struct _Convert_Pal { --
