diff --git a/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c b/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c index ced89d9aa3..15e5628423 100644 --- a/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c +++ b/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c @@ -2,82 +2,135 @@ #include "evas_private.h" #include "evas_soft16.h" -#define BLEND(s, a, d) \ - { DATA32 wsp, wdp; \ - wsp = (*s | (*s << 16)) & 0x07e0f81f; \ - wdp = (*d | (*d << 16)) & 0x07e0f81f; \ - wdp = (((wdp * (32 - *a)) >> 5) & 0x07e0f81f) + wsp; \ - *d = wdp | (wdp >> 16); \ - } +#define RGB_565_UNPACKED_MASK 0x07e0f81f +#define RGB_565_UNPACK(rgb) \ + (((rgb) | ((rgb) << 16)) & RGB_565_UNPACKED_MASK) +#define RGB_565_PACK(rgb) \ + ((((rgb) & RGB_565_UNPACKED_MASK) | \ + ((rgb) & RGB_565_UNPACKED_MASK) >> 16) & 0xffff) +#define RGB_565_UNPACKED_BLEND(a, b, alpha) \ + ((b) + ((((a) - (b)) * (alpha)) >> 5)) -typedef void (*Scanline_Func) (DATA16 *s, DATA8 *a, DATA8 *m, DATA32 c, DATA16 *d, int l); +#define RGB_565_FROM_COMPONENTS(r, g, b) \ + (((((r) >> 3) & 0x1f) << 11) | \ + ((((g) >> 2) & 0x3f) << 5) | \ + (((b) >> 3) & 0x1f)) + +#if defined(__ARMEL__) +/* tested on ARMv6 (arm1136j-s), Nokia N800 CPU */ +#define pld(addr, off) \ + __asm__("pld [%[address], %[offset]]":: \ + [address] "r" (addr), [offset] "i" (off)) +#else +#define pld(addr, off) +#endif /* __ARMEL__ */ + + +#define IMG_BYTE_SIZE(stride, height, has_alpha) \ + ((stride) * (height) * (!(has_alpha) ? 2 : 3)) + + +static inline void _soft16_scanline_blend_solid_solid(DATA16 *src, DATA16 *dst, int size); +static inline void _soft16_scanline_blend_transp_solid(DATA16 *src, DATA8 *alpha, DATA16 *dst, int size); -static void -_soft16_image_rgba32_import(Soft16_Image *im, DATA32 *src); -static void -_soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, - RGBA_Draw_Context *dc, - int src_region_x, int src_region_y, - int src_region_w, int src_region_h, - int dst_region_x, int dst_region_y, - int dst_region_w, int dst_region_h); -static void -_soft16_scanline_blend(DATA16 *s, DATA8 *a, DATA8 *m, DATA32 c, DATA16 *d, int l); -static void -_soft16_scanline_copy(DATA16 *s, DATA8 *a, DATA8 *m, DATA32 c, DATA16 *d, int l); static Evas_Hash *_soft16_image_cache_hash = NULL; -Soft16_Image * -soft16_image_new(int w, int h, int stride, int have_alpha, DATA16 *pixels, int copy) +static inline int +_calc_stride(int w) +{ + int pad; + + pad = w % 4; + if (!pad) return w; + else return w + 4 - pad; +} + +static void +soft16_image_alloc_pixels(Soft16_Image *im) +{ + if (im->pixels) return; + + im->pixels = malloc(IMG_BYTE_SIZE(im->stride, im->h, im->have_alpha)); + if (!im->pixels) return; + if (im->have_alpha) im->alpha = (DATA8 *)(im->pixels + (im->stride * im->h)); + im->free_pixels = 1; +} + +static Soft16_Image * +soft16_image_alloc(int w, int h, int stride, int have_alpha, int have_pixels) { Soft16_Image *im; - + im = calloc(1, sizeof(Soft16_Image)); if (!im) return NULL; + im->w = w; im->h = h; - im->stride = w; - if (copy) + im->stride = stride; + im->have_alpha = have_alpha; + im->references = 1; + if (!have_pixels) return im; + + soft16_image_alloc_pixels(im); + if (!im->pixels) { - if (have_alpha) - { - im->pixels = malloc((im->stride * im->h * sizeof(DATA16)) + - (im->stride * im->h * sizeof(DATA8))); - if (!im->pixels) - { - free(im); - return NULL; - } - im->alpha = (DATA8 *)(im->pixels + (im->stride * im->h)); - if (pixels) - memcpy(im->pixels, pixels, - (im->stride * im->h * sizeof(DATA16)) + - (im->stride * im->h * sizeof(DATA8))); - } - else - { - im->pixels = malloc(im->stride * im->h * sizeof(DATA16)); - if (!im->pixels) - { - free(im); - return NULL; - } - if (pixels) - memcpy(im->pixels, pixels, - im->stride * im->h * sizeof(DATA16)); - } - im->free_pixels = 1; + free(im); + return NULL; } + + return im; +} + +Soft16_Image * +soft16_image_new(int w, int h, int stride, int have_alpha, DATA16 *pixels, + int copy) +{ + Soft16_Image *im; + + im = soft16_image_alloc(w, h, stride, have_alpha, copy); + if (!im) return NULL; + + if (copy) memcpy(im->pixels, pixels, IMG_BYTE_SIZE(stride, h, have_alpha)); else { im->pixels = pixels; - if (have_alpha) im->alpha = (DATA8 *)(im->pixels + (im->stride * im->h)); + if (have_alpha) im->alpha = (DATA8 *)(im->pixels + (stride * h)); } - im->references = 1; return im; } +static void +soft16_image_cache_key(const Evas_Image_Load_Opts *lo, const char *key, + const char *file, char *buf, unsigned bufsize) +{ + if ((!lo) || + ((lo->scale_down_by == 0) && (lo->dpi == 0.0) && + ((lo->w == 0) || (lo->h == 0)))) + { + if (key) snprintf(buf, bufsize, "%s//://%s", file, key); + else strncpy(buf, file, bufsize); + } + else + { + if (key) + snprintf(buf, bufsize, "//@/%i/%1.5f/%ix%i//%s//://%s", + lo->scale_down_by, lo->dpi, lo->w, lo->h, + file, key); + else + snprintf(buf, bufsize, "//@/%i/%1.5f/%ix%i//%s", + lo->scale_down_by, lo->dpi, lo->w, lo->h, + file); + } +} + +static inline void +soft16_image_cache_key_from_img(const Soft16_Image *im, char *buf, + unsigned bufsize) +{ + soft16_image_cache_key(&im->lo, im->key, im->file, buf, bufsize); +} + void soft16_image_free(Soft16_Image *im) { @@ -87,26 +140,7 @@ soft16_image_free(Soft16_Image *im) if (im->file) { char buf[4096 + 1024]; - - if ((im->lo.scale_down_by == 0) && (im->lo.dpi == 0.0) && - ((im->lo.w == 0) || (im->lo.h == 0))) - { - if (im->key) - snprintf(buf, sizeof(buf), "%s//://%s", im->file, im->key); - else - snprintf(buf, sizeof(buf), "%s", im->file); - } - else - { - if (im->key) - snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//%s//://%s", - im->lo.scale_down_by, im->lo.dpi, im->lo.w, im->lo.h, - im->file, im->key); - else - snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//%s", - im->lo.scale_down_by, im->lo.dpi, im->lo.w, im->lo.h, - im->file); - } + soft16_image_cache_key_from_img(im, buf, sizeof(buf)); _soft16_image_cache_hash = evas_hash_del(_soft16_image_cache_hash, buf, im); } @@ -118,133 +152,129 @@ soft16_image_free(Soft16_Image *im) #define STAT_GAP 2 -Soft16_Image * -soft16_image_load(const char *file, const char *key, int *error, - Evas_Image_Load_Opts *lo) +static Soft16_Image * +soft16_image_cache_get(const char *cache_key) +{ + Soft16_Image *im; + + im = evas_hash_find(_soft16_image_cache_hash, cache_key); + if (im) + { + time_t t; + + t = time(NULL); + if ((t - im->laststat) > STAT_GAP) + { + struct stat st; + + if (stat(im->file, &st) < 0) return NULL; + if (st.st_mtime != im->timestamp) return NULL; + + im->laststat = t; + } + im->references++; + } + + return im; +} + +static Soft16_Image * +soft16_image_load_new(const char *file, const char *key, + Evas_Image_Load_Opts *lo) { Soft16_Image *im; RGBA_Image *sim; - char buf[4096 + 1024]; - struct stat st; - static time_t laststat = 0; - time_t t, mt = 0; + int have_alpha; - *error = 0; - if (!(lo) || - ((lo->scale_down_by == 0) && (lo->dpi == 0.0) && - ((lo->w == 0) || (lo->h == 0)))) - { - if (key) - snprintf(buf, sizeof(buf), "%s//://%s", file, key); - else - snprintf(buf, sizeof(buf), "%s", file); - } - else - { - if (key) - snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//%s//://%s", - lo->scale_down_by, lo->dpi, lo->w, lo->h, file, key); - else - snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//%s", - lo->scale_down_by, lo->dpi, lo->w, lo->h, file); - } - im = evas_hash_find(_soft16_image_cache_hash, buf); - if (im) - { - if ((t - im->laststat) < STAT_GAP) - { - im->references++; - return im; - } - else - { - struct stat st; - - if (stat(file, &st) < 0) return NULL; - mt = st.st_mtime; - if (mt == im->timestamp) - { - im->laststat = t; - laststat = t; - im->references++; - return im; - } - } - } sim = evas_common_load_image_from_file(file, key, lo); if (!sim) return NULL; - im = calloc(1, sizeof(Soft16_Image)); + + have_alpha = !!(sim->flags & RGBA_IMAGE_HAS_ALPHA); + im = soft16_image_alloc(sim->image->w, sim->image->h, + _calc_stride(sim->image->w), have_alpha, 0); if (!im) { evas_common_image_unref(sim); return NULL; } + im->source_im = sim; - im->w = im->source_im->image->w; - im->h = im->source_im->image->h; - im->stride = im->w; im->timestamp = im->source_im->timestamp; im->laststat = im->source_im->laststat; + if (lo) im->lo = *lo; if (file) im->file = evas_stringshare_add(file); if (key) im->key = evas_stringshare_add(key); - if (im->source_im->flags & RGBA_IMAGE_HAS_ALPHA) im->have_alpha = 1; - im->references = 1; - _soft16_image_cache_hash = evas_hash_add(_soft16_image_cache_hash, buf, im); + return im; } +Soft16_Image * +soft16_image_load(const char *file, const char *key, int *error, + Evas_Image_Load_Opts *lo) +{ + Soft16_Image *im; + char buf[4096 + 1024]; + + *error = 0; + soft16_image_cache_key(lo, key, file, buf, sizeof(buf)); + im = soft16_image_cache_get(buf); + if (im) return im; + + im = soft16_image_load_new(file, key, lo); + if (im) _soft16_image_cache_hash = evas_hash_add(_soft16_image_cache_hash, buf, im); + + return im; +} static void _soft16_image_rgba32_import(Soft16_Image *im, DATA32 *src) { - DATA32 *sp, r, g, b, a; - DATA16 *dp, *dpl; - DATA8 *da, *dal; - int x, y; - + DATA32 *sp; + DATA16 *dpl; + /* FIXME: dither and optimize */ sp = src; dpl = im->pixels; - dal = im->alpha; - if (dal) + if (im->alpha) { + DATA8 *dal; + dal = im->alpha; + int y; + for (y = 0; y < im->h; y++) { + DATA16 *dp, *dp_end; + DATA8 *da; + dp = dpl; + dp_end = dp + im->w; da = dal; - for (x = 0; x < im->w; x++) + + for (; dp < dp_end; da++, dp++, sp++) { - a = (A_VAL(sp) * 32) / 255; - r = (R_VAL(sp) >> 3); - g = (G_VAL(sp) >> 2); - b = (B_VAL(sp) >> 3); - /* FIXME: not sure about this yet - also need to check alpha is not letss that G when alpha is upscaled to 6bits */ - *da = a; /* scale 0-32 - yes, 1 over 5bits - makes bitshift math later work better */ - if ((*da << 1) < g) g--; - *dp = (r << 11) | (g << 5) | (b); - dp++; - da++; - sp++; + *da = A_VAL(sp) >> 3; + *dp = RGB_565_FROM_COMPONENTS(R_VAL(sp), G_VAL(sp), B_VAL(sp)); } + dpl += im->stride; dal += im->stride; } } else { + int y; + for (y = 0; y < im->h; y++) { + DATA16 *dp, *dp_end; + dp = dpl; - for (x = 0; x < im->w; x++) - { - *dp = - ((R_VAL(sp) >> 3) << 11) | - ((G_VAL(sp) >> 2) << 5 ) | - ((B_VAL(sp) >> 3) ); - dp++; - sp++; - } + dp_end = dp + im->w; + + for (; dp < dp_end; dp++, sp++) + *dp = RGB_565_FROM_COMPONENTS(R_VAL(sp), G_VAL(sp), B_VAL(sp)); + dpl += im->stride; } } @@ -256,39 +286,226 @@ soft16_image_load_data(Soft16_Image *im) if (!im) return; if (im->pixels) return; if (!im->source_im) return; - + evas_common_load_image_data_from_file(im->source_im); if (im->source_im->image->data) { - if (im->source_im->flags & RGBA_IMAGE_HAS_ALPHA) - { - im->pixels = malloc((im->stride * im->h * sizeof(DATA16)) + - (im->stride * im->h * sizeof(DATA8))); - if (!im->pixels) goto done; - im->alpha = (DATA8 *)(im->pixels + (im->stride * im->h)); - } - else - { - im->pixels = malloc(im->stride * im->h * sizeof(DATA16)); - if (!im->pixels) goto done; - } - _soft16_image_rgba32_import(im, im->source_im->image->data); - im->free_pixels = 1; + if (!im->pixels) soft16_image_alloc_pixels(im); + if (im->pixels) _soft16_image_rgba32_import(im, im->source_im->image->data); } - done: evas_common_image_unref(im->source_im); im->source_im = NULL; } +static inline void +_get_clip(const RGBA_Draw_Context *dc, const Soft16_Image *im, + Evas_Rectangle *clip) +{ + if (dc->clip.use) + { + clip->x = dc->clip.x; + clip->y = dc->clip.y; + clip->w = dc->clip.w; + clip->h = dc->clip.h; + if (clip->x < 0) + { + clip->w += clip->x; + clip->x = 0; + } + if (clip->y < 0) + { + clip->h += clip->y; + clip->y = 0; + } + if ((clip->x + clip->w) > im->w) clip->w = im->w - clip->x; + if ((clip->y + clip->h) > im->h) clip->h = im->h - clip->y; + } + else + { + clip->x = 0; + clip->y = 0; + clip->w = im->w; + clip->h = im->h; + } +} + +static inline int +_is_empty_rectangle(const Evas_Rectangle *r) +{ + return (r->w < 1) || (r->h < 1); +} + +static inline void +_shrink(int *s_pos, int *s_size, int pos, int size) +{ + int d; + + d = (*s_pos) - pos; + if (d < 0) + { + (*s_size) += d; + (*s_pos) = pos; + } + + d = size + pos - (*s_pos); + if ((*s_size) > d) + (*s_size) = d; +} + +static int +_soft16_adjust_areas(Evas_Rectangle *src, + int src_max_x, int src_max_y, + Evas_Rectangle *dst, + int dst_max_x, int dst_max_y, + Evas_Rectangle *dst_clip) +{ + if (_is_empty_rectangle(src) || + _is_empty_rectangle(dst) || + _is_empty_rectangle(dst_clip)) + return 0; + + /* shrink clip */ + _shrink(&dst_clip->x, &dst_clip->w, dst->x, dst->w); + _shrink(&dst_clip->y, &dst_clip->h, dst->y, dst->h); + if (_is_empty_rectangle(dst_clip)) return 0; + + /* sanitise x */ + if (src->x < 0) + { + dst->x -= (src->x * dst->w) / src->w; + dst->w += (src->x * dst->w) / src->w; + src->w += src->x; + src->x = 0; + } + if (src->x >= src_max_x) return 0; + if ((src->x + src->w) > src_max_x) + { + dst->w = (dst->w * (src_max_x - src->x)) / (src->w); + src->w = src_max_x - src->x; + } + if (dst->w <= 0) return 0; + if (src->w <= 0) return 0; + if (dst_clip->x < 0) + { + dst_clip->w += dst_clip->x; + dst_clip->x = 0; + } + if (dst_clip->w <= 0) return 0; + if (dst_clip->x >= dst_max_x) return 0; + + _shrink(&dst_clip->x, &dst_clip->w, dst->x, dst_max_x); + if (dst_clip->w <= 0) return 0; + + /* sanitise y */ + if (src->y < 0) + { + dst->y -= (src->y * dst->h) / src->h; + dst->h += (src->y * dst->h) / src->h; + src->h += src->y; + src->y = 0; + } + if (src->y >= src_max_y) return 0; + if ((src->y + src->h) > src_max_y) + { + dst->h = (dst->h * (src_max_y - src->y)) / (src->h); + src->h = src_max_y - src->y; + } + if (dst->h <= 0) return 0; + if (src->h <= 0) return 0; + if (dst_clip->y < 0) + { + dst_clip->h += dst_clip->y; + dst_clip->y = 0; + } + if (dst_clip->h <= 0) return 0; + if (dst_clip->y >= dst_max_y) return 0; + + _shrink(&dst_clip->y, &dst_clip->h, dst->y, dst_max_y); + if (dst_clip->h <= 0) return 0; + + return 1; +} + +static void +_soft16_image_draw_unscaled_solid_solid(Soft16_Image *src, Soft16_Image *dst, + RGBA_Draw_Context *dc, + int src_offset, int dst_offset, + int w, int h) +{ + DATA16 *src_itr, *dst_itr; + int y; + + src_itr = src->pixels + src_offset; + dst_itr = dst->pixels + dst_offset; + + for (y = 0; y < h; y++) + { + _soft16_scanline_blend_solid_solid(src_itr, dst_itr, w); + src_itr += src->stride; + dst_itr += dst->stride; + } +} + +static void +_soft16_image_draw_unscaled_transp_solid(Soft16_Image *src, Soft16_Image *dst, + RGBA_Draw_Context *dc, + int src_offset, int dst_offset, + int w, int h) + +{ + DATA16 *src_itr, *dst_itr; + DATA8 *alpha_itr; + int y; + + src_itr = src->pixels + src_offset; + alpha_itr = src->alpha + src_offset; + dst_itr = dst->pixels + dst_offset; + + for (y = 0; y < h; y++) + { + _soft16_scanline_blend_transp_solid(src_itr, alpha_itr, dst_itr, w); + src_itr += src->stride; + alpha_itr += src->stride; + dst_itr += dst->stride; + } +} + +static void +_soft16_image_draw_unscaled(Soft16_Image *src, Soft16_Image *dst, + RGBA_Draw_Context *dc, + const Evas_Rectangle sr, + const Evas_Rectangle dr, + const Evas_Rectangle cr) +{ + int src_offset_rows, src_offset, dst_offset; + + src_offset_rows = (cr.y - dr.y) + sr.y; + src_offset = (src_offset_rows * src->stride) + (cr.x - dr.x) + sr.x; + + dst_offset = cr.x + (cr.y * dst->stride); + + if (src->have_alpha && (!dst->have_alpha)) + _soft16_image_draw_unscaled_transp_solid(src, dst, dc, + src_offset, dst_offset, + cr.w, cr.h); + else if ((!src->have_alpha) && (!dst->have_alpha)) + _soft16_image_draw_unscaled_solid_solid(src, dst, dc, + src_offset, dst_offset, + cr.w, cr.h); + else + fprintf(stderr, + "Unsupported draw of unscaled images src->have_alpha=%d, " + "dst->have_alpha=%d\n", + src->have_alpha, dst->have_alpha); +} + static void _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, RGBA_Draw_Context *dc, - int src_region_x, int src_region_y, - int src_region_w, int src_region_h, - int dst_region_x, int dst_region_y, - int dst_region_w, int dst_region_h) + Evas_Rectangle sr, Evas_Rectangle dr) { - Scanline_Func func; + Evas_Rectangle cr; +/* Scanline_Func func; */ int x, y; int *lin_ptr; DATA16 *buf, *dptr; @@ -297,217 +514,82 @@ _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, DATA8 *bufa, *daptr; DATA8 **rowa_ptr = NULL; DATA8 *aptr, *dsta_ptr, *srca_data, *dsta_data; - int dst_jump, dst_stride, src_stride; - int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h; - int src_w, src_h, dst_w, dst_h; - - if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->w, dst->h))) + if (!(RECTS_INTERSECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->w, dst->h))) return; - if (!(RECTS_INTERSECT(src_region_x, src_region_y, src_region_w, src_region_h, 0, 0, src->w, src->h))) - return; - - src_w = src->w; - src_h = src->h; - dst_w = dst->w; - dst_h = dst->h; - - if (dc->clip.use) - { - dst_clip_x = dc->clip.x; - dst_clip_y = dc->clip.y; - dst_clip_w = dc->clip.w; - dst_clip_h = dc->clip.h; - if (dst_clip_x < 0) - { - dst_clip_w += dst_clip_x; - dst_clip_x = 0; - } - if (dst_clip_y < 0) - { - dst_clip_h += dst_clip_y; - dst_clip_y = 0; - } - if ((dst_clip_x + dst_clip_w) > dst_w) - dst_clip_w = dst_w - dst_clip_x; - if ((dst_clip_y + dst_clip_h) > dst_h) - dst_clip_h = dst_h - dst_clip_y; - } - else - { - dst_clip_x = 0; - dst_clip_y = 0; - dst_clip_w = dst_w; - dst_clip_h = dst_h; - } - - if (dst_clip_x < dst_region_x) - { - dst_clip_w += dst_clip_x - dst_region_x; - dst_clip_x = dst_region_x; - } - if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w)) - dst_clip_w = dst_region_x + dst_region_w - dst_clip_x; - if (dst_clip_y < dst_region_y) - { - dst_clip_h += dst_clip_y - dst_region_y; - dst_clip_y = dst_region_y; - } - if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h)) - dst_clip_h = dst_region_y + dst_region_h - dst_clip_y; - - if ((src_region_w <= 0) || (src_region_h <= 0) || - (dst_region_w <= 0) || (dst_region_h <= 0) || - (dst_clip_w <= 0) || (dst_clip_h <= 0)) + if (!(RECTS_INTERSECT(sr.x, sr.y, sr.w, sr.h, 0, 0, src->w, src->h))) return; - /* sanitise x */ - if (src_region_x < 0) - { - dst_region_x -= (src_region_x * dst_region_w) / src_region_w; - dst_region_w += (src_region_x * dst_region_w) / src_region_w; - src_region_w += src_region_x; - src_region_x = 0; - } - if (src_region_x >= src_w) return; - if ((src_region_x + src_region_w) > src_w) - { - dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w); - src_region_w = src_w - src_region_x; - } - if (dst_region_w <= 0) return; - if (src_region_w <= 0) return; - if (dst_clip_x < 0) - { - dst_clip_w += dst_clip_x; - dst_clip_x = 0; - } - if (dst_clip_w <= 0) return; - if (dst_clip_x >= dst_w) return; - if (dst_clip_x < dst_region_x) - { - dst_clip_w += (dst_clip_x - dst_region_x); - dst_clip_x = dst_region_x; - } - if ((dst_clip_x + dst_clip_w) > dst_w) - { - dst_clip_w = dst_w - dst_clip_x; - } - if (dst_clip_w <= 0) return; - - /* sanitise y */ - if (src_region_y < 0) - { - dst_region_y -= (src_region_y * dst_region_h) / src_region_h; - dst_region_h += (src_region_y * dst_region_h) / src_region_h; - src_region_h += src_region_y; - src_region_y = 0; - } - if (src_region_y >= src_h) return; - if ((src_region_y + src_region_h) > src_h) - { - dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h); - src_region_h = src_h - src_region_y; - } - if (dst_region_h <= 0) return; - if (src_region_h <= 0) return; - if (dst_clip_y < 0) - { - dst_clip_h += dst_clip_y; - dst_clip_y = 0; - } - if (dst_clip_h <= 0) return; - if (dst_clip_y >= dst_h) return; - if (dst_clip_y < dst_region_y) - { - dst_clip_h += (dst_clip_y - dst_region_y); - dst_clip_y = dst_region_y; - } - if ((dst_clip_y + dst_clip_h) > dst_h) - { - dst_clip_h = dst_h - dst_clip_y; - } - if (dst_clip_h <= 0) return; + _get_clip(dc, dst, &cr); + if (!_soft16_adjust_areas(&sr, src->w, src->h, &dr, dst->w, dst->h, &cr)) + return; src_data = src->pixels; srca_data = src->alpha; dst_data = dst->pixels; dsta_data = dst->alpha; - - dst_stride = dst->stride; - src_stride = src->stride; - - /* figure out dest start ptr */ - dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_stride); - dsta_ptr = dsta_data + dst_clip_x + (dst_clip_y * dst_stride); - func = _soft16_scanline_copy; - if (( src->alpha) && ( dst->alpha)) func = _soft16_scanline_blend; - else if (( src->alpha) && (!dst->alpha)) func = _soft16_scanline_blend; - else if ((!src->alpha) && ( dst->alpha)) func = _soft16_scanline_copy; - else if ((!src->alpha) && (!dst->alpha)) func = _soft16_scanline_copy; + /* figure out dest start ptr */ + dst_ptr = dst_data + cr.x + (cr.y * dst->stride); + dsta_ptr = dsta_data + cr.x + (cr.y * dst->stride); + +/* func = _soft16_scanline_copy; */ +/* if (( src->alpha) && ( dst->alpha)) func = _soft16_scanline_blend; */ +/* else if (( src->alpha) && (!dst->alpha)) func = _soft16_scanline_blend; */ +/* else if ((!src->alpha) && ( dst->alpha)) func = _soft16_scanline_copy; */ +/* else if ((!src->alpha) && (!dst->alpha)) func = _soft16_scanline_copy; */ /* not being scaled at all */ - if ((dst_region_w == src_region_w) && (dst_region_h == src_region_h)) - { - ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_stride) + (dst_clip_x - dst_region_x) + src_region_x; - aptr = srca_data + ((dst_clip_y - dst_region_y + src_region_y) * src_stride) + (dst_clip_x - dst_region_x) + src_region_x; - for (y = 0; y < dst_clip_h; y++) - { - /* * blend here [clip_w *] ptr -> dst_ptr * */ - func(ptr, aptr, NULL, dc->mul.col, dst_ptr, dst_clip_w); - ptr += src_stride; - aptr += src_stride; - dst_ptr += dst_stride; - } - } + if ((dr.w == sr.w) && (dr.h == sr.h)) + _soft16_image_draw_unscaled(src, dst, dc, sr, dr, cr); +#if 0 else { /* allocate scale lookup tables */ - lin_ptr = alloca(dst_clip_w * sizeof(int)); - row_ptr = alloca(dst_clip_h * sizeof(DATA16 *)); - rowa_ptr = alloca(dst_clip_h * sizeof(DATA8 *)); + lin_ptr = alloca(cr.w * sizeof(int)); + row_ptr = alloca(cr.h * sizeof(DATA16 *)); + rowa_ptr = alloca(cr.h * sizeof(DATA8 *)); /* fill scale tables */ - for (x = 0; x < dst_clip_w; x++) - lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x; - for (y = 0; y < dst_clip_h; y++) + for (x = 0; x < cr.w; x++) + lin_ptr[x] = (((x + cr.x - dr.x) * sr.w) / dr.w) + sr.x; + for (y = 0; y < cr.h; y++) { row_ptr[y] = src_data + - (((((y + dst_clip_y - dst_region_y) * src_region_h) / - dst_region_h) + src_region_y) * src_stride); + (((((y + cr.y - dr.y) * sr.h) / + dr.h) + sr.y) * src->stride); rowa_ptr[y] = srca_data + - (((((y + dst_clip_y - dst_region_y) * src_region_h) / - dst_region_h) + src_region_y) * src_stride); + (((((y + cr.y - dr.y) * sr.h) / + dr.h) + sr.y) * src->stride); } /* scale to dst */ dptr = dst_ptr; daptr = dsta_ptr; if ((!(src->alpha)) && (!(dst->alpha)) && (!dc->mul.use)) { - for (y = 0; y < dst_clip_h; y++) + for (y = 0; y < cr.h; y++) { dst_ptr = dptr; - for (x = 0; x < dst_clip_w; x++) + for (x = 0; x < cr.w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; dst_ptr++; } - dptr += dst_stride; + dptr += dst->stride; } } else { /* a scanline buffer */ - buf = alloca(dst_clip_w * sizeof(DATA16) * 2); + buf = alloca(cr.w * sizeof(DATA16) * 2); if (src->alpha) { - bufa = alloca(dst_clip_w * sizeof(DATA8) * 2); - for (y = 0; y < dst_clip_h; y++) + bufa = alloca(cr.w * sizeof(DATA8) * 2); + for (y = 0; y < cr.h; y++) { dst_ptr = dptr; - for (x = 0; x < dst_clip_w; x++) + for (x = 0; x < cr.w; x++) { ptr = row_ptr[y] + lin_ptr[x]; aptr = rowa_ptr[y] + lin_ptr[x]; @@ -517,7 +599,7 @@ _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, /* dst_ptr = buf; dsta_ptr = bufa; - for (x = 0; x < dst_clip_w; x++) + for (x = 0; x < cr.w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; @@ -527,17 +609,17 @@ _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, *dsta_ptr = *aptr; dsta_ptr++; } - func(buf, bufa, NULL, dc->mul.col, dptr, dst_clip_w); + func(buf, bufa, NULL, dc->mul.col, dptr, cr.w); */ - dptr += dst_stride; + dptr += dst->stride; } } else { - for (y = 0; y < dst_clip_h; y++) + for (y = 0; y < cr.h; y++) { dst_ptr = dptr; - for (x = 0; x < dst_clip_w; x++) + for (x = 0; x < cr.w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; @@ -545,19 +627,20 @@ _soft16_image_draw_sampled_int(Soft16_Image *src, Soft16_Image *dst, } /* dst_ptr = buf; - for (x = 0; x < dst_clip_w; x++) + for (x = 0; x < cr.w; x++) { ptr = row_ptr[y] + lin_ptr[x]; *dst_ptr = *ptr; dst_ptr++; } - func(buf, NULL, NULL, dc->mul.col, dptr, dst_clip_w); + func(buf, NULL, NULL, dc->mul.col, dptr, cr.w); */ - dptr += dst_stride; + dptr += dst->stride; } } } } +#endif } void @@ -569,25 +652,38 @@ soft16_image_draw(Soft16_Image *src, Soft16_Image *dst, int dst_region_w, int dst_region_h, int smooth) { + Evas_Rectangle sr, dr; Cutout_Rects *rects; Cutout_Rect *r; - int c, cx, cy, cw, ch; - int i; + int c, cx, cy, cw, ch; + int i; + /* handle cutouts here! */ - - if ((dst_region_w <= 0) || (dst_region_h <= 0)) return; - if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->w, dst->h))) + dr.x = dst_region_x; + dr.y = dst_region_y; + dr.w = dst_region_w; + dr.h = dst_region_h; + + if (_is_empty_rectangle(&dr)) return; + if (!(RECTS_INTERSECT(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->w, dst->h))) return; + + sr.x = src_region_x; + sr.y = src_region_y; + sr.w = src_region_w; + sr.h = src_region_h; + + if (_is_empty_rectangle(&sr)) return; + if (!(RECTS_INTERSECT(sr.x, sr.y, sr.w, sr.h, 0, 0, src->w, src->h))) + return; + /* no cutouts - cut right to the chase */ if (!dc->cutout.rects) { - _soft16_image_draw_sampled_int(src, dst, dc, - src_region_x, src_region_y, - src_region_w, src_region_h, - dst_region_x, dst_region_y, - dst_region_w, dst_region_h); + _soft16_image_draw_sampled_int(src, dst, dc, sr, dr); 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->w, dst->h); @@ -603,12 +699,7 @@ soft16_image_draw(Soft16_Image *src, Soft16_Image *dst, { r = rects->rects + i; evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); - _soft16_image_draw_sampled_int(src, dst, dc, - src_region_x, src_region_y, - src_region_w, src_region_h, - dst_region_x, dst_region_y, - dst_region_w, dst_region_h); - + _soft16_image_draw_sampled_int(src, dst, dc, sr, dr); } evas_common_draw_context_apply_clear_cutouts(rects); /* restore clip info */ @@ -616,126 +707,76 @@ soft16_image_draw(Soft16_Image *src, Soft16_Image *dst, } -static void -_soft16_scanline_blend(DATA16 *s, DATA8 *a, DATA8 *m, DATA32 c, DATA16 *d, int l) +static inline void +_soft16_scanline_blend_transp_solid(DATA16 *src, DATA8 *alpha, DATA16 *dst, int size) { - DATA16 *e = d + l; - DATA32 wsp, wdp; - DATA32 xsp, xdp; - DATA32 ysp, ydp; - DATA32 zsp, zdp; + DATA16 *start, *end; -/* - if (((unsigned long)(((DATA8 *)s)) & 0x3) == - (((unsigned long)((DATA8 *)d)) & 0x3)) - { - if (((unsigned long)(((DATA8 *)s)) & 0x3) == 2) - { - wsp = (*s | (*s << 16)) & 0x07e0f81f; - wdp = (*d | (*d << 16)) & 0x07e0f81f; - wdp = (((wdp * (32 - *a)) >> 5) & 0x07e0f81f) + wsp; - *d = wdp | (wdp >> 16); - s++; a++; d++; - } - e -= 3; - while (d < e) - { - wsp = (s[0] | (s[0] << 16)) & 0x07e0f81f; - xsp = (s[1] | (s[1] << 16)) & 0x07e0f81f; - ysp = (s[2] | (s[2] << 16)) & 0x07e0f81f; - zsp = (s[3] | (s[3] << 16)) & 0x07e0f81f; - wdp = (d[0] | (d[0] << 16)) & 0x07e0f81f; - xdp = (d[1] | (d[1] << 16)) & 0x07e0f81f; - ydp = (d[2] | (d[2] << 16)) & 0x07e0f81f; - zdp = (d[3] | (d[3] << 16)) & 0x07e0f81f; - wdp = (((wdp * (32 - a[0])) >> 5) & 0x07e0f81f) + wsp; - xdp = (((xdp * (32 - a[1])) >> 5) & 0x07e0f81f) + xsp; - ydp = (((ydp * (32 - a[2])) >> 5) & 0x07e0f81f) + ysp; - zdp = (((zdp * (32 - a[3])) >> 5) & 0x07e0f81f) + zsp; - *((DATA32 *)d) = - ((xdp | (xdp >> 16)) << 16) | - ((wdp | (wdp >> 16)) & 0x0000ffff); - d += 2; - *((DATA32 *)d) = - ((zdp | (zdp >> 16)) << 16) | - ((ydp | (ydp >> 16)) & 0x0000ffff); - d += 2; - s += 4; a += 4; - } - e += 3; - while (d < e) - { - wsp = (*s | (*s << 16)) & 0x07e0f81f; - wdp = (*d | (*d << 16)) & 0x07e0f81f; - wdp = (((wdp * (32 - *a)) >> 5) & 0x07e0f81f) + wsp; - *d = wdp | (wdp >> 16); - s++; a++; d++; - } + pld(alpha, 0); + pld(src, 0); + start = dst; + end = start + (size & ~7); + +#define BLEND(dst, src, alpha) \ + if (UNLIKELY(alpha == 31)) \ + (dst) = (src); \ + else if (alpha != 0) \ + { \ + DATA32 a, b; \ + a = RGB_565_UNPACK(src); \ + b = RGB_565_UNPACK(dst); \ + b = RGB_565_UNPACKED_BLEND(a, b, alpha); \ + dst = RGB_565_PACK(b); \ } - else - */ + + /* work on 8 pixels per time, do data preload */ + while (start < end) { - while (d < e) - { - wsp = (*s | (*s << 16)) & 0x07e0f81f; - wdp = (*d | (*d << 16)) & 0x07e0f81f; - wdp = (((wdp * (32 - *a)) >> 5) & 0x07e0f81f) + wsp; - *d = wdp | (wdp >> 16); - s++; a++; d++; - } + DATA8 alpha1, alpha2; + + alpha1 = alpha[0]; + alpha += 8; + + /* empirical tests show these give the best performance */ + pld(alpha, 8); + pld(src, 32); + + src += 8; + start += 8; + + alpha2 = alpha[-7]; + BLEND(start[-8], src[-8], alpha1); + + alpha1 = alpha[-6]; + BLEND(start[-7], src[-7], alpha2); + + alpha2 = alpha[-5]; + BLEND(start[-6], src[-6], alpha1); + + alpha1 = alpha[-4]; + BLEND(start[-5], src[-5], alpha2); + + alpha2 = alpha[-3]; + BLEND(start[-4], src[-4], alpha1); + + alpha1 = alpha[-2]; + BLEND(start[-3], src[-3], alpha2); + + alpha2 = alpha[-1]; + BLEND(start[-2], src[-2], alpha1); + + BLEND(start[-1], src[-1], alpha2); } + + /* remaining pixels (up to 7) */ + end = start + (size & 7); + for (; start < end; start++, src++, alpha++) + BLEND(*start, *src, *alpha); +#undef BLEND } -//#define MEMCPY 1 -//#define SIMPLE 1 - -static void -_soft16_scanline_copy(DATA16 *s, DATA8 *a, DATA8 *m, DATA32 c, DATA16 *d, int l) +static inline void +_soft16_scanline_blend_solid_solid(DATA16 *src, DATA16 *dst, int size) { -#ifdef MEMCPY - memcpy(d, s, l * sizeof(DATA16)); -#else - DATA16 *e = d + l; - -#ifdef SIMPLE - while (d < e) - { - *d = *s; - d++; - s++; - } -#else - if (((unsigned long)(((DATA8 *)s)) & 0x3) == - (((unsigned long)((DATA8 *)d)) & 0x3)) - { - if (((unsigned long)(((DATA8 *)s)) & 0x3) == 2) - { - *d = *s; - d++; - s++; - } - e -= 1; - while (d < e) - { - *((DATA32 *)d) = *((DATA32 *)s); - d += 2; - s += 2; - } - e += 1; - if (d < e) - { - *d = *s; - } - } - else - { - while (d < e) - { - *d = *s; - d++; - s++; - } - } -#endif -#endif + memcpy(dst, src, size * sizeof(DATA16)); }