From aa591640017b29a9ca51d9bcd54f0be9a2bd3aef Mon Sep 17 00:00:00 2001 From: Brett Nash Date: Sun, 6 Feb 2011 23:52:17 +0000 Subject: [PATCH] Support for Proxy Objects (and others) Proxy objects allow you to use another image as the source of an image. Essentially allowing the same object to be rendered multiple times. One object (the source) is the original, each additional 'copy' is an image with evas_object_image_source_set. This is complete. Also add partially working arbitrary maps, and arbitrary clipping. Unfortunately both have some issues yet to be resolved (waiting on the next feature to get merged together). SVN revision: 56777 --- legacy/evas/.gitignore | 3 + legacy/evas/src/lib/Evas.h | 20 +++- legacy/evas/src/lib/canvas/evas_map.c | 98 ++++++++++++------- .../evas/src/lib/canvas/evas_object_image.c | 52 ++++++++-- .../evas/src/lib/canvas/evas_object_proxy.c | 95 +++++++++++++----- legacy/evas/src/lib/canvas/evas_render.c | 18 +++- .../engines/common/evas_convert_colorspace.c | 30 ++++++ .../src/lib/engines/common/evas_map_image.c | 16 +-- .../src/lib/engines/common/evas_map_image.h | 4 +- .../evas/src/lib/engines/common/evas_pipe.h | 4 +- legacy/evas/src/lib/include/evas_common.h | 1 + legacy/evas/src/lib/include/evas_private.h | 2 +- .../engines/gl_common/shader/.gitignore | 1 + .../engines/gl_common/shader/img_mask_frag.h | 11 +++ .../gl_common/shader/img_mask_frag.shd | 11 +++ .../engines/gl_common/shader/img_mask_vert.h | 16 +++ .../gl_common/shader/img_mask_vert.shd | 16 +++ .../src/modules/engines/gl_x11/evas_engine.c | 4 +- .../engines/software_generic/evas_engine.c | 16 ++- 19 files changed, 331 insertions(+), 87 deletions(-) create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/.gitignore create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.h create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.h create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.shd diff --git a/legacy/evas/.gitignore b/legacy/evas/.gitignore index 0024e2d056..638192ce83 100644 --- a/legacy/evas/.gitignore +++ b/legacy/evas/.gitignore @@ -7,6 +7,7 @@ Makefile Makefile.in *.so +.*.sw[po] /README /aclocal.m4 /autom4te.cache/ @@ -25,3 +26,5 @@ Makefile.in /ltmain.sh /missing /stamp-h1 +tags +cscope.out diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index a0701f283c..e8bccc9f68 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -164,7 +164,7 @@ typedef enum _Evas_Colorspace EVAS_COLORSPACE_YCBCR422P601_PL, /**< YCbCr 4:2:2 Planar, ITU.BT-601 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */ EVAS_COLORSPACE_YCBCR422P709_PL,/**< YCbCr 4:2:2 Planar, ITU.BT-709 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */ EVAS_COLORSPACE_RGB565_A5P, /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */ - EVAS_COLORSPACE_GRY8 /**< 8bit grayscale */ + EVAS_COLORSPACE_GRY8, /**< 8bit grayscale */ } Evas_Colorspace; /**< Colorspaces for pixel data supported by Evas */ /** @@ -331,7 +331,7 @@ typedef enum _Evas_Pixel_Import_Pixel_Format { EVAS_PIXEL_FORMAT_NONE = 0, /**< No pixel format */ EVAS_PIXEL_FORMAT_ARGB32 = 1, /**< ARGB 32bit pixel format with A in the high byte per 32bit pixel word */ - EVAS_PIXEL_FORMAT_YUV420P_601 = 2 /**< YUV 420 Planar format with CCIR 601 color encoding wuth contiguous planes in the order Y, U and V */ + EVAS_PIXEL_FORMAT_YUV420P_601 = 2, /**< YUV 420 Planar format with CCIR 601 color encoding wuth contiguous planes in the order Y, U and V */ } Evas_Pixel_Import_Pixel_Format; /**< Pixel format for import call. See evas_object_image_pixels_import() */ struct _Evas_Pixel_Import_Source @@ -995,6 +995,7 @@ typedef void (*Evas_Async_Events_Put_Cb)(void *target, Evas_Callback_Type t EAPI Eina_Bool evas_map_alpha_get (const Evas_Map *m); EAPI Evas_Map *evas_map_dup (const Evas_Map *m); EAPI void evas_map_free (Evas_Map *m); + EAPI int evas_map_count_get (const Evas_Map *m) EINA_CONST; EAPI void evas_map_point_coord_set (Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z); EAPI void evas_map_point_coord_get (const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z); EAPI void evas_map_point_image_uv_set (Evas_Map *m, int idx, double u, double v); @@ -1229,6 +1230,11 @@ typedef void (*Evas_Object_Intercept_Clip_Unset_Cb) (void *data, Evas_Object *ob * * R = (r * a) / 32; G = (g * a) / 32; B = (b * a) / 32; * + * EVAS_COLORSPACE_A8: + * + * The image is just a alpha mask (8 bit's per pixel). This is used for alpha + * masking. + * * @ingroup Evas_Object_Specific */ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); @@ -1287,6 +1293,8 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o); EAPI void evas_object_image_content_hint_set (Evas_Object *obj, Evas_Image_Content_Hint hint) EINA_ARG_NONNULL(1); EAPI Evas_Image_Content_Hint evas_object_image_content_hint_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; + EAPI void evas_object_image_alpha_mask_set (Evas_Object *, Eina_Bool) EINA_ARG_NONNULL(1); + /** * @defgroup Evas_Object_Text Text Object Functions * @@ -2091,7 +2099,13 @@ struct _Evas_Smart_Cb_Description /** * @defgroup Evas_Proxy Evas Proxy Objects * - * Provides a way of applying effects to complete objects. + * @brief Provides a way of applying effects to complete objects. + * + * A proxy object is a visible copy of another object. Generally a map or + * similar effect will be applied to the proxy to apply some sort of rendering + * effect to. + * + * Proxies are generally used for special effects. */ EAPI Evas_Object *evas_object_proxy_add (Evas *e) EINA_MALLOC; EAPI Eina_Bool evas_object_proxy_source_set (Evas_Object *o, Evas_Object *source); diff --git a/legacy/evas/src/lib/canvas/evas_map.c b/legacy/evas/src/lib/canvas/evas_map.c index 42974ef90d..63f957dd80 100644 --- a/legacy/evas/src/lib/canvas/evas_map.c +++ b/legacy/evas/src/lib/canvas/evas_map.c @@ -96,7 +96,15 @@ static inline Evas_Map * _evas_map_new(int count) { int i; - Evas_Map *m = calloc(1, sizeof(Evas_Map) + (count * sizeof(Evas_Map_Point))); + int alloc; + Evas_Map *m; + + /* Adjust allocation such that: at least 4 points, and always an even + * number: this allows the software engine to work efficiently */ + alloc = (count < 4) ? 4 : count; + if (alloc & 0x1) alloc ++; + + m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point))); if (!m) return NULL; m->count = count; m->persp.foc = 0; @@ -155,24 +163,24 @@ Eina_Bool evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord *mx, Evas_Coord *my, int grab) { - int i, j, edges, edge[4][2], douv; + int i, j, edges, edge[m->count][2], douv; Evas_Coord xe[2]; double u[2] = { 0.0, 0.0 }; double v[2] = { 0.0, 0.0 }; - if (m->count != 4) return 0; + if (m->count < 4) return 0; // FIXME need to handle grab mode and extrapolte coords outside // map if (grab) { Evas_Coord ymin, ymax; - + ymin = m->points[0].y; ymax = m->points[0].y; for (i = 1; i < m->count; i++) { - if (m->points[i].y < ymin) ymin = m->points[i].y; - else if (m->points[i].y > ymax) ymax = m->points[i].y; + if (m->points[i].y < ymin) ymin = m->points[i].y; + else if (m->points[i].y > ymax) ymax = m->points[i].y; } if (y <= ymin) y = ymin + 1; if (y >= ymax) y = ymax - 1; @@ -250,12 +258,12 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, if (xe[0] > xe[1]) { int ti; - + ti = xe[0]; xe[0] = xe[1]; xe[1] = ti; if (douv) { double td; - + td = u[0]; u[0] = u[1]; u[1] = td; td = v[0]; v[0] = v[1]; v[1] = td; } @@ -264,11 +272,11 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, { if (douv) { - if (mx) - *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / + if (mx) + *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / (xe[1] - xe[0])); if (my) - *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / + *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / (xe[1] - xe[0])); } return 1; @@ -277,11 +285,11 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, { if (douv) { - if (mx) - *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / + if (mx) + *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / (xe[1] - xe[0])); if (my) - *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / + *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / (xe[1] - xe[0])); } return 1; @@ -471,21 +479,23 @@ evas_object_map_set(Evas_Object *obj, const Evas_Map *map) } return; } - if (!obj->cur.map) - { - obj->cur.map = _evas_map_dup(map); - if (obj->cur.usemap) - evas_object_mapped_clip_across_mark(obj); - } - else + + if (obj->cur.map && obj->cur.map->count == map->count) { Evas_Map *omap = obj->cur.map; - obj->cur.map = _evas_map_new(4); - memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (4 * sizeof(Evas_Map_Point))); + obj->cur.map = _evas_map_new(map->count); + memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point))); _evas_map_copy(obj->cur.map, map); if (obj->prev.map == omap) obj->prev.map = NULL; free(omap); } + else + { + if (obj->cur.map) evas_map_free(obj->cur.map); + obj->cur.map = _evas_map_dup(map); + if (obj->cur.usemap) + evas_object_mapped_clip_across_mark(obj); + } _evas_map_calc_map_geometry(obj); } @@ -543,9 +553,9 @@ evas_object_map_get(const Evas_Object *obj) EAPI Evas_Map * evas_map_new(int count) { - if (count != 4) + if (count < 4) { - ERR("num (%i) != 4 is unsupported!", count); + ERR("num (%i) < 4 is unsupported!", count); return NULL; } return _evas_map_new(count); @@ -644,6 +654,21 @@ evas_map_free(Evas_Map *m) _evas_map_free(NULL, m); } +/** + * Get a maps size. + * + * Returns the number of points in a map. Should be at least 4. + * + * @param m map to get size. + * @return -1 on error, points otherwise. + */ +EAPI int +evas_map_count_get(const Evas_Map *m) +{ + if (!m) return -1; + return m->count; +} + /** * Change the map point's coordinate. * @@ -1216,10 +1241,11 @@ evas_map_util_3d_lighting(Evas_Map *m, x = m->points[i].x; y = m->points[i].y; z = m->points[i].z; - +printf("Normal %d\n",i); // calc normal - h = (i + m->count - 1) % m->count; // prev point - j = (i + 1) % m->count; // next point + h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point + j = (i + 1) % 4 + (i & ~0x3); // next point +printf("\tNext/Prev: %2d/%2d\n",h,j); x1 = m->points[h].x - x; y1 = m->points[h].y - y; @@ -1228,13 +1254,16 @@ evas_map_util_3d_lighting(Evas_Map *m, x2 = m->points[j].x - x; y2 = m->points[j].y - y; z2 = m->points[j].z - z; - +printf("\tX: %3.2lf,%3.2lf,%3.2lf\n",x,y,z); +printf("\tX1: %3.2lf,%3.2lf,%3.2lf\n",x1,y1,z1); +printf("\tX2: %3.2lf,%3.2lf,%3.2lf\n",x2,y2,z2); nx = (y1 * z2) - (z1 * y2); ny = (z1 * x2) - (x1 * z2); nz = (x1 * y2) - (y1 * x2); ln = (nx * nx) + (ny * ny) + (nz * nz); ln = sqrt(ln); +printf("\tLength: %3.2lf\n",ln); if (ln != 0.0) { @@ -1242,7 +1271,8 @@ evas_map_util_3d_lighting(Evas_Map *m, ny /= ln; nz /= ln; } - +printf("\tpoint %2d: %3.2lf,%3.2lf,%3.2lf normal: %3.2lf %3.2lf %3.2lf\n",i,x,y,z,nx,ny,nz); + // calc point -> light vector x = lx - x; y = ly - y; @@ -1265,9 +1295,11 @@ evas_map_util_3d_lighting(Evas_Map *m, mr = ar + ((lr - ar) * br); mg = ag + ((lg - ag) * br); mb = ab + ((lb - ab) * br); - mr = (mr * m->points[i].a) / 255; - mg = (mg * m->points[i].a) / 255; - mb = (mb * m->points[i].a) / 255; + if (m->points[i].a != 255){ + mr = (mr * m->points[i].a) / 255; + mg = (mg * m->points[i].a) / 255; + mb = (mb * m->points[i].a) / 255; + } m->points[i].r = (m->points[i].r * mr) / 255; m->points[i].g = (m->points[i].g * mg) / 255; m->points[i].b = (m->points[i].b * mb) / 255; diff --git a/legacy/evas/src/lib/canvas/evas_object_image.c b/legacy/evas/src/lib/canvas/evas_object_image.c index e66f83b7bf..ce05deb6be 100644 --- a/legacy/evas/src/lib/canvas/evas_object_image.c +++ b/legacy/evas/src/lib/canvas/evas_object_image.c @@ -2049,6 +2049,39 @@ evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hin } } +/** + * Enable an image to be used as an alpha mask. + * + * This will set any flags, and discard any excess image data not used as an + * alpha mask. + * + * Note there is little point in using a image as alpha mask unless it has an + * alpha channel. + * + * @param obj Object to use as an alpha mask. + * @param ismask Use image as alphamask, must be true. + */ +EAPI void +evas_object_image_alpha_mask_set(Evas_Object *obj, Eina_Bool ismask) +{ + Evas_Object_Image *o; + + if (!ismask) return; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + o = (Evas_Object_Image *)(obj->object_data); + MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); + return; + MAGIC_CHECK_END(); + + /* Convert to A8 if not already */ + + /* done */ + +} + /** * Get the content hint of a given image of the canvas. * @@ -2453,13 +2486,13 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su } o->dirty_pixels = 0; } - if ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)) + if ((obj->cur.map) && (obj->cur.map->count > 3) && (obj->cur.usemap)) { const Evas_Map_Point *p, *p_end; - RGBA_Map_Point pts[4], *pt; + RGBA_Map_Point pts[obj->cur.map->count], *pt; p = obj->cur.map->points; - p_end = p + 4; + p_end = p + obj->cur.map->count; pt = pts; pts[0].px = obj->cur.map->persp.px << FP; @@ -2483,9 +2516,14 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su else if (pt->v > (o->cur.image.h * FP1)) pt->v = (o->cur.image.h * FP1); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); } - obj->layer->evas->engine.func->image_map4_draw - (output, context, surface, o->engine_data, pts, - o->cur.smooth_scale | obj->cur.map->smooth, 0); + if (obj->cur.map->count & 0x1) + { + pts[obj->cur.map->count] = pts[obj->cur.map->count -1]; + } + + obj->layer->evas->engine.func->image_map_draw + (output, context, surface, o->engine_data, obj->cur.map->count, + pts, o->cur.smooth_scale | obj->cur.map->smooth, 0); } else { @@ -3256,3 +3294,5 @@ evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED evas_object_geometry_get(obj, NULL, NULL, &w, &h); evas_object_image_fill_set(obj, 0, 0, w, h); } + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/legacy/evas/src/lib/canvas/evas_object_proxy.c b/legacy/evas/src/lib/canvas/evas_object_proxy.c index 58dadda76e..8471bf8d24 100644 --- a/legacy/evas/src/lib/canvas/evas_object_proxy.c +++ b/legacy/evas/src/lib/canvas/evas_object_proxy.c @@ -21,6 +21,7 @@ typedef struct _Evas_Object_Proxy Evas_Map *defmap; Eina_Bool mapupdate; + Eina_Bool rendering; } Evas_Object_Proxy; @@ -98,6 +99,14 @@ static const Evas_Object_Func object_func = }; +/** + * Add a new proxy object. + * + * The proxy object must have a source set before it is useful. + * + * @param e Evas canvas to add proxy too. + * @return New proxy object. + */ EAPI Evas_Object * evas_object_proxy_add(Evas *e) { @@ -119,32 +128,33 @@ evas_object_proxy_add(Evas *e) return obj; } +/** + * Set the source object on a proxy object. + * + * Any existing source object will be removed. Setting the src to NULL clears + * the proxy object. + * + * You cannot set a proxy on a proxy. + * + * @param obj Proxy object. + * @param src Source of the proxy. + * @return EINA_TRUE on success, EINA_FALSE on error. + */ EAPI Eina_Bool evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src) { - Evas_Object_Proxy *o,*so; + Evas_Object_Proxy *o; MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); - return false; + return EINA_FALSE; MAGIC_CHECK_END(); o = obj->object_data; MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY); - return false; + return EINA_FALSE; MAGIC_CHECK_END(); - if (o->source == src) return true; - - if (src) - { - MAGIC_CHECK(src, Evas_Object, MAGIC_OBJ); - return false; - MAGIC_CHECK_END(); - so = src->object_data; - /* Stop the loop _now_ */ - /* FIXME: Should I check for smarts that contain proxies too? */ - if (so->magic == MAGIC_OBJ_PROXY) - return false; - } + if (src == obj) return EINA_FALSE; + if (o->source == src) return EINA_TRUE; if (o->source) { @@ -156,9 +166,15 @@ evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src) _proxy_set(obj, src); } - return true; + return EINA_TRUE; } +/** + * Get the current source object of a proxy. + * + * @param obj Proxy object + * @return Source object, or NULL on error. + */ EAPI Evas_Object * evas_object_proxy_source_get(Evas_Object *obj) { @@ -175,15 +191,23 @@ evas_object_proxy_source_get(Evas_Object *obj) return o->source; } +/** + * Clear the source on a proxy. + * + * This is equivalent to calling evas_object_proxy_source_set with a NULL + * source. + * + * @param obj Proxy object to clear source of. + * @return EINA_TRUE on success, EINA_FALSE on error. + */ EAPI Eina_Bool -evas_object_proxy_source_unset(Evas_Object *o) +evas_object_proxy_source_unset(Evas_Object *obj) { - return evas_object_proxy_source_set(o, NULL); + return evas_object_proxy_source_set(obj, NULL); } - /* Internal helpers */ static void evas_object_proxy_init(Evas_Object *obj) @@ -313,6 +337,30 @@ _proxy_render(Evas_Object *obj, void *output, void *context, o = obj->object_data; + if (o->rendering) + { + int r = rand() % 255; + int g = rand() % 255; + int b = rand() % 255; + printf("Ahh: Recursive proxies: Go away!\n"); + obj->layer->evas->engine.func->context_color_set(output, + context, + r,g,b,255); + obj->layer->evas->engine.func->context_multiplier_unset(output, + context); + obj->layer->evas->engine.func->context_render_op_set(output, context, + obj->cur.render_op); + obj->layer->evas->engine.func->rectangle_draw(output, + context, + surface, + obj->cur.geometry.x + x, + obj->cur.geometry.y + y, + obj->cur.geometry.w, + obj->cur.geometry.h); + return; + } + + if (!o->source) return; // ENFN->context_multiplier_unset(output, context); @@ -331,8 +379,10 @@ _proxy_render(Evas_Object *obj, void *output, void *context, } else { + o->rendering = true; _proxy_subrender(obj->layer->evas, o->source); pixels = o->source->proxy.surface; + o->rendering = false; } if (o->mapupdate) _proxy_map_update(obj); @@ -383,8 +433,9 @@ _proxy_render(Evas_Object *obj, void *output, void *context, pt->v = p->v * FP1; pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); } - obj->layer->evas->engine.func->image_map4_draw - (output, context, surface, pixels, pts, map->smooth, 0); + obj->layer->evas->engine.func->image_map_draw + (output, context, surface, pixels, map->count, pts, + map->smooth, 0); } else { diff --git a/legacy/evas/src/lib/canvas/evas_render.c b/legacy/evas/src/lib/canvas/evas_render.c index 25b8789d7d..26a4b13889 100644 --- a/legacy/evas/src/lib/canvas/evas_render.c +++ b/legacy/evas/src/lib/canvas/evas_render.c @@ -703,7 +703,10 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, // set render_pre - for child objs that may not have gotten it. obj->pre_render_done = 1; - + RD(" Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map, + obj->func->can_map ? obj->func->can_map(obj): -1, + obj->cur.map, obj->cur.usemap, + _evas_render_has_map(obj)); if (_evas_render_has_map(obj)) { const Evas_Map_Point *p, *p_end; @@ -730,7 +733,7 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, pts[0].z0 = obj->cur.map->persp.z0 << FP; p = obj->cur.map->points; - p_end = p + 4; + p_end = p + obj->cur.map->count; pt = pts; for (; p < p_end; p++, pt++) { @@ -748,6 +751,12 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, else if (pt->v > (sh * FP1)) pt->v = (sh * FP1); pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b); } + /* Copy last for software engine */ + if (obj->cur.map->count & 0x1) + { + pts[obj->cur.map->count] = pts[obj->cur.map->count - 1]; + } + if (obj->cur.map->surface) { @@ -937,9 +946,10 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, } } if (obj->cur.cache.clip.visible) - obj->layer->evas->engine.func->image_map4_draw + obj->layer->evas->engine.func->image_map_draw (e->engine.data.output, e->engine.data.context, surface, - obj->cur.map->surface, pts, obj->cur.map->smooth, 0); + obj->cur.map->surface, obj->cur.map->count, pts, + obj->cur.map->smooth, 0); // FIXME: needs to cache these maps and // keep them only rendering updates // obj->layer->evas->engine.func->image_map_surface_free diff --git a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c index 75711bb9f9..c0918ee21b 100644 --- a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c +++ b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c @@ -9,6 +9,9 @@ #define CONVERT_A5P_TO_A8(s) \ ((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) +#define CONVERT_ARGB_8888_TO_A_8(s) ((s) >> 24) + + static inline void * evas_common_convert_argb8888_to_rgb565_a5p(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__, int stride __UNUSED__, Eina_Bool has_alpha __UNUSED__) { @@ -43,6 +46,28 @@ evas_common_convert_rgb565_a5p_to_argb8888(void *data, int w, int h, int stride, return ret; } +static inline void * +evas_common_convert_argb8888_to_a8(void *data, int w, int h, int stride, Eina_Bool has_alpha) +{ + uint32_t *src, *end; + uint8_t *ret, *dst; + + src = data; + end = src + (stride * h); + ret = malloc(w * h); + + if (!has_alpha) + { + return memset(ret,0xff, w * h); + } + + for ( ; src < end ; src ++, dst ++) + *dst = CONVERT_ARGB_8888_TO_A_8(*src); + return ret; +} + + + EAPI void * evas_common_convert_argb8888_to(void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace) { @@ -50,6 +75,8 @@ evas_common_convert_argb8888_to(void *data, int w, int h, int stride, Eina_Bool { case EVAS_COLORSPACE_RGB565_A5P: return evas_common_convert_argb8888_to_rgb565_a5p(data, w, h, stride, has_alpha); + case EVAS_COLORSPACE_A8: + return evas_common_convert_argb8888_to_a8(data, w, h, stride, has_alpha); default: break; } @@ -68,3 +95,6 @@ evas_common_convert_rgb565_a5p_to(void *data, int w, int h, int stride, Eina_Boo } return NULL; } + + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ 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 41b71a1b05..733091034a 100644 --- a/legacy/evas/src/lib/engines/common/evas_map_image.c +++ b/legacy/evas/src/lib/engines/common/evas_map_image.c @@ -325,23 +325,23 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy #ifdef BUILD_SCALE_SMOOTH # ifdef BUILD_MMX # undef FUNC_NAME -# define FUNC_NAME evas_common_map4_rgba_internal_mmx +# define FUNC_NAME evas_common_map_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 +# define FUNC_NAME evas_common_map_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, +evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, - RGBA_Map_Point *p, + int npoints, RGBA_Map_Point *p, int smooth, int level) { #ifdef BUILD_MMX @@ -363,11 +363,11 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst, { #ifdef BUILD_MMX if (mmx) - evas_common_map4_rgba_internal_mmx(src, dst, dc, p, smooth, level); + evas_common_map_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); + evas_common_map_rgba_internal(src, dst, dc, p, smooth, level); #endif return; } @@ -387,11 +387,11 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst, 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); + evas_common_map_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); + evas_common_map_rgba_internal(src, dst, dc, p, smooth, level); #endif } evas_common_draw_context_apply_clear_cutouts(rects); diff --git a/legacy/evas/src/lib/engines/common/evas_map_image.h b/legacy/evas/src/lib/engines/common/evas_map_image.h index 883b278e06..a7cb8cf6b6 100644 --- a/legacy/evas/src/lib/engines/common/evas_map_image.h +++ b/legacy/evas/src/lib/engines/common/evas_map_image.h @@ -2,9 +2,9 @@ #define _EVAS_MAP_H EAPI void -evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst, +evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, - RGBA_Map_Point *points, + int npoints, RGBA_Map_Point *points, int smooth, int level); #endif /* _EVAS_MAP_H */ diff --git a/legacy/evas/src/lib/engines/common/evas_pipe.h b/legacy/evas/src/lib/engines/common/evas_pipe.h index 73213b6114..a6662c9b7b 100644 --- a/legacy/evas/src/lib/engines/common/evas_pipe.h +++ b/legacy/evas/src/lib/engines/common/evas_pipe.h @@ -95,8 +95,8 @@ EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGB EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_Text_Props *intl_props); EAPI void evas_common_pipe_image_load(RGBA_Image *im); EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, 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); -EAPI void evas_common_pipe_map4_begin(RGBA_Image *root); -EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, +EAPI void evas_common_pipe_map_begin(RGBA_Image *root); +EAPI void evas_common_pipe_map_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, int smooth, int level); EAPI void evas_common_pipe_flush(RGBA_Image *im); diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index b43f937c39..5d6ee93c73 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -664,6 +664,7 @@ struct _RGBA_Draw_Context DATA32 col; } col; struct RGBA_Draw_Context_clip { + DATA8 *mask; int x, y, w, h; Eina_Bool use : 1; } clip; diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 23d1fc0bf8..26b1b623a3 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -672,7 +672,7 @@ struct _Evas_Func int (*image_scale_hint_get) (void *data, void *image); int (*font_last_up_to_pos) (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y); - void (*image_map4_draw) (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level); + void (*image_map_draw) (void *data, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level); void *(*image_map_surface_new) (void *data, int w, int h, int alpha); void (*image_map_surface_free) (void *data, void *surface); diff --git a/legacy/evas/src/modules/engines/gl_common/shader/.gitignore b/legacy/evas/src/modules/engines/gl_common/shader/.gitignore new file mode 100644 index 0000000000..a01ee289f9 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.h b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.h new file mode 100644 index 0000000000..0571c721f9 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.h @@ -0,0 +1,11 @@ +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"uniform sampler2D tex, texm;\n" +"varying vec4 col;\n" +"varying vec2 tex_c, tex_cm;\n" +"void main()\n" +"{\n" +" gl_FragColor = texture2D(texm, tex_cm.xy).aaaa * texture2D(tex, tex_c.xy).rgba * col;\n" +"}\n" +"\n" diff --git a/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.shd b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.shd new file mode 100644 index 0000000000..87aa2b7782 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_frag.shd @@ -0,0 +1,11 @@ +#ifdef GL_ES +precision mediump float; +#endif +uniform sampler2D tex, texm; +varying vec4 col; +varying vec2 tex_c, tex_cm; +void main() +{ + gl_FragColor = texture2D(texm, tex_cm.xy).aaaa * texture2D(tex, tex_c.xy).rgba * col; +} + diff --git a/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.h b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.h new file mode 100644 index 0000000000..5b52e41a18 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.h @@ -0,0 +1,16 @@ +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"attribute vec4 vertex;\n" +"attribute vec4 color;\n" +"attribute vec2 tex_coord, tex_coordm;\n" +"uniform mat4 mvp;\n" +"varying vec4 col;\n" +"varying vec2 tex_c, tex_cm;\n" +"void main()\n" +"{\n" +" gl_Position = mvp * vertex;\n" +" col = color;\n" +" tex_c = tex_coord;\n" +" tex_cm = tex_coordm;\n" +"}\n" diff --git a/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.shd b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.shd new file mode 100644 index 0000000000..f91b545232 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/img_mask_vert.shd @@ -0,0 +1,16 @@ +#ifdef GL_ES +precision mediump float; +#endif +attribute vec4 vertex; +attribute vec4 color; +attribute vec2 tex_coord, tex_coordm; +uniform mat4 mvp; +varying vec4 col; +varying vec2 tex_c, tex_cm; +void main() +{ + gl_Position = mvp * vertex; + col = color; + tex_c = tex_coord; + tex_cm = tex_coordm; +} diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index ccf3f9add9..851cfc71ff 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -1738,7 +1738,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image) } static void -eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { Evas_GL_Image *gim = image; Render_Engine *re; @@ -1942,7 +1942,7 @@ module_open(Evas_Module *em) ORD(image_scale_hint_get); ORD(image_stride_get); - ORD(image_map4_draw); + ORD(image_map_draw); ORD(image_map_surface_new); ORD(image_map_surface_free); diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index 84628e573c..fe4486f30e 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -506,12 +506,14 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image, } static void -eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level) +eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) { RGBA_Image *im; if (!image) return; + if (npoints < 3) return; im = image; + if ((p[0].x == p[3].x) && (p[1].x == p[2].x) && (p[0].y == p[1].y) && @@ -550,12 +552,18 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i && evas_common_frameq_enabled() # endif ) - evas_common_pipe_map4_draw(im, surface, context, p, smooth, level); + evas_common_pipe_map_draw(im, surface, context, npoints, p, smooth, level); else #endif - evas_common_map4_rgba(im, surface, context, p, smooth, level); + evas_common_map_rgba(im, surface, context, npoints, p, smooth, level); } evas_common_cpu_end_opt(); + + if (npoints > 4) + { + eng_image_map_draw(data, context, surface, image, npoints - 2, p + 2, + smooth, level); + } } static void * @@ -907,7 +915,7 @@ static Evas_Func func = /* more font draw functions */ eng_font_last_up_to_pos, /* FUTURE software generic calls go here (done) */ - eng_image_map4_draw, + eng_image_map_draw, eng_image_map_surface_new, eng_image_map_surface_free, NULL, // eng_image_content_hint_set - software doesn't use it