diff --git a/legacy/evas/src/lib/engines/common/evas_tiler.c b/legacy/evas/src/lib/engines/common/evas_tiler.c index 895907470d..30e2f6b501 100644 --- a/legacy/evas/src/lib/engines/common/evas_tiler.c +++ b/legacy/evas/src/lib/engines/common/evas_tiler.c @@ -1,8 +1,723 @@ #include "evas_common.h" +#ifdef EVAS_RECT_SPLIT + +static const list_node_t list_node_zeroed = {.next = NULL}; +static const list_t list_zeroed = {.head = NULL, .tail = NULL}; + +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; +} + +void +rect_print(const rect_t r) +{ + printf("", r.left, r.top, r.width, r.height); +} + +void +rect_list_print(const list_t rects) +{ + list_node_t *node; + int len; + + len = 0; + for (node = rects.head; node != NULL; node = node->next) len++; + + printf("["); + for (node = rects.head; node != NULL; node = node->next) + { + rect_print(((rect_node_t *)node)->rect); + if (node->next) + { + putchar(','); + if (len < 4) putchar(' '); + else + { + putchar('\n'); + putchar(' '); + } + } + } + printf("]\n"); +} + +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; + } +} + +inline void +rect_list_append(list_t *rects, const rect_t r) +{ + rect_node_t *rect_node; + + rect_node = malloc(sizeof(rect_node_t)); + rect_node->rect = r; + rect_node->_lst = list_node_zeroed; + + rect_list_append_node(rects, (list_node_t *)rect_node); +} + +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); +} + +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; +} + +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; +} + +inline void +rect_list_del_next(list_t *rects, list_node_t *parent_node) +{ + list_node_t *node; + + node = rect_list_unlink_next(rects, parent_node); + free(node); +} + +void +rect_list_clear(list_t *rects) +{ + list_node_t *node; + + node = rects->head; + while (node) + { + list_node_t *aux; + + aux = node->next; + free(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; */ + } +} + +void +rect_list_add_split_strict(list_t *rects, list_node_t *node) +{ + list_t dirty = list_zeroed; + list_t new_dirty = list_zeroed; + list_node_t *cur_node; + + if (!rects->head) + { + rect_list_append_node(rects, node); + return; + } + + rect_list_append_node(&dirty, node); + + cur_node = rects->head; + while (dirty.head) + { + rect_t current; + + if (!cur_node) + { + rect_list_concat(rects, &dirty); + break; + } + + current = ((rect_node_t*)cur_node)->rect; + + while (dirty.head) + { + int intra_width, intra_height; + rect_t r; + + r = ((rect_node_t *)dirty.head)->rect; + _calc_intra_rect_area(r, current, &intra_width, &intra_height); + if ((intra_width == r.width) && (intra_height == r.height)) + /* .-------.cur + * | .---.r| + * | | | | + * | `---' | + * `-------' + */ + rect_list_del_next(&dirty, NULL); + else if ((intra_width <= 0) || (intra_height <= 0)) + { + /* .---.cur .---.r + * | | | | + * `---+---.r `---+---.cur + * | | | | + * `---' `---' + */ + list_node_t *tmp; + tmp = rect_list_unlink_next(&dirty, NULL); + rect_list_append_node(&new_dirty, tmp); + } + else + { + _split_strict(&new_dirty, current, r); + rect_list_del_next(&dirty, NULL); + } + } + dirty = new_dirty; + new_dirty = list_zeroed; + + cur_node = cur_node->next; + } +} + +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; +} + +list_node_t * +rect_list_add_split_fuzzy(list_t *rects, const rect_t r, int accepted_error) +{ + list_t dirty = list_zeroed; + list_node_t *old_last; + + old_last = rects->tail; + + if (!rects->head) + { + rect_list_append(rects, r); + return old_last; + } + + rect_list_append(&dirty, r); + 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 <= 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; */ + printf("Should not get here!\n"); + abort(); + } + + keep_dirty = 0; + break; + } + } + + if (keep_dirty) rect_list_append_node(rects, d_node); + else free(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; +} + +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 != NULL) + { + 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); + } +} + +void +rect_list_add_split_fuzzy_and_merge(list_t *rects, const rect_t r, + int split_accepted_error, + int merge_accepted_error) +{ + list_node_t *n; + + n = rect_list_add_split_fuzzy(rects, r, 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); + } +} +#endif /* EVAS_RECT_SPLIT */ + #define TILE(tb, x, y) ((tb)->tiles.tiles[((y) * (tb)->tiles.w) + (x)]) #ifdef RECTUPDATE +#elif defined(EVAS_RECT_SPLIT) #else static int tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill); static int tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill); @@ -36,6 +751,8 @@ evas_common_tilebuf_free(Tilebuf *tb) { #ifdef RECTUPDATE evas_common_regionbuf_free(tb->rb); +#elif defined(EVAS_RECT_SPLIT) + rect_list_clear(&tb->rects); #else if (tb->tiles.tiles) free(tb->tiles.tiles); #endif @@ -69,6 +786,25 @@ evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) for (i = 0; i < h; i++) evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i); return 1; +#elif defined(EVAS_RECT_SPLIT) + rect_t r; + 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; + + x >>= 1; + y >>= 1; + w += 2; + w >>= 1; + h += 2; + h >>= 1; + + rect_init(&r, x, y, w, h); + //fprintf(stderr, "ACCOUNTING: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h); + //testing on my core2 duo desktop - fuzz of 48 is best. +#define FUZZ 48 + rect_list_add_split_fuzzy_and_merge(&tb->rects, r, FUZZ * FUZZ, FUZZ * FUZZ); + return 1; #else int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; @@ -114,6 +850,50 @@ evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h) for (i = 0; i < h; i++) evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i); +#elif defined(EVAS_RECT_SPLIT) + list_node_t *lst; + rect_node_t n; + + + 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; + + x += 1; + y += 1; + x >>= 1; + y >>= 1; + w -= 1; + w >>= 1; + h -= 1; + h >>= 1; + + if ((w <= 0) || (h <= 0)) return 0; + + rect_init(&n.rect, x, y, w, h); + //fprintf(stderr, "ACCOUNTING: del_redraw: %4d,%4d %3dx%3d\n", x, y, w, h); + + lst = tb->rects.head; + + n._lst = list_node_zeroed; + tb->rects.head = (list_node_t *)&n; + tb->rects.tail = (list_node_t *)&n; + + while (lst) + { + list_node_t *tmp; + rect_t r; + + tmp = lst->next; + lst->next = NULL; + rect_list_add_split_strict(&tb->rects, lst); + lst = tmp; + } + /* remove deleted rectangle */ + rect_list_unlink_next(&tb->rects, NULL); + + return 0; #else int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; int num; @@ -170,6 +950,8 @@ evas_common_tilebuf_clear(Tilebuf *tb) { #ifdef RECTUPDATE evas_common_regionbuf_clear(tb->rb); +#elif defined(EVAS_RECT_SPLIT) + rect_list_clear(&tb->rects); #else if (!tb->tiles.tiles) return; memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); @@ -181,6 +963,32 @@ evas_common_tilebuf_get_render_rects(Tilebuf *tb) { #ifdef RECTUPDATE return evas_common_regionbuf_rects_get(tb->rb); +#elif defined(EVAS_RECT_SPLIT) + + list_node_t *n; + Tilebuf_Rect *rects = NULL; + for (n = tb->rects.head; n != NULL; n = n->next) { + rect_t cur; + Tilebuf_Rect *r; + + cur = ((rect_node_t *)n)->rect; + + r = malloc(sizeof(Tilebuf_Rect)); + r->_list_data.next = NULL; + r->_list_data.prev = NULL; + r->_list_data.last = NULL; + r->x = cur.left << 1; + r->y = cur.top << 1; + r->w = cur.width << 1; + r->h = cur.height << 1; + +/* fprintf(stderr, "\tclear: %4d,%4d %3dx%3d\n", */ +/* r->x, r->y, r->w, r->h); */ + + rects = evas_object_list_append(rects, r); + } + return rects; + #else Tilebuf_Rect *rects = NULL; Tilebuf_Tile *tbt; @@ -294,6 +1102,8 @@ tilebuf_setup(Tilebuf *tb) if ((tb->outbuf_w <= 0) || (tb->outbuf_h <= 0)) return; #ifdef RECTUPDATE tb->rb = evas_common_regionbuf_new(tb->outbuf_w, tb->outbuf_h); +#elif defined(EVAS_RECT_SPLIT) + tb->rects = list_zeroed; #else if (tb->tiles.tiles) free(tb->tiles.tiles); tb->tiles.tiles = NULL; @@ -314,6 +1124,7 @@ tilebuf_setup(Tilebuf *tb) } #ifdef RECTUPDATE +#elif defined(EVAS_RECT_SPLIT) #else static int tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill) diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index 5d2e67af57..d68495e42f 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -531,6 +531,58 @@ struct _RGBA_Gfx_Compositor RGBA_Gfx_Pt_Func (*composite_pixel_mask_pt_get)(int src_flags, RGBA_Image *dst); }; +#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 +{ + short left; + short top; + short right; + short bottom; + short width; + short height; + int area; +}; + +struct rect_node +{ + struct list_node _lst; + struct rect rect; +}; + + +void rect_init(rect_t *r, int x, int y, int w, int h); +void rect_list_append_node(list_t *rects, list_node_t *node); +void rect_list_append(list_t *rects, const rect_t r); +void rect_list_append_xywh(list_t *rects, int x, int y, int w, int h); +void rect_list_concat(list_t *rects, list_t *other); +list_node_t *rect_list_unlink_next(list_t *rects, list_node_t *parent_node); +void rect_list_del_next(list_t *rects, list_node_t *parent_node); +void rect_list_clear(list_t *rects); +void rect_list_add_split_strict(list_t *rects, list_node_t *node); +list_node_t *rect_list_add_split_fuzzy(list_t *rects, const rect_t r, int accepted_error); +void rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error);void rect_list_add_split_fuzzy_and_merge(list_t *rects, const rect_t r, int split_accepted_error, int merge_accepted_error); + +void rect_print(const rect_t r); +void rect_list_print(const list_t rects); +#endif /* EVAS_RECT_SPLIT */ + struct _Tilebuf { int outbuf_w; @@ -542,6 +594,8 @@ struct _Tilebuf #ifdef RECTUPDATE Regionbuf *rb; +#elif defined(EVAS_RECT_SPLIT) + list_t rects; #else struct { int w, h; diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h index c7d15999d7..290c74a7ce 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h @@ -86,6 +86,10 @@ struct _Evas_GL_Context Evas_List *tex_pool; RGBA_Draw_Context *dc; + + struct { + GLhandleARB prog, fshad; + } yuv422p; }; struct _Evas_GL_Texture @@ -96,7 +100,6 @@ struct _Evas_GL_Texture int uw, uh; GLuint texture, texture2, texture3; - GLhandleARB prog; unsigned char smooth : 1; unsigned char changed : 1; @@ -106,6 +109,7 @@ struct _Evas_GL_Texture unsigned char opt : 1; int references; + GLhandleARB prog; }; struct _Evas_GL_Image diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c index 23466788c2..f4708b0108 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c @@ -39,6 +39,41 @@ evas_gl_common_context_new(void) gc->change.clip = 1; gc->change.buf = 1; gc->change.other = 1; + + gc->yuv422p.prog = glCreateProgramObjectARB(); +// on an nv 6600gt this is fast - but on a 5500fx its DEAD SLOW!!!!! +// if (!gc->ext.arb_texture_non_power_of_two) return NULL; + /* BEGIN LEAK */ + gc->yuv422p.fshad = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + { + const char *code = + "uniform sampler2D ytex, utex, vtex;\n" + "void main(void) {\n" + " float r, g, b, y, u, v;\n" + " y = texture2D(ytex, gl_TexCoord[0].st).r;\n" + " u = texture2D(utex, gl_TexCoord[0].st).r;\n" + " v = texture2D(vtex, gl_TexCoord[0].st).r;\n" + " y = (y - 0.0625) * 1.164;\n" + " u = u - 0.5;\n" + " v = v - 0.5;\n" + " r = y + (1.402 * v);\n" + " g = y - (0.34414 * u) - (0.71414 * v);\n" + " b = y + (1.772 * u);\n" + " gl_FragColor = vec4(r * gl_Color.r * gl_Color.a, g * gl_Color.g * gl_Color.a, b * gl_Color.b * gl_Color.a, gl_Color.a);\n" + "}\n"; + glShaderSourceARB(gc->yuv422p.fshad, 1, &code, NULL); + } + glCompileShaderARB(gc->yuv422p.fshad); + glAttachObjectARB(gc->yuv422p.prog, gc->yuv422p.fshad); + /* END LEAK - something in the above leaks... beats me what. */ + glLinkProgramARB(gc->yuv422p.prog); + + glUseProgramObjectARB(gc->yuv422p.prog); + glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "ytex"), 0); + glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "utex"), 1); + glUniform1iARB(glGetUniformLocationARB(gc->yuv422p.prog, "vtex"), 2); + glUseProgramObjectARB(0); + return gc; } @@ -47,7 +82,15 @@ evas_gl_common_context_free(Evas_GL_Context *gc) { gc->references--; if (gc->references > 0) return; - + if (gc->yuv422p.fshad) + { + glDeleteObjectARB(gc->yuv422p.fshad); + } + if (gc->yuv422p.prog) + { + glDeleteObjectARB(gc->yuv422p.prog); + } + if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL; free(gc); } diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c index 1080c647e7..5ba1174049 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c @@ -105,6 +105,7 @@ evas_gl_common_image_new_from_data(Evas_GL_Context *gc, int w, int h, int *data, im->cached = 1; gc->images = evas_list_prepend(gc->images, im); */ + printf("new im cs = %i\n", im->cs.space); return im; } @@ -166,6 +167,33 @@ evas_gl_common_image_new(Evas_GL_Context *gc, int w, int h, int alpha, int cspac free(im); return NULL; } + im->gc = gc; + im->cs.space = cspace; + if (alpha) + im->im->flags |= RGBA_IMAGE_HAS_ALPHA; + else + im->im->flags &= ~RGBA_IMAGE_HAS_ALPHA; + switch (cspace) + { + case EVAS_COLORSPACE_ARGB8888: +// if (data) +// memcpy(im->im->image->data, data, w * h * sizeof(DATA32)); + break; + case EVAS_COLORSPACE_YCBCR422P601_PL: + case EVAS_COLORSPACE_YCBCR422P709_PL: + evas_common_image_surface_dealloc(im->im->image); + im->im->image->data = NULL; +// if (im->tex) evas_gl_common_texture_free(im->tex); + im->tex = NULL; + im->cs.no_free = 0; + im->cs.data = calloc(1, im->im->image->h * sizeof(unsigned char *) * 2); +// if ((data) && (im->cs.data)) +// memcpy(im->cs.data, data, im->im->image->h * sizeof(unsigned char *) * 2); + break; + default: + abort(); + break; + } return im; } @@ -215,6 +243,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy r = g = b = a = 255; } evas_common_load_image_data_from_file(im->im); +/* leak in this switch */ switch (im->cs.space) { case EVAS_COLORSPACE_ARGB8888: @@ -251,7 +280,9 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy im->dirty = 0; } if ((!im->tex) && (im->cs.data) && (*((unsigned char **)im->cs.data))) - im->tex = evas_gl_common_ycbcr601pl_texture_new(gc, im->cs.data, im->im->image->w, im->im->image->h, smooth); + { + im->tex = evas_gl_common_ycbcr601pl_texture_new(gc, im->cs.data, im->im->image->w, im->im->image->h, smooth); + } if (!im->tex) return; ow = (dw * im->tex->tw) / sw; oh = (dh * im->tex->th) / sh; @@ -270,11 +301,13 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy ty2 = (double)(sy + sh) / (double)(im->tex->h); } evas_gl_common_context_texture_set(gc, im->tex, smooth, ow, oh); + break; default: abort(); break; } + // if ((!im->tex->have_mipmaps) && (smooth) && // ((im->tex->uw < im->tex->tw) || (im->tex->uh < im->tex->th)) && // (!gc->ext.sgis_generate_mipmap)) diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c index a62adee5c1..4b719e221e 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c @@ -296,8 +296,16 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex) glDeleteTextures(1, &tex->texture); if (tex->texture2) glDeleteTextures(1, &tex->texture2); if (tex->texture3) glDeleteTextures(1, &tex->texture3); +/* + if (tex->fshad) + { + glDeleteObjectARB(tex->fshad); + } if (tex->prog) - glDeleteObjectARB(tex->prog); + { + glDeleteObjectARB(tex->prog); + } + */ free(tex); } @@ -418,7 +426,6 @@ evas_gl_common_ycbcr601pl_texture_new(Evas_GL_Context *gc, unsigned char **rows, Evas_GL_Texture *tex; int im_w, im_h, tw, th, y; GLenum texfmt; - GLhandleARB fshad; // on an nv 6600gt this is fast - but on a 5500fx its DEAD SLOW!!!!! // if (!gc->ext.arb_texture_non_power_of_two) return NULL; @@ -436,40 +443,13 @@ evas_gl_common_ycbcr601pl_texture_new(Evas_GL_Context *gc, unsigned char **rows, tex->references = 0; tex->smooth = 0; tex->changed = 1; - - tex->prog = glCreateProgramObjectARB(); - fshad = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); - { - const char *code = - "uniform sampler2D ytex, utex, vtex;\n" - "void main(void) {\n" - " float r, g, b, y, u, v;\n" - " y = texture2D(ytex, gl_TexCoord[0].st).r;\n" - " u = texture2D(utex, gl_TexCoord[0].st).r;\n" - " v = texture2D(vtex, gl_TexCoord[0].st).r;\n" - " y = (y - 0.0625) * 1.164;\n" - " u = u - 0.5;\n" - " v = v - 0.5;\n" - " r = y + (1.402 * v);\n" - " g = y - (0.34414 * u) - (0.71414 * v);\n" - " b = y + (1.772 * u);\n" - " gl_FragColor = vec4(r * gl_Color.r * gl_Color.a, g * gl_Color.g * gl_Color.a, b * gl_Color.b * gl_Color.a, gl_Color.a);\n" - "}\n"; - glShaderSourceARB(fshad, 1, &code, NULL); - } - - glCompileShaderARB(fshad); - glAttachObjectARB(tex->prog, fshad); - glLinkProgramARB(tex->prog); + tex->prog = gc->yuv422p.prog; glEnable(GL_TEXTURE_2D); texfmt = GL_LUMINANCE; glUseProgramObjectARB(tex->prog); - glUniform1iARB(glGetUniformLocationARB(tex->prog, "ytex"), 0); - glUniform1iARB(glGetUniformLocationARB(tex->prog, "utex"), 1); - glUniform1iARB(glGetUniformLocationARB(tex->prog, "vtex"), 2); glGenTextures(1, &(tex->texture)); glBindTexture(GL_TEXTURE_2D, tex->texture); diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index 08f585b7c6..5f20cc2c54 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -718,6 +718,9 @@ eng_image_size_set(void *data, void *image, int w, int h) if (!image) return NULL; eng_window_use(re->win); im_old = image; + if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) || + (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL)) + w &= ~0x1; if ((im_old) && (im_old->im->image->w == w) && (im_old->im->image->h == h)) return image; if (im_old) diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index 4d2a53609b..1200c8ff6b 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -512,6 +512,7 @@ eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, break; case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: + w &= ~0x1; im->image->w = w; im->image->h = h; evas_common_image_surface_alloc(im->image); @@ -546,6 +547,7 @@ eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int break; case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: + w &= ~0x1; im = evas_common_image_create(w, h); im->cs.data = calloc(1, im->image->h * sizeof(unsigned char *) * 2); if ((image_data) && (im->cs.data)) @@ -582,13 +584,22 @@ eng_image_size_set(void *data, void *image, int w, int h) RGBA_Image *im, *im_old; im_old = image; + if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || + (im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) + w &= ~0x1; + if ((im_old) && (im_old->image->w == w) && (im_old->image->h == h)) + return image; im = evas_common_image_create(w, h); if (!im) return im_old; if (im_old) { im->cs.space = im_old->cs.space; im->flags = im_old->flags; -/* + im->cs.no_free = 0; + if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || + (im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) + im->cs.data = calloc(1, im->image->h * sizeof(unsigned char *) * 2); + /* evas_common_load_image_data_from_file(im_old); evas_common_image_colorspace_normalize(im); if (im_old->image->data) @@ -596,8 +607,9 @@ eng_image_size_set(void *data, void *image, int w, int h) evas_common_blit_rectangle(im_old, im, 0, 0, w, h, 0, 0); evas_common_cpu_end_opt(); } - */ + */ evas_common_image_unref(im_old); + evas_common_image_colorspace_dirty(im); } return im; } diff --git a/legacy/evas/src/modules/engines/software_x11/evas_outbuf.c b/legacy/evas/src/modules/engines/software_x11/evas_outbuf.c index dcbcadccc0..61b6e37cab 100644 --- a/legacy/evas/src/modules/engines/software_x11/evas_outbuf.c +++ b/legacy/evas/src/modules/engines/software_x11/evas_outbuf.c @@ -559,7 +559,7 @@ evas_software_x11_outbuf_debug_show(Outbuf * buf, Drawable draw, int x, int y, i XGetWindowAttributes(buf->priv.x.disp, root, &wattr); screen_num = XScreenNumberOfScreen(wattr.screen); } - for (i = 0; i < 10; i++) + for (i = 0; i < 20; i++) { XImage *xim; @@ -567,19 +567,19 @@ evas_software_x11_outbuf_debug_show(Outbuf * buf, Drawable draw, int x, int y, i BlackPixel(buf->priv.x.disp, screen_num)); XFillRectangle(buf->priv.x.disp, draw, buf->priv.x.gc, x, y, w, h); XSync(buf->priv.x.disp, False); - xim = - XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap); - if (xim) - XDestroyImage(xim); +// xim = +// XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap); +// if (xim) +// XDestroyImage(xim); XSync(buf->priv.x.disp, False); XSetForeground(buf->priv.x.disp, buf->priv.x.gc, WhitePixel(buf->priv.x.disp, screen_num)); XFillRectangle(buf->priv.x.disp, draw, buf->priv.x.gc, x, y, w, h); XSync(buf->priv.x.disp, False); - xim = - XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap); - if (xim) - XDestroyImage(xim); +// xim = +// XGetImage(buf->priv.x.disp, draw, x, y, w, h, 0xffffffff, ZPixmap); +// if (xim) +// XDestroyImage(xim); XSync(buf->priv.x.disp, False); } } diff --git a/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c b/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c index 51958fdf8d..9d99361eae 100644 --- a/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/xrender_x11/evas_engine.c @@ -645,6 +645,9 @@ eng_image_size_set(void *data, void *image, int w, int h) if (!image) return NULL; im_old = image; + if ((im_old->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || + (im_old->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) + w &= ~0x1; if ((im_old) && (im_old->w == w) && (im_old->h == h)) return image; if ((w <= 0) || (h <= 0))