From: ChunEon Park Date: Wed, 26 Nov 2014 06:12:25 +0000 (+0900) Subject: evas/map: support aa in basic c computation. X-Git-Tag: upstream/1.12.0+179+gc1eb5de~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a3b3e1ecad73f2da2e95d86670c336a474cff77f;p=platform%2Fupstream%2Fefl.git evas/map: support aa in basic c computation. --- diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index cfa6c72..9e67eac 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -350,6 +350,7 @@ lib/evas/common/evas_font_compress_draw.c \ lib/evas/common/evas_map_image_internal.c \ lib/evas/common/evas_map_image_core.c \ lib/evas/common/evas_map_image_loop.c \ +lib/evas/common/evas_map_image_aa.c \ lib/evas/common/evas_scale_smooth_scaler.c \ lib/evas/common/evas_scale_smooth_scaler_down.c \ lib/evas/common/evas_scale_smooth_scaler_downx.c \ diff --git a/src/lib/evas/common/evas_map_image.c b/src/lib/evas/common/evas_map_image.c index 0fa1f6c..8cc83d9 100644 --- a/src/lib/evas/common/evas_map_image.c +++ b/src/lib/evas/common/evas_map_image.c @@ -30,6 +30,8 @@ struct _Span struct _Line { Span span[2]; + int aa_cov[2]; + int aa_len[2]; }; static inline FPc @@ -82,6 +84,8 @@ _interpolated_clip_span(Span *s, int c1, int c2, Eina_Bool interp_col) } } +#include "evas_map_image_aa.c" + // 12.63 % of time - this can improve static void _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy EINA_UNUSED, int cw, int ch EINA_UNUSED) diff --git a/src/lib/evas/common/evas_map_image_aa.c b/src/lib/evas/common/evas_map_image_aa.c new file mode 100644 index 0000000..671e067 --- /dev/null +++ b/src/lib/evas/common/evas_map_image_aa.c @@ -0,0 +1,297 @@ +/* + * evas_map_image_aa.c + * + * Created on: Nov 21, 2014 + * Author: hermet + */ + +#define READY_TX() \ +{ \ + if (eidx == 0) \ + { \ + tx[0] = edge2.x; \ + tx[1] = spans[y].span[0].x[0]; \ + } \ + else \ + { \ + tx[0] = spans[y].span[0].x[1]; \ + tx[1] = edge2.x; \ + } \ +} + +#define READY_TX2() \ +{ \ + if (eidx == 0) \ + { \ + tx2[0] = edge2.x; \ + tx2[1] = edge1.x; \ + } \ + else \ + { \ + tx2[0] = edge1.x; \ + tx2[1] = edge2.x; \ + } \ +} + +#define PUSH_EDGES(xx) \ +{ \ + if (!leftover) \ + { \ + edge1.x = edge2.x; \ + edge1.y = edge2.y; \ + edge2.x = (xx); \ + edge2.y = y; \ + } \ + else \ + { \ + edge1.y = edge2.y; \ + edge2.y = y; \ + } \ + reset_tx2 = EINA_TRUE; \ +} + +//Vertical Inside Direction +#define VERT_INSIDE(rewind, y_advance) \ +{ \ + int cov_range = edge2.y - edge1.y; \ + int coverage = (256 / (cov_range + 1)); \ + int ry; \ + int val; \ + for (ry = 1; ry < ((rewind) + 1); ry++) \ + { \ + int ridx = (y - ry) + (y_advance); \ + if (spans[ridx].aa_len[eidx] > 1) continue; \ + if (eidx == 1) \ + val = (256 - (coverage * (ry + (cov_range - (rewind))))); \ + else \ + val = (coverage * (ry + (cov_range - (rewind)))); \ + if ((spans[ridx].aa_len[eidx] == 0) || \ + (val < spans[ridx].aa_cov[eidx])) \ + spans[ridx].aa_cov[eidx] = val; \ + spans[ridx].aa_len[eidx] = 1; \ + } \ + prev_aa = 4; \ +} + +//Vertical Outside Direction +#define VERT_OUTSIDE(rewind, y_advance, cov_range) \ +{ \ + int coverage = (256 / ((cov_range) + 1)); \ + int ry = 1; \ + for (; ry < ((rewind) + 1); ry++) \ + { \ + int ridx = (y - ry) + (y_advance); \ + if (spans[ridx].aa_len[(eidx)] > 1) continue; \ + spans[ridx].aa_len[(eidx)] = 1; \ + if (eidx == 1) \ + { \ + spans[ridx].aa_cov[(eidx)] = \ + (coverage * (ry + (cov_range - (rewind)))); \ + } \ + else \ + { \ + spans[ridx].aa_cov[(eidx)] = \ + (256 - (coverage * (ry + ((cov_range) - (rewind))))); \ + } \ + } \ + prev_aa = 2; \ +} + +//Horizontal Inside Direction +#define HORIZ_INSIDE(yy, xx, xx2) \ +{ \ + if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \ + { \ + spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \ + spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \ + } \ +} + +//Horizontal Outside Direction +#define HORIZ_OUTSIDE(yy, xx, xx2) \ +{ \ + if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \ + { \ + spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \ + spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \ + } \ +} + +static inline DATA32 +_aa_coverage_apply(Line *line, int ww, int w, DATA32 val) +{ + //Left Edge Anti Anliasing + if ((w - line->aa_len[0]) < ww) + { + return MUL_256((line->aa_cov[0] * (w - ww + 1)), val); + } + //Right Edge Anti Aliasing + if (line->aa_len[1] >= ww) + { + return MUL_256(256 - (line->aa_cov[1] * (line->aa_len[1] - ww + 1)), + val); + } + return val; +} + +void +_calc_aa_edges_internal(Line *spans, int eidx, int ystart, int yend) +{ + int y; + Evas_Coord_Point edge1 = { -1, -1 }; //prev-previous edge pixel + Evas_Coord_Point edge2 = { -1, -1 }; //previous edge pixel + + /* store larger to tx[0] between prev and current edge's x positions. */ + int tx[2] = {0, 0}; + + /* store lager to tx2[0] between edge1 and edge2's x positions. */ + int tx2[2] = {0, 0}; + + /* previous edge anti-aliased type. + 2: vertical outside + 4: vertical inside */ + int prev_aa = 0; + + Eina_Bool reset_tx2 = EINA_TRUE; + + yend -= ystart; + + //Find Start Edge + for (y = 0; y < yend; y++) + { + if (spans[y].span[0].x[0] == -1) continue; + edge1.x = edge2.x = spans[y].span[0].x[eidx]; + edge1.y = edge2.y = y; + break; + } + + //Calculates AA Edges + for (y++; y <= yend; y++) + { + Eina_Bool leftover = EINA_FALSE; + + if (spans[y].span[0].x[eidx] == -1) leftover = EINA_TRUE; + + if (!leftover) READY_TX() + + //Case1. Outside Incremental + if (tx[0] > tx[1]) + { + //Horizontal Edge + if ((y - edge2.y) == 1) + { + HORIZ_OUTSIDE(y, tx[0], tx[1]) + } + //Vertical Edge + else if (tx[0] > tx[1]) + { + VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y)) + + //Just in case: 1 pixel alias next to vertical edge? + if (abs(spans[(y + 1)].span[0].x[eidx] - + spans[y].span[0].x[eidx]) >= 1) + { + HORIZ_OUTSIDE(y, tx[0], tx[1]) + } + } + PUSH_EDGES(spans[y].span[0].x[eidx]) + } + //Case2. Inside Incremental + else if (tx[1] > tx[0]) + { + //Just in case: direction is reversed at the outside vertical edge? + if (prev_aa == 2) + { + VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y)) + edge1.x = spans[y - 1].span[0].x[eidx]; + edge1.y = y - 1; + edge2.x = spans[y].span[0].x[eidx]; + edge2.y = y; + } + else + PUSH_EDGES(spans[y].span[0].x[eidx]) + + /* Find next edge. We go forward 2 more index since this logic + computes aa edges by looking back in advance 2 spans. */ + for (y++; y <= (yend + 2); y++) + { + leftover = EINA_FALSE; + + if ((spans[y].span[0].x[eidx] == -1) || (y > yend)) + leftover = EINA_TRUE; + + if (!leftover) READY_TX() + if (reset_tx2) READY_TX2() + + //Case 1. Inside Direction + if (tx[1] > tx[0]) + { + //Horizontal Edge + if ((edge2.y - edge1.y) == 1) + { + HORIZ_INSIDE(edge1.y, tx2[0], tx2[1]); + } + //Vertical Edge + else if ((tx2[0] - tx2[1]) == 1) + { + VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y)) + } + //Just in case: Right Side Square Edge...? + else if (prev_aa == 4) + { + VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y)) + if ((y - edge2.y) == 1) + { + HORIZ_INSIDE((edge2.y - 1), edge2.x, + spans[y].span[0].x[eidx]); + } + } + PUSH_EDGES(spans[y].span[0].x[eidx]) + } + //Case 2. Reversed. Outside Direction + else if (tx[1] < tx[0]) + { + //Horizontal Edge + if ((edge2.y - edge1.y) == 1) + HORIZ_INSIDE(edge1.y, tx2[0], tx2[1]) + //Vertical Edge + else + VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y)) + + PUSH_EDGES(spans[y].span[0].x[eidx]) + break; + } + } + } + } + + y = yend; + + //Leftovers for verticals. + if (prev_aa == 2) + { + if (((eidx == 0) && (edge1.x > edge2.x)) || + ((eidx == 1) && (edge1.x < edge2.x))) + VERT_OUTSIDE((y - edge2.y + 1), 1, (edge2.y - edge1.y)); + } + else if (prev_aa == 4) + { + if (((eidx == 0) && (edge1.x < edge2.x)) || + ((eidx == 1) && (edge1.x > edge2.x))) + { + VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y)) + VERT_INSIDE((y - edge2.y) + 1, 1); + } + } +} + +static void +_calc_aa_edges(Line *spans, int ystart, int yend) +{ + //FIXME: support 2 span case. + + //left side + _calc_aa_edges_internal(spans, 0, ystart, yend); + //right side + _calc_aa_edges_internal(spans, 1, ystart, yend); +} diff --git a/src/lib/evas/common/evas_map_image_internal.c b/src/lib/evas/common/evas_map_image_internal.c index 331c3dd..ba00981 100644 --- a/src/lib/evas/common/evas_map_image_internal.c +++ b/src/lib/evas/common/evas_map_image_internal.c @@ -76,12 +76,20 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst, // calculate the spans list _calc_spans(p, spans, ystart, yend, cx, cy, cw, ch); + // calculate anti alias edges + if (anti_alias) _calc_aa_edges(spans, ystart, yend); + // walk through spans and render // if operation is solid, bypass buf and draw func and draw direct to dst direct = 0; + + + /* FIXME: even if anti-alias is enabled, only edges may require the + pixels composition. we can optimize it. */ + if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) && - (mul_col == 0xffffffff) && (!havea)) + (mul_col == 0xffffffff) && (!havea) && (!anti_alias)) { direct = 1; } @@ -96,9 +104,10 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst, func = evas_common_gfx_func_composite_pixel_color_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, mul_col, dst->cache_entry.flags.alpha, cw, render_op); else func = evas_common_gfx_func_composite_pixel_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dst->cache_entry.flags.alpha, cw, render_op); - src->cache_entry.flags.alpha = pa; - } + if (anti_alias) src->cache_entry.flags.alpha = EINA_TRUE; + else src->cache_entry.flags.alpha = pa; + } if (havecol == 0) { #undef COLMUL diff --git a/src/lib/evas/common/evas_map_image_loop.c b/src/lib/evas/common/evas_map_image_loop.c index 971d986..f0bd332 100644 --- a/src/lib/evas/common/evas_map_image_loop.c +++ b/src/lib/evas/common/evas_map_image_loop.c @@ -31,12 +31,13 @@ while (ww > 0) { + DATA32 val1 = 0x00000000; # ifdef COLBLACK *d = 0xff000000; // col # else //COLBLACK FPc uu1, vv1, uu2, vv2; FPc rv, ru; - DATA32 val1, val2, val3, val4; + DATA32 val2, val3, val4; uu1 = u; if (uu1 < 0) uu1 = 0; @@ -156,19 +157,19 @@ val1 = INTERP_256(rv, val3, val1); // col # ifdef COLMUL # ifdef COLSAME - *d = MUL4_SYM(c1, val1); + val1 = MUL4_SYM(c1, val1); # else //COLSAME val2 = INTERP_256((cv >> 16), c2, c1); // col - *d = MUL4_SYM(val2, val1); // col + val1 = MUL4_SYM(val2, val1); // col cv += cd; // col # endif //COLSAME -# else - *d = val1; # endif //COLMUL # endif //SCALE_USING_MMX u += ud; v += vd; # endif //COLBLACK + if (anti_alias) val1 = _aa_coverage_apply(line, ww, w, val1); + *d = val1; d++; ww--; } @@ -200,9 +201,9 @@ while (ww > 0) { + DATA32 val1 = 0x00000000; # ifdef COLMUL # ifndef COLBLACK - DATA32 val1; # ifdef COLSAME # else DATA32 cval; // col @@ -211,7 +212,7 @@ # endif //COLMUL # ifdef COLBLACK - *d = 0xff000000; // col + val1 = 0xff000000; // col # else //COLBLACK s = sp + ((v >> (FP + FPI)) * sw) + (u >> (FP + FPI)); # ifdef COLMUL @@ -225,7 +226,7 @@ MUL4_SYM_NEON(d0, d1, d4) VMOV_R2M_NEON(q0, d0, d); # else - *d = MUL4_SYM(c1, val1); + val1 = MUL4_SYM(c1, val1); # endif //SCALE_USING_NEON # else //COLSAME /* XXX: this neon is broken! :( FIXME @@ -242,18 +243,20 @@ # else */ cval = INTERP_256((cv >> 16), c2, c1); // col - *d = MUL4_SYM(cval, val1); + val1 = MUL4_SYM(cval, val1); cv += cd; // col /* # endif */ # endif //COLSAME # else //COLMUL - *d = *s; + val1 = *s; # endif //COLMUL u += ud; v += vd; # endif //COLBLACK + if (anti_alias) val1 = _aa_coverage_apply(line, ww, w, val1); + *d = val1; d++; ww--; }