forked from enlightenment/efl
evas/map: support aa in basic c computation.
This commit is contained in:
parent
215b52ecc1
commit
a3b3e1ecad
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue