summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChunEon Park <hermet@hermet.pe.kr>2014-11-26 15:12:25 +0900
committerChunEon Park <hermet@hermet.pe.kr>2014-11-26 15:12:25 +0900
commita3b3e1ecad73f2da2e95d86670c336a474cff77f (patch)
tree2460f9ce0a6ceaf0ac1218628d02c753f9d53b17
parent215b52ecc108b2b13814534d75565152e8c0973a (diff)
evas/map: support aa in basic c computation.
-rw-r--r--src/Makefile_Evas.am1
-rw-r--r--src/lib/evas/common/evas_map_image.c4
-rw-r--r--src/lib/evas/common/evas_map_image_aa.c297
-rw-r--r--src/lib/evas/common/evas_map_image_internal.c15
-rw-r--r--src/lib/evas/common/evas_map_image_loop.c23
5 files changed, 327 insertions, 13 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index cfa6c72264..9e67eacb8d 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -350,6 +350,7 @@ lib/evas/common/evas_font_compress_draw.c \
350lib/evas/common/evas_map_image_internal.c \ 350lib/evas/common/evas_map_image_internal.c \
351lib/evas/common/evas_map_image_core.c \ 351lib/evas/common/evas_map_image_core.c \
352lib/evas/common/evas_map_image_loop.c \ 352lib/evas/common/evas_map_image_loop.c \
353lib/evas/common/evas_map_image_aa.c \
353lib/evas/common/evas_scale_smooth_scaler.c \ 354lib/evas/common/evas_scale_smooth_scaler.c \
354lib/evas/common/evas_scale_smooth_scaler_down.c \ 355lib/evas/common/evas_scale_smooth_scaler_down.c \
355lib/evas/common/evas_scale_smooth_scaler_downx.c \ 356lib/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 0fa1f6c182..8cc83d9186 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
30struct _Line 30struct _Line
31{ 31{
32 Span span[2]; 32 Span span[2];
33 int aa_cov[2];
34 int aa_len[2];
33}; 35};
34 36
35static inline FPc 37static inline FPc
@@ -82,6 +84,8 @@ _interpolated_clip_span(Span *s, int c1, int c2, Eina_Bool interp_col)
82 } 84 }
83} 85}
84 86
87#include "evas_map_image_aa.c"
88
85// 12.63 % of time - this can improve 89// 12.63 % of time - this can improve
86static void 90static void
87_calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy EINA_UNUSED, int cw, int ch EINA_UNUSED) 91_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 0000000000..671e067900
--- /dev/null
+++ b/src/lib/evas/common/evas_map_image_aa.c
@@ -0,0 +1,297 @@
1/*
2 * evas_map_image_aa.c
3 *
4 * Created on: Nov 21, 2014
5 * Author: hermet
6 */
7
8#define READY_TX() \
9{ \
10 if (eidx == 0) \
11 { \
12 tx[0] = edge2.x; \
13 tx[1] = spans[y].span[0].x[0]; \
14 } \
15 else \
16 { \
17 tx[0] = spans[y].span[0].x[1]; \
18 tx[1] = edge2.x; \
19 } \
20}
21
22#define READY_TX2() \
23{ \
24 if (eidx == 0) \
25 { \
26 tx2[0] = edge2.x; \
27 tx2[1] = edge1.x; \
28 } \
29 else \
30 { \
31 tx2[0] = edge1.x; \
32 tx2[1] = edge2.x; \
33 } \
34}
35
36#define PUSH_EDGES(xx) \
37{ \
38 if (!leftover) \
39 { \
40 edge1.x = edge2.x; \
41 edge1.y = edge2.y; \
42 edge2.x = (xx); \
43 edge2.y = y; \
44 } \
45 else \
46 { \
47 edge1.y = edge2.y; \
48 edge2.y = y; \
49 } \
50 reset_tx2 = EINA_TRUE; \
51}
52
53//Vertical Inside Direction
54#define VERT_INSIDE(rewind, y_advance) \
55{ \
56 int cov_range = edge2.y - edge1.y; \
57 int coverage = (256 / (cov_range + 1)); \
58 int ry; \
59 int val; \
60 for (ry = 1; ry < ((rewind) + 1); ry++) \
61 { \
62 int ridx = (y - ry) + (y_advance); \
63 if (spans[ridx].aa_len[eidx] > 1) continue; \
64 if (eidx == 1) \
65 val = (256 - (coverage * (ry + (cov_range - (rewind))))); \
66 else \
67 val = (coverage * (ry + (cov_range - (rewind)))); \
68 if ((spans[ridx].aa_len[eidx] == 0) || \
69 (val < spans[ridx].aa_cov[eidx])) \
70 spans[ridx].aa_cov[eidx] = val; \
71 spans[ridx].aa_len[eidx] = 1; \
72 } \
73 prev_aa = 4; \
74}
75
76//Vertical Outside Direction
77#define VERT_OUTSIDE(rewind, y_advance, cov_range) \
78{ \
79 int coverage = (256 / ((cov_range) + 1)); \
80 int ry = 1; \
81 for (; ry < ((rewind) + 1); ry++) \
82 { \
83 int ridx = (y - ry) + (y_advance); \
84 if (spans[ridx].aa_len[(eidx)] > 1) continue; \
85 spans[ridx].aa_len[(eidx)] = 1; \
86 if (eidx == 1) \
87 { \
88 spans[ridx].aa_cov[(eidx)] = \
89 (coverage * (ry + (cov_range - (rewind)))); \
90 } \
91 else \
92 { \
93 spans[ridx].aa_cov[(eidx)] = \
94 (256 - (coverage * (ry + ((cov_range) - (rewind))))); \
95 } \
96 } \
97 prev_aa = 2; \
98}
99
100//Horizontal Inside Direction
101#define HORIZ_INSIDE(yy, xx, xx2) \
102{ \
103 if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \
104 { \
105 spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \
106 spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \
107 } \
108}
109
110//Horizontal Outside Direction
111#define HORIZ_OUTSIDE(yy, xx, xx2) \
112{ \
113 if (((xx) - (xx2)) > spans[(yy)].aa_len[(eidx)]) \
114 { \
115 spans[(yy)].aa_len[(eidx)] = ((xx) - (xx2)); \
116 spans[(yy)].aa_cov[(eidx)] = (256 / (spans[(yy)].aa_len[(eidx)] + 1)); \
117 } \
118}
119
120static inline DATA32
121_aa_coverage_apply(Line *line, int ww, int w, DATA32 val)
122{
123 //Left Edge Anti Anliasing
124 if ((w - line->aa_len[0]) < ww)
125 {
126 return MUL_256((line->aa_cov[0] * (w - ww + 1)), val);
127 }
128 //Right Edge Anti Aliasing
129 if (line->aa_len[1] >= ww)
130 {
131 return MUL_256(256 - (line->aa_cov[1] * (line->aa_len[1] - ww + 1)),
132 val);
133 }
134 return val;
135}
136
137void
138_calc_aa_edges_internal(Line *spans, int eidx, int ystart, int yend)
139{
140 int y;
141 Evas_Coord_Point edge1 = { -1, -1 }; //prev-previous edge pixel
142 Evas_Coord_Point edge2 = { -1, -1 }; //previous edge pixel
143
144 /* store larger to tx[0] between prev and current edge's x positions. */
145 int tx[2] = {0, 0};
146
147 /* store lager to tx2[0] between edge1 and edge2's x positions. */
148 int tx2[2] = {0, 0};
149
150 /* previous edge anti-aliased type.
151 2: vertical outside
152 4: vertical inside */
153 int prev_aa = 0;
154
155 Eina_Bool reset_tx2 = EINA_TRUE;
156
157 yend -= ystart;
158
159 //Find Start Edge
160 for (y = 0; y < yend; y++)
161 {
162 if (spans[y].span[0].x[0] == -1) continue;
163 edge1.x = edge2.x = spans[y].span[0].x[eidx];
164 edge1.y = edge2.y = y;
165 break;
166 }
167
168 //Calculates AA Edges
169 for (y++; y <= yend; y++)
170 {
171 Eina_Bool leftover = EINA_FALSE;
172
173 if (spans[y].span[0].x[eidx] == -1) leftover = EINA_TRUE;
174
175 if (!leftover) READY_TX()
176
177 //Case1. Outside Incremental
178 if (tx[0] > tx[1])
179 {
180 //Horizontal Edge
181 if ((y - edge2.y) == 1)
182 {
183 HORIZ_OUTSIDE(y, tx[0], tx[1])
184 }
185 //Vertical Edge
186 else if (tx[0] > tx[1])
187 {
188 VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y))
189
190 //Just in case: 1 pixel alias next to vertical edge?
191 if (abs(spans[(y + 1)].span[0].x[eidx] -
192 spans[y].span[0].x[eidx]) >= 1)
193 {
194 HORIZ_OUTSIDE(y, tx[0], tx[1])
195 }
196 }
197 PUSH_EDGES(spans[y].span[0].x[eidx])
198 }
199 //Case2. Inside Incremental
200 else if (tx[1] > tx[0])
201 {
202 //Just in case: direction is reversed at the outside vertical edge?
203 if (prev_aa == 2)
204 {
205 VERT_OUTSIDE((y - edge2.y), 0, (y - edge2.y))
206 edge1.x = spans[y - 1].span[0].x[eidx];
207 edge1.y = y - 1;
208 edge2.x = spans[y].span[0].x[eidx];
209 edge2.y = y;
210 }
211 else
212 PUSH_EDGES(spans[y].span[0].x[eidx])
213
214 /* Find next edge. We go forward 2 more index since this logic
215 computes aa edges by looking back in advance 2 spans. */
216 for (y++; y <= (yend + 2); y++)
217 {
218 leftover = EINA_FALSE;
219
220 if ((spans[y].span[0].x[eidx] == -1) || (y > yend))
221 leftover = EINA_TRUE;
222
223 if (!leftover) READY_TX()
224 if (reset_tx2) READY_TX2()
225
226 //Case 1. Inside Direction
227 if (tx[1] > tx[0])
228 {
229 //Horizontal Edge
230 if ((edge2.y - edge1.y) == 1)
231 {
232 HORIZ_INSIDE(edge1.y, tx2[0], tx2[1]);
233 }
234 //Vertical Edge
235 else if ((tx2[0] - tx2[1]) == 1)
236 {
237 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
238 }
239 //Just in case: Right Side Square Edge...?
240 else if (prev_aa == 4)
241 {
242 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
243 if ((y - edge2.y) == 1)
244 {
245 HORIZ_INSIDE((edge2.y - 1), edge2.x,
246 spans[y].span[0].x[eidx]);
247 }
248 }
249 PUSH_EDGES(spans[y].span[0].x[eidx])
250 }
251 //Case 2. Reversed. Outside Direction
252 else if (tx[1] < tx[0])
253 {
254 //Horizontal Edge
255 if ((edge2.y - edge1.y) == 1)
256 HORIZ_INSIDE(edge1.y, tx2[0], tx2[1])
257 //Vertical Edge
258 else
259 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
260
261 PUSH_EDGES(spans[y].span[0].x[eidx])
262 break;
263 }
264 }
265 }
266 }
267
268 y = yend;
269
270 //Leftovers for verticals.
271 if (prev_aa == 2)
272 {
273 if (((eidx == 0) && (edge1.x > edge2.x)) ||
274 ((eidx == 1) && (edge1.x < edge2.x)))
275 VERT_OUTSIDE((y - edge2.y + 1), 1, (edge2.y - edge1.y));
276 }
277 else if (prev_aa == 4)
278 {
279 if (((eidx == 0) && (edge1.x < edge2.x)) ||
280 ((eidx == 1) && (edge1.x > edge2.x)))
281 {
282 VERT_INSIDE((edge2.y - edge1.y), -(y - edge2.y))
283 VERT_INSIDE((y - edge2.y) + 1, 1);
284 }
285 }
286}
287
288static void
289_calc_aa_edges(Line *spans, int ystart, int yend)
290{
291 //FIXME: support 2 span case.
292
293 //left side
294 _calc_aa_edges_internal(spans, 0, ystart, yend);
295 //right side
296 _calc_aa_edges_internal(spans, 1, ystart, yend);
297}
diff --git a/src/lib/evas/common/evas_map_image_internal.c b/src/lib/evas/common/evas_map_image_internal.c
index 331c3dd77c..ba00981319 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,
76 // calculate the spans list 76 // calculate the spans list
77 _calc_spans(p, spans, ystart, yend, cx, cy, cw, ch); 77 _calc_spans(p, spans, ystart, yend, cx, cy, cw, ch);
78 78
79 // calculate anti alias edges
80 if (anti_alias) _calc_aa_edges(spans, ystart, yend);
81
79 // walk through spans and render 82 // walk through spans and render
80 83
81 // if operation is solid, bypass buf and draw func and draw direct to dst 84 // if operation is solid, bypass buf and draw func and draw direct to dst
82 direct = 0; 85 direct = 0;
86
87
88 /* FIXME: even if anti-alias is enabled, only edges may require the
89 pixels composition. we can optimize it. */
90
83 if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) && 91 if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) &&
84 (mul_col == 0xffffffff) && (!havea)) 92 (mul_col == 0xffffffff) && (!havea) && (!anti_alias))
85 { 93 {
86 direct = 1; 94 direct = 1;
87 } 95 }
@@ -96,9 +104,10 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
96 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); 104 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);
97 else 105 else
98 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); 106 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);
99 src->cache_entry.flags.alpha = pa;
100 }
101 107
108 if (anti_alias) src->cache_entry.flags.alpha = EINA_TRUE;
109 else src->cache_entry.flags.alpha = pa;
110 }
102 if (havecol == 0) 111 if (havecol == 0)
103 { 112 {
104#undef COLMUL 113#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 971d98679c..f0bd3323c8 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 @@
31 31
32 while (ww > 0) 32 while (ww > 0)
33 { 33 {
34 DATA32 val1 = 0x00000000;
34# ifdef COLBLACK 35# ifdef COLBLACK
35 *d = 0xff000000; // col 36 *d = 0xff000000; // col
36# else //COLBLACK 37# else //COLBLACK
37 FPc uu1, vv1, uu2, vv2; 38 FPc uu1, vv1, uu2, vv2;
38 FPc rv, ru; 39 FPc rv, ru;
39 DATA32 val1, val2, val3, val4; 40 DATA32 val2, val3, val4;
40 41
41 uu1 = u; 42 uu1 = u;
42 if (uu1 < 0) uu1 = 0; 43 if (uu1 < 0) uu1 = 0;
@@ -156,19 +157,19 @@
156 val1 = INTERP_256(rv, val3, val1); // col 157 val1 = INTERP_256(rv, val3, val1); // col
157# ifdef COLMUL 158# ifdef COLMUL
158# ifdef COLSAME 159# ifdef COLSAME
159 *d = MUL4_SYM(c1, val1); 160 val1 = MUL4_SYM(c1, val1);
160# else //COLSAME 161# else //COLSAME
161 val2 = INTERP_256((cv >> 16), c2, c1); // col 162 val2 = INTERP_256((cv >> 16), c2, c1); // col
162 *d = MUL4_SYM(val2, val1); // col 163 val1 = MUL4_SYM(val2, val1); // col
163 cv += cd; // col 164 cv += cd; // col
164# endif //COLSAME 165# endif //COLSAME
165# else
166 *d = val1;
167# endif //COLMUL 166# endif //COLMUL
168# endif //SCALE_USING_MMX 167# endif //SCALE_USING_MMX
169 u += ud; 168 u += ud;
170 v += vd; 169 v += vd;
171# endif //COLBLACK 170# endif //COLBLACK
171 if (anti_alias) val1 = _aa_coverage_apply(line, ww, w, val1);
172 *d = val1;
172 d++; 173 d++;
173 ww--; 174 ww--;
174 } 175 }
@@ -200,9 +201,9 @@
200 201
201 while (ww > 0) 202 while (ww > 0)
202 { 203 {
204 DATA32 val1 = 0x00000000;
203# ifdef COLMUL 205# ifdef COLMUL
204# ifndef COLBLACK 206# ifndef COLBLACK
205 DATA32 val1;
206# ifdef COLSAME 207# ifdef COLSAME
207# else 208# else
208 DATA32 cval; // col 209 DATA32 cval; // col
@@ -211,7 +212,7 @@
211# endif //COLMUL 212# endif //COLMUL
212 213
213# ifdef COLBLACK 214# ifdef COLBLACK
214 *d = 0xff000000; // col 215 val1 = 0xff000000; // col
215# else //COLBLACK 216# else //COLBLACK
216 s = sp + ((v >> (FP + FPI)) * sw) + (u >> (FP + FPI)); 217 s = sp + ((v >> (FP + FPI)) * sw) + (u >> (FP + FPI));
217# ifdef COLMUL 218# ifdef COLMUL
@@ -225,7 +226,7 @@
225 MUL4_SYM_NEON(d0, d1, d4) 226 MUL4_SYM_NEON(d0, d1, d4)
226 VMOV_R2M_NEON(q0, d0, d); 227 VMOV_R2M_NEON(q0, d0, d);
227# else 228# else
228 *d = MUL4_SYM(c1, val1); 229 val1 = MUL4_SYM(c1, val1);
229# endif //SCALE_USING_NEON 230# endif //SCALE_USING_NEON
230# else //COLSAME 231# else //COLSAME
231/* XXX: this neon is broken! :( FIXME 232/* XXX: this neon is broken! :( FIXME
@@ -242,18 +243,20 @@
242# else 243# else
243 */ 244 */
244 cval = INTERP_256((cv >> 16), c2, c1); // col 245 cval = INTERP_256((cv >> 16), c2, c1); // col
245 *d = MUL4_SYM(cval, val1); 246 val1 = MUL4_SYM(cval, val1);
246 cv += cd; // col 247 cv += cd; // col
247/* 248/*
248# endif 249# endif
249 */ 250 */
250# endif //COLSAME 251# endif //COLSAME
251# else //COLMUL 252# else //COLMUL
252 *d = *s; 253 val1 = *s;
253# endif //COLMUL 254# endif //COLMUL
254 u += ud; 255 u += ud;
255 v += vd; 256 v += vd;
256# endif //COLBLACK 257# endif //COLBLACK
258 if (anti_alias) val1 = _aa_coverage_apply(line, ww, w, val1);
259 *d = val1;
257 d++; 260 d++;
258 ww--; 261 ww--;
259 } 262 }