From 422faf09fd222911f88e7f0e845908561f4fe97a Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Thu, 29 Oct 2009 06:52:51 +0000 Subject: [PATCH] clean up map - move to #included worker and add mmx - just copied from normal image scaler actually. SVN revision: 43336 --- legacy/evas/src/lib/canvas/evas_render.c | 120 +++--- .../evas/src/lib/engines/common/Makefile.am | 3 +- .../src/lib/engines/common/evas_map_image.c | 357 ++++-------------- .../engines/common/evas_map_image_internal.c | 278 ++++++++++++++ 4 files changed, 415 insertions(+), 343 deletions(-) create mode 100644 legacy/evas/src/lib/engines/common/evas_map_image_internal.c diff --git a/legacy/evas/src/lib/canvas/evas_render.c b/legacy/evas/src/lib/canvas/evas_render.c index 24a4f403d0..17ab8336da 100644 --- a/legacy/evas/src/lib/canvas/evas_render.c +++ b/legacy/evas/src/lib/canvas/evas_render.c @@ -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 { diff --git a/legacy/evas/src/lib/engines/common/Makefile.am b/legacy/evas/src/lib/engines/common/Makefile.am index c17587a7a8..02e804f51a 100644 --- a/legacy/evas/src/lib/engines/common/Makefile.am +++ b/legacy/evas/src/lib/engines/common/Makefile.am @@ -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 diff --git a/legacy/evas/src/lib/engines/common/evas_map_image.c b/legacy/evas/src/lib/engines/common/evas_map_image.c index ca339bcf0b..61a046e78b 100644 --- a/legacy/evas/src/lib/engines/common/evas_map_image.c +++ b/legacy/evas/src/lib/engines/common/evas_map_image.c @@ -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; } diff --git a/legacy/evas/src/lib/engines/common/evas_map_image_internal.c b/legacy/evas/src/lib/engines/common/evas_map_image_internal.c new file mode 100644 index 0000000000..da497557c6 --- /dev/null +++ b/legacy/evas/src/lib/engines/common/evas_map_image_internal.c @@ -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; + } + } + } +}