#include "evas_common_private.h" #include "evas_private.h" #include "evas_blend_private.h" #ifdef BUILD_NEON #include #endif #ifdef BUILD_MMX # undef SCALE_USING_MMX # define SCALE_USING_MMX #endif #define FPI 8 #define FPI1 (1 << (FPI)) #define FPIH (1 << (FPI - 1)) #define FPFPI1 (1 << (FP + FPI)) typedef struct _Line Line; typedef struct _Span Span; struct _Span { int x[2]; FPc o1, o2, z1, z2; FPc u[2], v[2]; DATA32 col[2]; }; struct _Line { Span span[2]; int aa_cov[2]; int aa_len[2]; }; static inline FPc _interp(int x1, int x2, int p, FPc u1, FPc u2) { FPc u; x2 -= x1; if (x2 == 0) x2 = 1; p -= x1; u = u2 - u1; u = ((u * p) / x2); // FIXME: do z persp return u1 + u; } static inline DATA32 _interp_col(int x1, int x2, int p, DATA32 col1, DATA32 col2) { x2 -= x1; if (x2 == 0) x2 = 1; p -= x1; p = ((p << 8) / x2); // FIXME: do z persp return INTERP_256(p, col2, col1); } static inline void _interpolated_clip_span(Span *s, int c1, int c2, Eina_Bool interp_col) { if (s->x[0] < c1) { s->u[0] = _interp(s->x[0], s->x[1], c1, s->u[0], s->u[1]); s->v[0] = _interp(s->x[0], s->x[1], c1, s->v[0], s->v[1]); if (interp_col) s->col[0] = _interp_col(s->x[0], s->x[1], c1, s->col[0], s->col[1]); s->x[0] = c1; s->o1 = c1 << FP; // FIXME: do s->z1 } if (s->x[1] > c2) { s->u[1] = _interp(s->x[0], s->x[1], c2, s->u[0], s->u[1]); s->v[1] = _interp(s->x[0], s->x[1], c2, s->v[0], s->v[1]); if (interp_col) s->col[1] = _interp_col(s->x[0], s->x[1], c2, s->col[0], s->col[1]); s->x[1] = c2; s->o2 = c2 << FP; // FIXME: do s->z2 } } // 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) { int i, y, yp; int py[4]; int edge[4][4], edge_num, order[4]; FPc uv[4][2], u, v, x, t, edge_h; DATA32 col[4]; Eina_Bool interp_col = EINA_FALSE; Eina_Bool swapped; for (i = 0; i < 4; i++) py[i] = (p[i].y >> FP); //Horizontal Line? if ((py[0] == py[1]) && (py[0] == py[2]) && (py[0] == py[3])) { int leftp, rightp; leftp = rightp = 0; for (i = 1; i < 4; i++) { if (p[i].x < p[leftp].x) leftp = i; if (p[i].x > p[rightp].x) rightp = i; if (p[i].col != 0xffffffff) interp_col = EINA_TRUE; } for (y = ystart; y <= yend; y++) { yp = y - ystart; if (y == py[0]) { i = 0; spans[yp].span[i].x[0] = p[leftp].x >> FP; spans[yp].span[i].o1 = p[leftp].x; spans[yp].span[i].u[0] = p[leftp].u; spans[yp].span[i].v[0] = p[leftp].v; spans[yp].span[i].col[0] = p[leftp].col; spans[yp].span[i].x[1] = p[rightp].x >> FP; spans[yp].span[i].o2 = p[rightp].x; spans[yp].span[i].u[1] = p[rightp].u; spans[yp].span[i].v[1] = p[rightp].v; spans[yp].span[i].col[1] = p[rightp].col; //Outside of the clipper if ((spans[yp].span[i].x[0] > (cx + cw)) || (spans[yp].span[i].x[1] < cx)) spans[yp].span[i].x[0] = -1; else { _interpolated_clip_span(&(spans[yp].span[i]), cx, (cx + cw), interp_col); i++; spans[yp].span[i].x[0] = -1; } } //The polygon shape seems not be completed definitely. else spans[yp].span[0].x[0] = -1; } return; } for (y = ystart; y <= yend; y++) { edge_num = 0; //Find edges that intersects with current scanline. for (i = 0; i < 4; i++) { if ((py[i] <= y) && (py[(i + 1) % 4] > y)) { edge[edge_num][0] = i; edge[edge_num][1] = (i + 1) % 4; edge_num++; } else if ((py[(i + 1) % 4] <= y) && (py[i] > y)) { edge[edge_num][0] = (i + 1) % 4; edge[edge_num][1] = i; edge_num++; } if (p[i].col != 0xffffffff) interp_col = EINA_TRUE; } // calculate line x points for each edge for (i = 0; i < edge_num; i++) { int e1 = edge[i][0]; int e2 = edge[i][1]; FPc t256; // compute x point that proportionated to the y point offset edge_h = (p[e2].y - p[e1].y) >> FP; //edge height if (edge_h < 1) edge_h = 1; t = (((y << FP) + (FP1 / 2) - 1) - p[e1].y) >> FP; x = p[e2].x - p[e1].x; //edge width FPc temp = (x * t); // TODO: prevent data overflow. We can remove this exception if FPc type is more than integer. if (temp < 0) temp = (((x >> FP) * t) / edge_h) << FP; else temp /= edge_h; x = p[e1].x + temp; // intersected x point /* // FIXME: 3d accuracy here // XXX t needs adjusting. above its a linear interp point // only. // // // FIXME: do in fixed pt. reduce divides evas_common_cpu_end_opt(); // int foc = 512, z0 = 0, px = 320, py = 240; // FIXME: need from map points // float focf, hf; float z1, z2, y1, y2, dz, dy, zt, dydz, yt; focf = foc; hf = h; // adjust for fixed point and focal length and z0 for map z1 = (p[e1].z >> FP) - z0 + foc; z2 = (p[e2].z >> FP) - z0 + foc; // deltas dz = z1 - z2; if (dz != 0) { int pt; // adjust for perspective point (being 0 0) y1 = (p[e1].y >> FP) - py; y2 = (p[e2].y >> FP) - py; // correct for x &y not being in world coords - screen coords y1 = (y1 * z1) / focf; y2 = (y2 * z2) / focf; // deltas dy = y1 - y2; yt = y - py; dydz = dy / dz; zt = (y2 - (dydz * z2)) / ((yt / focf) - dydz); pt = t; t = ((z1 - zt) * hf) / dz; } */ //compute texture u coordinate u = p[e2].u - p[e1].u; u = p[e1].u + ((u * t) / edge_h); //compute texture v coordinate v = p[e2].v - p[e1].v; v = p[e1].v + ((v * t) / edge_h); // FIXME: 3d accuracy for color too t256 = (t << 8) / edge_h; // maybe * 255? col[i] = INTERP_256(t256, p[e2].col, p[e1].col); // FIXME: store z persp uv[i][0] = u; uv[i][1] = v; edge[i][2] = x >> FP; edge[i][3] = x; // also fill in order order[i] = i; } // sort edges from left to right - bubble. its a small list! do { swapped = EINA_FALSE; for (i = 0; i < (edge_num - 1); i++) { if (edge[order[i]][2] > edge[order[i + 1]][2]) { t = order[i]; order[i] = order[i + 1]; order[i + 1] = t; swapped = EINA_TRUE; } } } while (swapped); yp = y - ystart; if (edge_num == 2) { i = 0; spans[yp].span[i].x[0] = edge[order[0]][2]; spans[yp].span[i].o1 = edge[order[0]][3]; spans[yp].span[i].u[0] = uv[order[0]][0]; spans[yp].span[i].v[0] = uv[order[0]][1]; spans[yp].span[i].col[0] = col[order[0]]; spans[yp].span[i].x[1] = edge[order[1]][2]; spans[yp].span[i].o2 = edge[order[1]][3]; spans[yp].span[i].u[1] = uv[order[1]][0]; spans[yp].span[i].v[1] = uv[order[1]][1]; spans[yp].span[i].col[1] = col[order[1]]; //Outside of the clipper if ((spans[yp].span[i].x[0] > (cx + cw)) || (spans[yp].span[i].x[1] < cx)) spans[yp].span[i].x[0] = -1; else { _interpolated_clip_span(&(spans[yp].span[i]), cx, (cx + cw), interp_col); i++; spans[yp].span[i].x[0] = -1; } } else if (edge_num == 4) { i = 0; spans[yp].span[i].x[0] = edge[order[0]][2]; spans[yp].span[i].u[0] = uv[order[0]][0]; spans[yp].span[i].v[0] = uv[order[0]][1]; spans[yp].span[i].col[0] = col[order[0]]; spans[yp].span[i].x[1] = edge[order[1]][2]; spans[yp].span[i].u[1] = uv[order[1]][0]; spans[yp].span[i].v[1] = uv[order[1]][1]; spans[yp].span[i].col[1] = col[order[1]]; //Outside of the clipper if ((spans[yp].span[i].x[0] > (cx + cw)) || (spans[yp].span[i].x[1] < cx)) spans[yp].span[i].x[0] = -1; else { _interpolated_clip_span(&(spans[yp].span[i]), cx, (cx + cw), interp_col); i++; } spans[yp].span[i].x[0] = edge[order[2]][2]; spans[yp].span[i].u[0] = uv[order[2]][0]; spans[yp].span[i].v[0] = uv[order[2]][1]; spans[yp].span[i].col[0] = col[order[2]]; spans[yp].span[i].x[1] = edge[order[3]][2]; spans[yp].span[i].u[1] = uv[order[3]][0]; spans[yp].span[i].v[1] = uv[order[3]][1]; spans[yp].span[i].col[1] = col[order[3]]; //Outside of the clipper if ((spans[yp].span[i].x[0] > (cx + cw)) || (spans[yp].span[i].x[1] < cx)) spans[yp].span[i].x[0] = -1; else { int l = cx; if (i > 0) l = spans[yp].span[i - 1].x[1]; _interpolated_clip_span(&(spans[yp].span[i]), l, (cx + cw), interp_col); } } //The polygon shape seems not be completed definitely. else spans[yp].span[0].x[0] = -1; } } /* FIXME: Account for 10% during pipe rendering, should be improved * Could be computing the interpolation once somehow. */ static void _clip_spans(Line *spans, int ystart, int yend, int cx, int cw, Eina_Bool interp_col) { int y, yp; for (y = ystart, yp = 0; y <= yend; y++, yp++) { if (spans[yp].span[0].x[0] > -1) { if ((spans[yp].span[0].x[0] >= (cx + cw)) || (spans[yp].span[0].x[1] < cx)) { spans[yp].span[0].x[0] = -1; } else { _interpolated_clip_span(&(spans[yp].span[0]), cx, (cx + cw), interp_col); if ((spans[yp].span[1].x[0] >= (cx + cw)) || (spans[yp].span[1].x[1] < cx)) { spans[yp].span[1].x[0] = -1; } else { _interpolated_clip_span(&(spans[yp].span[1]), spans[yp].span[0].x[1], cx + cw, interp_col); } } } } } typedef struct _RGBA_Map_Spans RGBA_Map_Spans; typedef struct _RGBA_Map_Cutout RGBA_Map_Cutout; struct _RGBA_Map_Spans { Line *spans; int size; int ystart; int yend; int havecol; Eina_Bool havea; Eina_Bool direct; }; struct _RGBA_Map_Cutout { int count; Cutout_Rects *rects; RGBA_Map_Spans spans[1]; }; EAPI void evas_common_map_rgba_clean(RGBA_Map *m) { RGBA_Map_Cutout *spans = m->engine_data; if (spans) { int i; if (spans->rects) evas_common_draw_context_apply_clear_cutouts(spans->rects); for (i = 0; i < spans->count; i++) free(spans->spans[i].spans); free(spans); } m->engine_data = NULL; } static void _rgba_map_cutout_resize(RGBA_Map *m, int count) { RGBA_Map_Cutout *old = m->engine_data; RGBA_Map_Cutout *r; int size; int i; if (count == 0) goto empty; if (old && old->count == count) { return; } size = sizeof (RGBA_Map_Cutout) + sizeof (RGBA_Map_Spans) * (count - 1); if (old) { for (i = 0; i < old->count; i++) { free(old->spans[i].spans); old->spans[i].spans = NULL; } } r = realloc(old, size); if (!r) goto empty; memset(r, 0, size); m->engine_data = r; r->count = count; return; empty: evas_common_map_rgba_clean(m); return; } static void _evas_common_map_rgba_span(RGBA_Map_Spans *span, RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int cx, int cy, int cw, int ch) { int ytop, ybottom, sw; unsigned int i; span->havecol = 4; span->havea = 0; span->direct = 0; // find y top line and y bottom line ytop = p[0].y; if ((p[0].col >> 24) < 0xff) span->havea = 1; if (p[0].col == 0xffffffff) span->havecol--; for (i = 1; i < 4; i++) { if (p[i].y < ytop) ytop = p[i].y; if ((p[i].col >> 24) < 0xff) span->havea = 1; if (p[i].col == 0xffffffff) span->havecol--; } 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) span->ystart = cy; else span->ystart = ytop; if (ybottom >= (cy + ch)) span->yend = (cy + ch) - 1; else span->yend = ybottom; // get some source image information sw = src->cache_entry.w; // 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 > (int)(sw << FP)) p[i].u = src->cache_entry.w << FP; if (p[i].v < 0) p[i].v = 0; else if (p[i].v > (int)(sw << FP)) p[i].v = src->cache_entry.h << FP; } // allocate some spans to hold out span list if (span->size < (span->yend - span->ystart + 1)) { free(span->spans); span->size = (span->yend - span->ystart + 1); span->spans = calloc(1, span->size * sizeof(Line)); } if (!span->spans) return; // calculate the spans list _calc_spans(p, span->spans, span->ystart, span->yend, cx, cy, cw, ch); // if operation is solid, bypass buf and draw func and draw direct to dst if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) && (!dc->mul.use) && (!span->havea)) { span->direct = 1; } } EAPI Eina_Bool evas_common_map_rgba_prepare(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map *m) { RGBA_Map_Cutout *spans; Cutout_Rects *rects = NULL; Cutout_Rect *r; int i; if ((!dc->cutout.rects) && (!dc->clip.use)) { evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h); if ((dc->clip.w <= 0) || (dc->clip.h <= 0)) { _rgba_map_cutout_resize(m, 0); return EINA_FALSE; } _rgba_map_cutout_resize(m, 1); if (!m->engine_data) return EINA_FALSE; spans = m->engine_data; _evas_common_map_rgba_span(&spans->spans[0], src, dst, dc, m->pts, 0, 0, dst->cache_entry.w, dst->cache_entry.h); return EINA_TRUE; } 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)) { _rgba_map_cutout_resize(m, 0); return EINA_FALSE; } spans = m->engine_data; if (spans) { rects = spans->rects; spans->rects = NULL; } rects = evas_common_draw_context_apply_cutouts(dc, rects); _rgba_map_cutout_resize(m, rects->active); spans = m->engine_data; if (!spans) { evas_common_draw_context_apply_clear_cutouts(rects); return EINA_FALSE; } spans->rects = rects; for (i = 0; i < spans->rects->active; ++i) { r = spans->rects->rects + i; _evas_common_map_rgba_span(&spans->spans[i], src, dst, dc, m->pts, r->x, r->y, r->w, r->h); } return EINA_TRUE; } #ifdef BUILD_MMX # undef FUNC_NAME # undef FUNC_NAME_DO # define FUNC_NAME _evas_common_map_rgba_internal_mmx # define FUNC_NAME_DO evas_common_map_rgba_internal_mmx_do # undef SCALE_USING_MMX # define SCALE_USING_MMX # include "evas_map_image_internal.c" #endif #undef FUNC_NAME #undef FUNC_NAME_DO #define FUNC_NAME _evas_common_map_rgba_internal #define FUNC_NAME_DO evas_common_map_rgba_internal_do #undef SCALE_USING_MMX #include "evas_map_image_internal.c" # ifdef BUILD_NEON # undef FUNC_NAME # undef FUNC_NAME_DO # define FUNC_NAME _evas_common_map_rgba_internal_neon # define FUNC_NAME_DO evas_common_map_rgba_internal_neon_do # undef SCALE_USING_NEON # define SCALE_USING_NEON # undef SCALE_USING_MMX # include "evas_map_image_internal.c" # undef SCALE_USING_NEON #endif #include "evas_map_image_internal_high.c" #ifdef BUILD_MMX void evas_common_map_rgba_internal_mmx(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int smooth, int level) { int clip_x, clip_y, clip_w, clip_h; DATA32 mul_col; if (dc->clip.use) { clip_x = dc->clip.x; clip_y = dc->clip.y; clip_w = dc->clip.w; clip_h = dc->clip.h; } else { clip_x = clip_y = 0; clip_w = dst->cache_entry.w; clip_h = dst->cache_entry.h; } mul_col = dc->mul.use ? dc->mul.col : 0xffffffff; _evas_common_map_rgba_internal_mmx(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, dc->render_op, p, smooth, dc->anti_alias, level, dc->clip.mask, dc->clip.mask_x, dc->clip.mask_y); } #endif void evas_common_map_rgba_internal_high(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int smooth, int level) { int clip_x, clip_y, clip_w, clip_h; DATA32 mul_col; if (dc->clip.use) { clip_x = dc->clip.x; clip_y = dc->clip.y; clip_w = dc->clip.w; clip_h = dc->clip.h; } else { clip_x = clip_y = 0; clip_w = dst->cache_entry.w; clip_h = dst->cache_entry.h; } mul_col = dc->mul.use ? dc->mul.col : 0xffffffff; _evas_common_map_rgba_internal_high(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, dc->render_op, p, smooth, dc->anti_alias, level, dc->clip.mask, dc->clip.mask_x, dc->clip.mask_y); } void evas_common_map_rgba_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int smooth, int level) { int clip_x, clip_y, clip_w, clip_h; DATA32 mul_col; if (dc->clip.use) { clip_x = dc->clip.x; clip_y = dc->clip.y; clip_w = dc->clip.w; clip_h = dc->clip.h; } else { clip_x = clip_y = 0; clip_w = dst->cache_entry.w; clip_h = dst->cache_entry.h; } mul_col = dc->mul.use ? dc->mul.col : 0xffffffff; _evas_common_map_rgba_internal(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, dc->render_op, p, smooth, dc->anti_alias, level, dc->clip.mask, dc->clip.mask_x, dc->clip.mask_y); } #ifdef BUILD_NEON void evas_common_map_rgba_internal_neon(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int smooth, int level) { int clip_x, clip_y, clip_w, clip_h; DATA32 mul_col; if (dc->clip.use) { clip_x = dc->clip.x; clip_y = dc->clip.y; clip_w = dc->clip.w; clip_h = dc->clip.h; } else { clip_x = clip_y = 0; clip_w = dst->cache_entry.w; clip_h = dst->cache_entry.h; } mul_col = dc->mul.use ? dc->mul.col : 0xffffffff; _evas_common_map_rgba_internal_neon(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, dc->render_op, p, smooth, dc->anti_alias, level, dc->clip.mask, dc->clip.mask_x, dc->clip.mask_y); } #endif EAPI void evas_common_map_rgba_cb(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int npoints EINA_UNUSED, RGBA_Map_Point *p, int smooth, int level, Evas_Common_Map_RGBA_Cb cb) { 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) || (!dst->image.data)) return; if ((!dc->cutout.rects) && (!dc->clip.use)) { cb(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; } dc->cache.rects = evas_common_draw_context_apply_cutouts(dc, dc->cache.rects); for (i = 0; i < dc->cache.rects->active; ++i) { r = dc->cache.rects->rects + i; evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); cb(src, dst, dc, p, smooth, level); } evas_common_draw_context_cache_update(dc); /* restore clip info */ dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch; } EAPI Eina_Bool evas_common_map_thread_rgba_cb(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map *map, int smooth, int level, int offset, Evas_Common_Map_Thread_RGBA_Cb cb) { Cutout_Rect *r; int c, cx, cy, cw, ch; int i; Eina_Bool ret = EINA_FALSE; 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) || (!dst->image.data)) return EINA_FALSE; if ((!dc->cutout.rects) && (!dc->clip.use)) { return cb(src, dst, dc, map, smooth, level, offset); } /* 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 EINA_FALSE; } dc->cache.rects = evas_common_draw_context_apply_cutouts(dc, dc->cache.rects); for (i = 0; i < dc->cache.rects->active; ++i) { r = dc->cache.rects->rects + i; evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); ret |= cb(src, dst, dc, map, smooth, level, offset); } evas_common_draw_context_cache_update(dc); /* restore clip info */ dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch; return ret; } EAPI void evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int npoints, RGBA_Map_Point *p, int smooth, int level) { Evas_Common_Map_RGBA_Cb cb; if (dc->anti_alias && smooth) { //FIXME: we cannot apply anti_aliasing per polygons. Eina_Bool aa = dc->anti_alias; if (npoints > 4) dc->anti_alias = EINA_FALSE; cb = evas_common_map_rgba_internal_high; if (npoints > 4) dc->anti_alias = aa; } else { #ifdef BUILD_MMX int mmx, sse, sse2; evas_common_cpu_can_do(&mmx, &sse, &sse2); if (mmx) cb = evas_common_map_rgba_internal_mmx; else #endif #ifdef BUILD_NEON if (evas_common_cpu_has_feature(CPU_FEATURE_NEON)) cb = evas_common_map_rgba_internal_neon; else #endif cb = evas_common_map_rgba_internal; } evas_common_map_rgba_cb(src, dst, dc, npoints, p, smooth, level, cb); } EAPI void evas_common_map_rgba_draw(RGBA_Image *src, RGBA_Image *dst, int clip_x, int clip_y, int clip_w, int clip_h, DATA32 mul_col, int render_op, int npoints, RGBA_Map_Point *p, int smooth, Eina_Bool anti_alias, int level, RGBA_Image *mask_ie, int mask_x, int mask_y) { //The best quaility requsted. if (anti_alias && smooth) { //FIXME: we cannot apply anti_aliasing per polygons. if (npoints > 4) anti_alias = EINA_FALSE; _evas_common_map_rgba_internal_high(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, render_op, p, smooth, anti_alias, level, mask_ie, mask_x, mask_y); } else { #ifdef BUILD_MMX int mmx, sse, sse2; evas_common_cpu_can_do(&mmx, &sse, &sse2); if (mmx) _evas_common_map_rgba_internal_mmx(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, render_op, p, smooth, anti_alias, level, mask_ie, mask_x, mask_y); else #endif #ifdef BUILD_NEON if (evas_common_cpu_has_feature(CPU_FEATURE_NEON)) _evas_common_map_rgba_internal_neon(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, render_op, p, smooth, anti_alias, level, mask_ie, mask_x, mask_y); else #endif _evas_common_map_rgba_internal(src, dst, clip_x, clip_y, clip_w, clip_h, mul_col, render_op, p, smooth, anti_alias, level, mask_ie, mask_x, mask_y); } } EAPI void evas_common_map_rgba_do(const Eina_Rectangle *clip, RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, const RGBA_Map *m, int smooth, int level) { #ifdef BUILD_MMX int mmx, sse, sse2; #endif const Cutout_Rects *rects; const RGBA_Map_Cutout *spans; Eina_Rectangle area; Cutout_Rect *r; int i; #ifdef BUILD_MMX evas_common_cpu_can_do(&mmx, &sse, &sse2); #endif spans = m->engine_data; rects = spans->rects; if (rects->active == 0 && spans->count == 1) { evas_common_draw_context_set_clip(dc, clip->x, clip->y, clip->w, clip->h); #ifdef BUILD_MMX if (mmx) evas_common_map_rgba_internal_mmx_do(src, dst, dc, &spans->spans[0], smooth, dc->anti_alias, level); else #endif #ifdef BUILD_NEON if (evas_common_cpu_has_feature(CPU_FEATURE_NEON)) evas_common_map_rgba_internal_neon_do(src, dst, dc, &spans->spans[0], smooth, dc->anti_alias, level); else #endif evas_common_map_rgba_internal_do(src, dst, dc, &spans->spans[0], smooth, dc->anti_alias, level); return; } for (i = 0; i < rects->active; ++i) { r = rects->rects + i; EINA_RECTANGLE_SET(&area, r->x, r->y, r->w, r->h); if (!eina_rectangle_intersection(&area, clip)) continue ; evas_common_draw_context_set_clip(dc, area.x, area.y, area.w, area.h); #ifdef BUILD_MMX if (mmx) { evas_common_map_rgba_internal_mmx_do(src, dst, dc, &spans->spans[i], smooth, dc->anti_alias, level); } else #endif #ifdef BUILD_NEON if (evas_common_cpu_has_feature(CPU_FEATURE_NEON)) evas_common_map_rgba_internal_neon_do(src, dst, dc, &spans->spans[i], smooth, dc->anti_alias, level); else #endif evas_common_map_rgba_internal_do(src, dst, dc, &spans->spans[i], smooth, dc->anti_alias, level); } }