clean up map - move to #included worker and add mmx - just copied from normal

image scaler actually.



SVN revision: 43336
This commit is contained in:
Carsten Haitzler 2009-10-29 06:52:51 +00:00
parent e867666096
commit 422faf09fd
4 changed files with 415 additions and 343 deletions

View File

@ -632,67 +632,71 @@ evas_render_updates_internal(Evas *e,
if (!((obj->func->can_map) && (obj->func->can_map(obj))) &&
((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)))
{
const Evas_Map_Point *p, *p_end;
RGBA_Map_Point pts[4], *pt;
void *ctx;
ctx = e->engine.func->context_new(e->engine.data.output);
if (!obj->cur.map->surface)
if ((obj->cur.map->normal_geometry.w > 0) &&
(obj->cur.map->normal_geometry.h > 0))
{
obj->cur.map->surface =
obj->layer->evas->engine.func->image_map_surface_new
const Evas_Map_Point *p, *p_end;
RGBA_Map_Point pts[4], *pt;
void *ctx;
ctx = e->engine.func->context_new(e->engine.data.output);
if (!obj->cur.map->surface)
{
obj->cur.map->surface =
obj->layer->evas->engine.func->image_map_surface_new
(e->engine.data.output,
obj->cur.map->normal_geometry.w,
obj->cur.map->normal_geometry.h,
1);
}
if (obj->smart.smart)
{
// FIXME: doesnt work yet
// smart object. draw all children to
// surface (and if they are mapped...
// recurse)
evas_render_updates_internal(e, obj, 0, 1);
}
else
{
obj->func->render(obj,
e->engine.data.output,
ctx,
obj->cur.map->surface,
-obj->cur.cache.clip.x,
-obj->cur.cache.clip.y
);
}
e->engine.func->context_free(e->engine.data.output, ctx);
p = obj->cur.map->points;
p_end = p + 4;
pt = pts;
for (; p < p_end; p++, pt++)
{
pt->x = (p->x + off_x) << FP;
pt->y = (p->y + off_y) << FP;
pt->z = (p->z) << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
}
obj->layer->evas->engine.func->image_map4_draw
(e->engine.data.output,
obj->cur.map->normal_geometry.w,
obj->cur.map->normal_geometry.h,
1);
e->engine.data.context,
surface,
obj->cur.map->surface,
pts,
1, // smooth? (on for now)
0);
// FIXME: needs to cache these maps and
// keep them only rendering updates
obj->layer->evas->engine.func->image_map_surface_free
(e->engine.data.output,
obj->cur.map->surface);
obj->cur.map->surface = NULL;
}
if (obj->smart.smart)
{
// FIXME: doesnt work yet
// smart object. draw all children to
// surface (and if they are mapped...
// recurse)
evas_render_updates_internal(e, obj, 0, 1);
}
else
{
obj->func->render(obj,
e->engine.data.output,
ctx,
obj->cur.map->surface,
-obj->cur.cache.clip.x,
-obj->cur.cache.clip.y
);
}
e->engine.func->context_free(e->engine.data.output, ctx);
p = obj->cur.map->points;
p_end = p + 4;
pt = pts;
for (; p < p_end; p++, pt++)
{
pt->x = (p->x + off_x) << FP;
pt->y = (p->y + off_y) << FP;
pt->z = (p->z) << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
}
obj->layer->evas->engine.func->image_map4_draw
(e->engine.data.output,
e->engine.data.context,
surface,
obj->cur.map->surface,
pts,
1, // smooth? (on for now)
0);
// FIXME: needs to cache these maps and
// keep them only rendering updates
obj->layer->evas->engine.func->image_map_surface_free
(e->engine.data.output,
obj->cur.map->surface);
obj->cur.map->surface = NULL;
}
else
{

View File

@ -108,7 +108,8 @@ evas_scale_smooth_scaler_noscale.c \
evas_scale_smooth_scaler_up.c \
evas_scale_span.h \
evas_pipe.h \
evas_intl_utils.h
evas_intl_utils.h \
evas_map_image_internal.c
libevas_engine_common_la_DEPENDENCIES = \
$(top_builddir)/config.h

View File

@ -5,6 +5,13 @@
#include "evas_common.h"
#include "evas_blend_private.h"
#ifdef BUILD_SCALE_SMOOTH
# ifdef BUILD_MMX
# undef SCALE_USING_MMX
# define SCALE_USING_MMX
# endif
#endif
#define FPI 8
#define FPI1 (1 << (FPI))
#define FPIH (1 << (FPI - 1))
@ -26,12 +33,6 @@ struct _Line
Span span[2];
};
static void
evas_common_map4_rgba_internal(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
RGBA_Map_Point *p,
int smooth, int level);
static FPc
_interp(int x1, int x2, int p, FPc u1, FPc u2)
{
@ -63,47 +64,6 @@ _limit(Span *s, int c1, int c2)
}
}
EAPI void
evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
RGBA_Map_Point *p,
int smooth, int level)
{
Cutout_Rects *rects;
Cutout_Rect *r;
int c, cx, cy, cw, ch;
int i;
if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
evas_cache_image_load_data(&src->cache_entry);
evas_common_image_colorspace_normalize(src);
if (!src->image.data) return;
if (!dc->cutout.rects)
{
evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
return;
}
/* save out clip info */
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
/* our clip is 0 size.. abort */
if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
{
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
return;
}
rects = evas_common_draw_context_apply_cutouts(dc);
for (i = 0; i < rects->active; ++i)
{
r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
}
evas_common_draw_context_apply_clear_cutouts(rects);
/* restore clip info */
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
}
// 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, int cw, int ch)
@ -279,249 +239,78 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
}
}
// 66.74 % of time
static void
evas_common_map4_rgba_internal(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
RGBA_Map_Point *p,
int smooth, int level)
#ifdef BUILD_SCALE_SMOOTH
# ifdef BUILD_MMX
# undef FUNC_NAME
# define FUNC_NAME evas_common_map4_rgba_internal_mmx
# undef SCALE_USING_MMX
# define SCALE_USING_MMX
# include "evas_map_image_internal.c"
# endif
# ifdef BUILD_C
# undef FUNC_NAME
# define FUNC_NAME evas_common_map4_rgba_internal
# undef SCALE_USING_MMX
# include "evas_map_image_internal.c"
# endif
#endif
EAPI void
evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
RGBA_Map_Point *p,
int smooth, int level)
{
int i;
int c, cx, cy, cw, ch;
int ytop, ybottom, ystart, yend, y, yp, sw, sh, shp, swp, direct;
Line *spans;
DATA32 *buf, *sp;
RGBA_Gfx_Func func;
// get the clip
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
if (!c)
#ifdef BUILD_MMX
int mmx, sse, sse2;
#endif
Cutout_Rects *rects;
Cutout_Rect *r;
int c, cx, cy, cw, ch;
int i;
if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
evas_cache_image_load_data(&src->cache_entry);
evas_common_image_colorspace_normalize(src);
if (!src->image.data) return;
evas_common_cpu_can_do(&mmx, &sse, &sse2);
if (!dc->cutout.rects)
{
cx = 0;
cy = 0;
cw = dst->cache_entry.w;
ch = dst->cache_entry.h;
}
// find y yop line and y bottom line
ytop = p[0].y;
for (i = 1; i < 4; i++)
{
if (p[i].y < ytop) ytop = p[i].y;
}
ybottom = p[0].y;
for (i = 1; i < 4; i++)
{
if (p[i].y > ybottom) ybottom = p[i].y;
}
// convert to screen space from fixed point
ytop = ytop >> FP;
ybottom = ybottom >> FP;
// if its outside the clip vertical bounds - don't bother
if ((ytop >= (cy + ch)) || (ybottom < cy)) return;
// limit to the clip vertical bounds
if (ytop < cy) ystart = cy;
else ystart = ytop;
if (ybottom >= (cy + ch)) yend = (cy + ch) - 1;
else yend = ybottom;
// get some source image information
sp = src->image.data;
sw = src->cache_entry.w;
swp = sw << (FP + FPI);
shp = src->cache_entry.h << (FP + FPI);
// limit u,v coords of points to be within the source image
for (i = 0; i < 4; i++)
{
if (p[i].u < 0) p[i].u = 0;
else if (p[i].u > (src->cache_entry.w << FP))
p[i].u = src->cache_entry.w << FP;
if (p[i].v < 0) p[i].v = 0;
else if (p[i].v > (src->cache_entry.h << FP))
p[i].v = src->cache_entry.h << FP;
}
// allocate some spans to hold out span list
spans = alloca((yend - ystart + 1) * sizeof(Line));
if (!spans) return;
memset(spans, 0, (yend - ystart + 1) * sizeof(Line));
// calculate the spans list
_calc_spans(p, spans, ystart, yend, cx, cy, cw, ch);
// walk through spans and render
// if operation is solid, bypass buf and draw func and draw direct to dst
direct = 0;
if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) &&
(!dc->mul.use))
direct = 1;
else
{
buf = alloca(cw * sizeof(DATA32));
if (!buf) return;
if (dc->mul.use)
func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, cw, dc->render_op);
#ifdef BUILD_MMX
if (mmx)
evas_common_map4_rgba_internal_mmx(src, dst, dc, p, smooth, level);
else
func = evas_common_gfx_func_composite_pixel_span_get(src, dst, cw, dc->render_op);
#endif
#ifdef BUILD_C
evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
#endif
return;
}
if (smooth)
/* save out clip info */
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
/* our clip is 0 size.. abort */
if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd, dv;
DATA32 *d, *s, *so[4], val1, val2;
yp = y - ystart;
for (i = 0; i < 2; i++)
{
if (spans[yp].span[i].x1 >= 0)
{
long long tl;
x = spans[yp].span[i].x1;
w = (spans[yp].span[i].x2 - x);
if (w <= 0) continue;
dv = (spans[yp].span[i].o2 - spans[yp].span[i].o1);
ww = w;
u = spans[yp].span[i].u[0] << FPI;
v = spans[yp].span[i].v[0] << FPI;
ud = ((spans[yp].span[i].u[1] << FPI) - u) / w;
vd = ((spans[yp].span[i].v[1] << FPI) - v) / w;
tl = (long long)ud * (w << FP);
tl = tl / dv;
ud = tl;
u -= (ud * (spans[yp].span[i].o1 - (spans[yp].span[i].x1 << FP))) / FP1;
tl = (long long)vd * (w << FP);
tl = tl / dv;
vd = tl;
v -= (vd * (spans[yp].span[i].o1 - (spans[yp].span[i].x1 << FP))) / FP1;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
FPc u1, v1, u2, v2;
FPc rv, ru;
DATA32 vala, valb, val1, val2;
u1 = u;
if (u1 < 0) u1 = 0;
else if (u1 >= swp) u1 = swp - 1;
v1 = v;
if (v1 < 0) v1 = 0;
else if (v1 >= shp) v1 = shp - 1;
u2 = u1 + FPFPI1;
if (u2 >= swp) u2 = swp - 1;
v2 = v1 + FPFPI1;
if (v2 >= shp) v2 = shp - 1;
ru = (u >> (FP + FPI - 8)) & 0xff;
rv = (v >> (FP + FPI - 8)) & 0xff;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val1 = *s;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val2 = *s;
vala = INTERP_256(ru, val2, val1);
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val1 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val2 = *s;
valb = INTERP_256(ru, val2, val1);
*d++ = INTERP_256(rv, valb, vala);
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
return;
}
else
rects = evas_common_draw_context_apply_cutouts(dc);
for (i = 0; i < rects->active; ++i)
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd;
DATA32 *d, *s;
yp = y - ystart;
for (i = 0; i < 2; i++)
{
if (spans[yp].span[i].x1 >= 0)
{
x = spans[yp].span[i].x1;
w = (spans[yp].span[i].x2 - x);
if (w <= 0) continue;
ww = w;
u = spans[yp].span[i].u[0] << FPI;
v = spans[yp].span[i].v[0] << FPI;
ud = ((spans[yp].span[i].u[1] << FPI) - u) / w;
vd = ((spans[yp].span[i].v[1] << FPI) - v) / w;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
s = sp + ((v >> (FP + FPI)) * sw) +
(u >> (FP + FPI));
*d++ = *s;
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
#ifdef BUILD_MMX
if (mmx)
evas_common_map4_rgba_internal_mmx(src, dst, dc, p, smooth, level);
else
#endif
#ifdef BUILD_C
evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
#endif
}
evas_common_draw_context_apply_clear_cutouts(rects);
/* restore clip info */
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
}

View File

@ -0,0 +1,278 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
// 66.74 % of time
static void
FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
RGBA_Map_Point *p,
int smooth, int level)
{
int i;
int c, cx, cy, cw, ch;
int ytop, ybottom, ystart, yend, y, sw, sh, shp, swp, direct;
Line *spans;
DATA32 *buf, *sp;
RGBA_Gfx_Func func;
// get the clip
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
if (!c)
{
cx = 0;
cy = 0;
cw = dst->cache_entry.w;
ch = dst->cache_entry.h;
}
// find y yop line and y bottom line
ytop = p[0].y;
for (i = 1; i < 4; i++)
{
if (p[i].y < ytop) ytop = p[i].y;
}
ybottom = p[0].y;
for (i = 1; i < 4; i++)
{
if (p[i].y > ybottom) ybottom = p[i].y;
}
// convert to screen space from fixed point
ytop = ytop >> FP;
ybottom = ybottom >> FP;
// if its outside the clip vertical bounds - don't bother
if ((ytop >= (cy + ch)) || (ybottom < cy)) return;
// limit to the clip vertical bounds
if (ytop < cy) ystart = cy;
else ystart = ytop;
if (ybottom >= (cy + ch)) yend = (cy + ch) - 1;
else yend = ybottom;
// get some source image information
sp = src->image.data;
sw = src->cache_entry.w;
swp = sw << (FP + FPI);
shp = src->cache_entry.h << (FP + FPI);
// limit u,v coords of points to be within the source image
for (i = 0; i < 4; i++)
{
if (p[i].u < 0) p[i].u = 0;
else if (p[i].u > (src->cache_entry.w << FP))
p[i].u = src->cache_entry.w << FP;
if (p[i].v < 0) p[i].v = 0;
else if (p[i].v > (src->cache_entry.h << FP))
p[i].v = src->cache_entry.h << FP;
}
// allocate some spans to hold out span list
spans = alloca((yend - ystart + 1) * sizeof(Line));
if (!spans) return;
memset(spans, 0, (yend - ystart + 1) * sizeof(Line));
// calculate the spans list
_calc_spans(p, spans, ystart, yend, cx, cy, cw, ch);
// walk through spans and render
// if operation is solid, bypass buf and draw func and draw direct to dst
direct = 0;
if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) &&
(!dc->mul.use))
direct = 1;
else
{
buf = alloca(cw * sizeof(DATA32));
if (!buf) return;
if (dc->mul.use)
func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, cw, dc->render_op);
else
func = evas_common_gfx_func_composite_pixel_span_get(src, dst, cw, dc->render_op);
}
if (smooth)
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd, dv;
DATA32 *d, *s, *so[4], val1, val2;
Line *line;
#ifdef SCALE_USING_MMX
pxor_r2r(mm0, mm0);
MOV_A2R(ALPHA_255, mm5)
#endif
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
long long tl;
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
dv = (span->o2 - span->o1);
if (dv <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
tl = (long long)ud * (w << FP);
tl = tl / dv;
ud = tl;
u -= (ud * (span->o1 - (span->x1 << FP))) / FP1;
tl = (long long)vd * (w << FP);
tl = tl / dv;
vd = tl;
v -= (vd * (span->o1 - (span->x1 << FP))) / FP1;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
FPc u1, v1, u2, v2;
FPc rv, ru;
DATA32 val1, val2, val3, val4;
u1 = u;
if (u1 < 0) u1 = 0;
else if (u1 >= swp) u1 = swp - 1;
v1 = v;
if (v1 < 0) v1 = 0;
else if (v1 >= shp) v1 = shp - 1;
u2 = u1 + FPFPI1;
if (u2 >= swp) u2 = swp - 1;
v2 = v1 + FPFPI1;
if (v2 >= shp) v2 = shp - 1;
ru = (u >> (FP + FPI - 8)) & 0xff;
rv = (v >> (FP + FPI - 8)) & 0xff;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val1 = *s;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val2 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val3 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val4 = *s;
#ifdef SCALE_USING_MMX
MOV_A2R(rv, mm4);
MOV_A2R(ru, mm6);
MOV_P2R(val1, mm1, mm0);
if (val1 | val2)
{
MOV_P2R(val2, mm2, mm0);
INTERP_256_R2R(mm6, mm2, mm1, mm5);
}
MOV_P2R(val3, mm2, mm0);
if (val3 | val4)
{
MOV_P2R(val4, mm3, mm0);
INTERP_256_R2R(mm6, mm3, mm2, mm5);
}
INTERP_256_R2R(mm4, mm2, mm1, mm5);
MOV_R2P(mm1, *d, mm0);
d++;
#else
val1 = INTERP_256(ru, val2, val1);
val3 = INTERP_256(ru, val4, val3);
*d++ = INTERP_256(rv, val3, val1);
#endif
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
}
else
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd;
DATA32 *d, *s;
Line *line;
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
s = sp + ((v >> (FP + FPI)) * sw) +
(u >> (FP + FPI));
*d++ = *s;
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
}
}