From: ChunEon Park Date: Tue, 14 Dec 2010 06:24:18 +0000 (+0900) Subject: merged evas image masking code from brett X-Git-Tag: 2.0_alpha~417 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f68b39f08155c074ab2a3c06cfce92b27a68a952;p=framework%2Fuifw%2Fevas.git merged evas image masking code from brett --- diff --git a/src/lib/Evas.h b/src/lib/Evas.h index 36a5739..1ff699d 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -162,7 +162,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 */ /** @@ -329,7 +329,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 @@ -977,6 +977,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); @@ -1211,6 +1212,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); @@ -2066,6 +2072,10 @@ struct _Evas_Smart_Cb_Description EAPI Eina_List *evas_object_table_children_get (const Evas_Object *o) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC; EAPI Evas_Object *evas_object_table_child_get (const Evas_Object *o, unsigned short col, unsigned short row) EINA_ARG_NONNULL(1); + EAPI Eina_Bool evas_object_image_source_set (Evas_Object *o, Evas_Object *source); + EAPI Evas_Object *evas_object_image_source_get (Evas_Object *o); + EAPI Eina_Bool evas_object_image_source_unset (Evas_Object *o); + /** * @defgroup Evas_Cserve Shared Image Cache Server * diff --git a/src/lib/canvas/evas_clip.c b/src/lib/canvas/evas_clip.c index 88defd6..55f7dad 100644 --- a/src/lib/canvas/evas_clip.c +++ b/src/lib/canvas/evas_clip.c @@ -263,11 +263,26 @@ evas_object_clip_set(Evas_Object *obj, Evas_Object *clip) obj->cur.clipper = clip; clip->clip.clipees = eina_list_append(clip->clip.clipees, obj); if (clip->clip.clipees) clip->cur.have_clipees = 1; + + /* If it's NOT a rectangle set the mask bits too */ + /* FIXME: Optmz ths chck */ + if (strcmp(evas_object_type_get(clip),"rectangle") == 0) + obj->cur.mask = NULL; + else + { + void *engdata; + obj->cur.mask = clip; + engdata = clip->func->engine_data_get(clip); + /* FIXME: Images only */ + clip->layer->evas->engine.func->image_mask_create( + clip->layer->evas->engine.data.output, + engdata); + } evas_object_change(clip); evas_object_change(obj); evas_object_clip_dirty(obj); evas_object_recalc_clippees(obj); - if ((!obj->smart.smart) && + if ((!obj->smart.smart) && (!((obj->cur.map) && (obj->cur.usemap)))) { if (evas_object_is_in_output_rect(obj, @@ -431,6 +446,31 @@ evas_object_clipees_get(const Evas_Object *obj) return obj->clip.clipees; } + +EAPI void +evas_object_mask_set(Evas_Object *obj, Evas_Object *mask) +{ + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + if (!mask) + { + //evas_object_clip_unset(obj); + return; + } + MAGIC_CHECK(mask, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + if (obj->cur.mask == mask) return; + if (obj == mask) return; + + obj->cur.mask = mask; + + evas_object_clip_set(obj, mask); +} + + + /** * @} */ diff --git a/src/lib/canvas/evas_map.c b/src/lib/canvas/evas_map.c index a623912..7051ee4 100644 --- a/src/lib/canvas/evas_map.c +++ b/src/lib/canvas/evas_map.c @@ -70,7 +70,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; @@ -129,24 +137,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; @@ -224,12 +232,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; } @@ -238,11 +246,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; @@ -251,11 +259,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; @@ -445,20 +453,22 @@ 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); 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); } @@ -516,9 +526,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); @@ -618,6 +628,21 @@ evas_map_free(Evas_Map *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. * * This sets the fixen point's coordinate in the map. Note that points @@ -1197,10 +1222,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; @@ -1209,13 +1235,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) { @@ -1223,7 +1252,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; @@ -1246,9 +1276,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/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index b5dcfd5..b6a67d5 100644 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -4,6 +4,8 @@ #include "../engines/common/evas_convert_colorspace.h" #include "../engines/common/evas_convert_yuv.h" +#define VERBOSE_PROXY_ERROR 1 + /* private magic number for image objects */ static const char o_type[] = "image"; @@ -26,6 +28,8 @@ struct _Evas_Object_Image double scale; } border; + Evas_Object *source; + Evas_Map *defmap; const char *file; const char *key; int cspace; @@ -62,6 +66,7 @@ struct _Evas_Object_Image unsigned char changed : 1; unsigned char dirty_pixels : 1; unsigned char filled : 1; + unsigned char proxyrendering : 1; }; /* private methods for image objects */ @@ -91,6 +96,11 @@ static int evas_object_image_can_map(Evas_Object *obj); static void *evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace); static void evas_object_image_filled_resize_listener(void *data, Evas *e, Evas_Object *obj, void *einfo); +static void _proxy_unset(Evas_Object *proxy); +static void _proxy_set(Evas_Object *proxy, Evas_Object *src); +static void _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, int x, int y); + + static const Evas_Object_Func object_func = { /* methods (compulsory) */ @@ -206,7 +216,7 @@ evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key) o->engine_data, obj); */ - + if (o->cur.source) _proxy_unset(obj); if (o->cur.file) eina_stringshare_del(o->cur.file); if (o->cur.key) eina_stringshare_del(o->cur.key); if (file) o->cur.file = eina_stringshare_add(file); @@ -299,6 +309,88 @@ evas_object_image_file_get(const Evas_Object *obj, const char **file, const char } /** + * 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_image_source_set(Evas_Object *obj, Evas_Object *src) +{ + Evas_Object_Image *o; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return EINA_FALSE; + MAGIC_CHECK_END(); + o = obj->object_data; + MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); + return EINA_FALSE; + MAGIC_CHECK_END(); + + if (src == obj) return EINA_FALSE; + if (o->cur.source == src) return EINA_TRUE; + + /* Kill the image if any */ + evas_object_image_file_set(obj, NULL, NULL); + + if (o->cur.source) + { + _proxy_unset(obj); + } + + if (src) + { + _proxy_set(obj, src); + } + + return EINA_TRUE; +} + + +/** + * Get the current source object of an image. + * + * @param obj Image object + * @return Source object, or NULL on error. + */ +EAPI Evas_Object * +evas_object_image_source_get(Evas_Object *obj) +{ + Evas_Object_Image *o; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return NULL; + MAGIC_CHECK_END(); + o = obj->object_data; + MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); + return NULL; + MAGIC_CHECK_END(); + + return o->cur.source; +} + +/** + * Clear the source on a proxy image. + * + * This is equivalent to calling evas_object_image_source_set with a NULL + * source. + * + * @param obj Image object to clear source of. + * @return EINA_TRUE on success, EINA_FALSE on error. + */ +EAPI Eina_Bool +evas_object_image_source_unset(Evas_Object *obj) +{ + return evas_object_image_source_set(obj, NULL); +} + +/** * Sets how much of each border of the given image object is not * to be scaled. * @@ -1895,6 +1987,7 @@ evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); return; MAGIC_CHECK_END(); + if (o->cur.source) _proxy_unset(obj); if (!obj->layer->evas->engine.func->image_native_set) return; o->engine_data = obj->layer->evas->engine.func->image_native_set(obj->layer->evas->engine.data.output, @@ -2188,6 +2281,159 @@ evas_image_cache_get(const Evas *e) */ /* all nice and private */ +static void +_proxy_unset(Evas_Object *proxy) +{ + Evas_Object_Image *o; + + o = proxy->object_data; + if (!o->cur.source) return; + + o->cur.source->proxy.proxies = eina_list_remove(o->cur.source->proxy.proxies, proxy); + + o->cur.source = NULL; + if (o->cur.defmap) + { + evas_map_free(o->cur.defmap); + o->cur.defmap = NULL; + } +} + + +static void +_proxy_set(Evas_Object *proxy, Evas_Object *src) +{ + Evas_Object_Image *o; + + o = proxy->object_data; + + evas_object_image_file_set(proxy, NULL, NULL); + + o->cur.source = src; + + src->proxy.proxies = eina_list_append(src->proxy.proxies, proxy); + src->proxy.redraw = EINA_TRUE; +} + +/* Some moron just set a proxy on a proxy. + * Give them some pixels. A random color + */ +static void +_proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, + int x, int y) +{ + Evas_Func *func; + int r = rand() % 255; + int g = rand() % 255; + int b = rand() % 255; + + /* XXX: Eina log error or something I'm sure + * If it bugs you, just fix it. Don't tell me */ + if (VERBOSE_PROXY_ERROR) printf("Err: Argh! Recursive proxies.\n"); + + func = proxy->layer->evas->engine.func; + func->context_color_set(output, context, r,g,b,255); + func->context_multiplier_unset(output, context); + func->context_render_op_set(output, context, proxy->cur.render_op); + func->rectangle_draw(output, context, surface, proxy->cur.geometry.x + x, + proxy->cur.geometry.y + y, + proxy->cur.geometry.w, + proxy->cur.geometry.h); + return; +} + +static void +_proxy_subrender_recurse(Evas_Object *obj, void *output, void *surface, void *ctx, int x, int y){ + Evas_Object *obj2; + Evas *e; + e = obj->layer->evas; + if (obj->clip.clipees) return; + if (!evas_object_is_visible(obj)) return; + obj->pre_render_done = 1; + ctx = e->engine.func->context_new(output); + if (obj->smart.smart) + { + EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2){ + _proxy_subrender_recurse(obj2, output, surface, ctx, x,y); + } + } + else + { + obj->func->render(obj, output, ctx, surface,x,y); + } + e->engine.func->context_free(output, ctx); +} + + + +/** + * Render the source object when a proxy is set. + * + * Used to force a draw if necessary, else just makes sures it's available. + */ +static void +_proxy_subrender(Evas *e, Evas_Object *source) +{ + void *ctx; + Evas_Object *obj2; + int w,h; + + if (!source) return; + + w = source->cur.geometry.w; + h = source->cur.geometry.h; + + source->proxy.redraw = EINA_FALSE; + + /* We need to redraw surface then */ + if (source->proxy.surface && (source->proxy.w != w || source->proxy.h != h)) + { + e->engine.func->image_map_surface_free(e->engine.data.output, + source->proxy.surface); + source->proxy.surface = NULL; + } + + /* FIXME: Hardcoded alpha 'on' */ + /* FIXME (cont): Should see if the object has alpha */ + if (!source->proxy.surface) + { + source->proxy.surface = e->engine.func->image_map_surface_new( + e->engine.data.output, w, h, 1); + source->proxy.w = w; + source->proxy.h = h; + } + + ctx = e->engine.func->context_new(e->engine.data.output); + e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0, 0, 0); + e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY); + e->engine.func->rectangle_draw(e->engine.data.output, ctx, + source->proxy.surface, 0, 0, w, h); + e->engine.func->context_free(e->engine.data.output, ctx); + + ctx = e->engine.func->context_new(e->engine.data.output); + if (source->smart.smart) + { + EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(source), obj2){ + _proxy_subrender_recurse(obj2, e->engine.data.output, + source->proxy.surface, + ctx, + -source->cur.geometry.x, + -source->cur.geometry.y); + } + } + else + { + source->func->render(source, e->engine.data.output, ctx, + source->proxy.surface, + -source->cur.geometry.x, + -source->cur.geometry.y); + } + + e->engine.func->context_free(e->engine.data.output, ctx); + source->proxy.surface = e->engine.func->image_dirty_region( + e->engine.data.output, source->proxy.surface, 0,0,w,h); + +} static void evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty) @@ -2359,6 +2605,7 @@ evas_object_image_new(void) o->cur.cspace = EVAS_COLORSPACE_ARGB8888; o->cur.spread = EVAS_TEXTURE_REPEAT; o->cur.opaque_valid = 0; + o->cur.source = NULL; o->prev = o->cur; return o; } @@ -2377,6 +2624,7 @@ evas_object_image_free(Evas_Object *obj) /* free obj */ if (o->cur.file) eina_stringshare_del(o->cur.file); if (o->cur.key) eina_stringshare_del(o->cur.key); + if (o->cur.source) _proxy_unset(obj); if (o->engine_data) { obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output, @@ -2396,6 +2644,8 @@ static void evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y) { Evas_Object_Image *o; + int imagew,imageh; + void *pixels; /* render object to surface with context, and offset by x,y */ o = (Evas_Object_Image *)(obj->object_data); @@ -2403,6 +2653,14 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1)) return; /* no error message, already printed in pre_render */ + /* Proxy sanity */ + if (o->proxyrendering) + { + _proxy_error(obj, context, output, surface, x, y); + return; + } + + obj->layer->evas->engine.func->context_color_set(output, context, 255, 255, 255, 255); @@ -2425,7 +2683,45 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op); - if (o->engine_data) + + if (0)// o->cur.source) + printf("Proxy: %p Source: %p Surface %p Redraw %s Type %s\n",obj, + o->cur.source,o->cur.source->proxy.surface, + o->cur.source->proxy.redraw?"yep":"nope",o->cur.source->type); + + if (!o->cur.source) + { + pixels = o->engine_data; + imagew = o->cur.image.w; + imageh = o->cur.image.h; + } + else if (o->cur.source->proxy.surface && !o->cur.source->proxy.redraw) + { + pixels = o->cur.source->proxy.surface; + imagew = o->cur.source->proxy.w; + imageh = o->cur.source->proxy.h; + } + else if (o->cur.source->type == o_type && + ((Evas_Object_Image *)o->cur.source->object_data)->engine_data) + { + Evas_Object_Image *oi; + oi = o->cur.source->object_data; + pixels = oi->engine_data; + imagew = oi->cur.image.w; + imageh = oi->cur.image.h; + } + else + { + o->proxyrendering = 1; + _proxy_subrender(obj->layer->evas, o->cur.source); + pixels = o->cur.source->proxy.surface; + imagew = o->cur.source->proxy.w; + imageh = o->cur.source->proxy.h; + o->proxyrendering = 0; + } + + + if (pixels) { Evas_Coord idw, idh, idx, idy; int ix, iy, iw, ih; @@ -2439,13 +2735,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; @@ -2464,16 +2760,21 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su 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, 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, pixels, obj->cur.map->count, + pts, o->cur.smooth_scale | obj->cur.map->smooth, 0); } else { obj->layer->evas->engine.func->image_scale_hint_set(output, - o->engine_data, + pixels, o->scale_hint); - o->engine_data = obj->layer->evas->engine.func->image_border_set(output, o->engine_data, + o->engine_data = obj->layer->evas->engine.func->image_border_set(output, pixels, o->cur.border.l, o->cur.border.r, o->cur.border.t, o->cur.border.b); idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw); @@ -2518,10 +2819,10 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su obj->layer->evas->engine.func->image_draw(output, context, surface, - o->engine_data, + pixels, 0, 0, - o->cur.image.w, - o->cur.image.h, + imagew, + imageh, obj->cur.geometry.x + ix + x, obj->cur.geometry.y + iy + y, iw, ih, @@ -2534,8 +2835,8 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su ox = obj->cur.geometry.x + ix + x; oy = obj->cur.geometry.y + iy + y; - imw = o->cur.image.w; - imh = o->cur.image.h; + imw = imagew; + imh = imageh; bl = o->cur.border.l; br = o->cur.border.r; bt = o->cur.border.t; @@ -2577,28 +2878,28 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su inw = bl; inh = bt; outx = ox; outy = oy; outw = bsl; outh = bst; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // .## // | inx = bl; iny = 0; inw = imw - bl - br; inh = bt; outx = ox + bsl; outy = oy; outw = iw - bsl - bsr; outh = bst; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // --# // | inx = imw - br; iny = 0; inw = br; inh = bt; outx = ox + iw - bsr; outy = oy; outw = bsr; outh = bst; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // .-- // # inx = 0; iny = bt; inw = bl; inh = imh - bt - bb; outx = ox; outy = oy + bst; outw = bsl; outh = ih - bst - bsb; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // .--. // |##| if (o->cur.border.fill > EVAS_BORDER_FILL_NONE) @@ -2613,12 +2914,12 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su { obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_COPY); - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); obj->layer->evas->engine.func->context_render_op_set(output, context, obj->cur.render_op); } else - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); } // --. // # @@ -2626,28 +2927,28 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su inw = br; inh = imh - bt - bb; outx = ox + iw - bsr; outy = oy + bst; outw = bsr; outh = ih - bst - bsb; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // | // #-- inx = 0; iny = imh - bb; inw = bl; inh = bb; outx = ox; outy = oy + ih - bsb; outw = bsl; outh = bsb; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // | // .## inx = bl; iny = imh - bb; inw = imw - bl - br; inh = bb; outx = ox + bsl; outy = oy + ih - bsb; outw = iw - bsl - bsr; outh = bsb; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); // | // --# inx = imw - br; iny = imh - bb; inw = br; inh = bb; outx = ox + iw - bsr; outy = oy + ih - bsb; outw = bsr; outh = bsb; - obj->layer->evas->engine.func->image_draw(output, context, surface, o->engine_data, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); + obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale); } idy += idh; if (dobreak_h) break; @@ -2665,6 +2966,7 @@ evas_object_image_render_pre(Evas_Object *obj) { Evas_Object_Image *o; int is_v, was_v; + Evas *e; /* dont pre-render the obj twice! */ if (obj->pre_render_done) return; @@ -2675,6 +2977,7 @@ evas_object_image_render_pre(Evas_Object *obj) /* then when this is done the object needs to figure if it changed and */ /* if so what and where and add the appropriate redraw rectangles */ o = (Evas_Object_Image *)(obj->object_data); + e = obj->layer->evas; if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1)) { @@ -2690,29 +2993,39 @@ evas_object_image_render_pre(Evas_Object *obj) evas_object_clip_recalc(obj->cur.clipper); obj->cur.clipper->func->render_pre(obj->cur.clipper); } + /* Proxy: Do it early */ + if (o->cur.source && o->cur.source->proxy.redraw) + { + /* XXX: Do I need to sort out the map here? */ + obj->changed = 1; + evas_add_rect(&e->clip_changes, + obj->cur.geometry.x, obj->cur.geometry.y, + obj->cur.geometry.w, obj->cur.geometry.h); + } + /* now figure what changed and add draw rects */ /* if it just became visible or invisible */ is_v = evas_object_is_visible(obj); was_v = evas_object_was_visible(obj); if (is_v != was_v) { - evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v); + evas_object_render_pre_visible_change(&e->clip_changes, obj, is_v, was_v); if (!o->pixel_updates) goto done; } if ((obj->cur.map != obj->prev.map) || (obj->cur.usemap != obj->prev.usemap)) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); goto done; } /* it's not visible - we accounted for it appearing or not so just abort */ if (!is_v) goto done; /* clipper changed this is in addition to anything else for obj */ - evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_clipper_change(&e->clip_changes, obj); /* if we restacked (layer or just within a layer) and don't clip anyone */ if (obj->restack) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } /* if it changed color */ @@ -2721,19 +3034,19 @@ evas_object_image_render_pre(Evas_Object *obj) (obj->cur.color.b != obj->prev.color.b) || (obj->cur.color.a != obj->prev.color.a)) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } /* if it changed render op */ if (obj->cur.render_op != obj->prev.render_op) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } /* if it changed anti_alias */ if (obj->cur.anti_alias != obj->prev.anti_alias) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if (o->changed) @@ -2744,7 +3057,7 @@ evas_object_image_render_pre(Evas_Object *obj) ((!o->cur.key) && (o->prev.key)) ) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if ((o->cur.image.w != o->prev.image.w) || @@ -2753,7 +3066,7 @@ evas_object_image_render_pre(Evas_Object *obj) (o->cur.cspace != o->prev.cspace) || (o->cur.smooth_scale != o->prev.smooth_scale)) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if ((o->cur.border.l != o->prev.border.l) || @@ -2763,12 +3076,12 @@ evas_object_image_render_pre(Evas_Object *obj) (o->cur.border.fill != o->prev.border.fill) || (o->cur.border.scale != o->prev.border.scale)) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if (o->dirty_pixels) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } } @@ -2787,7 +3100,7 @@ evas_object_image_render_pre(Evas_Object *obj) (!o->pixel_updates) ) { - evas_rects_return_difference_rects(&obj->layer->evas->clip_changes, + evas_rects_return_difference_rects(&e->clip_changes, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, @@ -2805,7 +3118,7 @@ evas_object_image_render_pre(Evas_Object *obj) (obj->cur.geometry.h != obj->prev.geometry.h)) ) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if (o->changed) @@ -2815,7 +3128,7 @@ evas_object_image_render_pre(Evas_Object *obj) (o->cur.fill.w != o->prev.fill.w) || (o->cur.fill.h != o->prev.fill.h)) { - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); if (!o->pixel_updates) goto done; } if ((o->cur.border.l == 0) && @@ -2832,7 +3145,7 @@ evas_object_image_render_pre(Evas_Object *obj) Evas_Coord idw, idh, idx, idy; int x, y, w, h; - obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output, o->engine_data, rr->x, rr->y, rr->w, rr->h); + e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, rr->x, rr->y, rr->w, rr->h); idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw); idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh); @@ -2861,7 +3174,7 @@ evas_object_image_render_pre(Evas_Object *obj) r.h = ((rr->h + 2) * h) / o->cur.image.h; r.x += obj->cur.geometry.x + x; r.y += obj->cur.geometry.y + y; - evas_add_rect(&obj->layer->evas->clip_changes, r.x, r.y, r.w, r.h); + evas_add_rect(&e->clip_changes, r.x, r.y, r.w, r.h); idy += h; } idx += idw; @@ -2879,8 +3192,8 @@ evas_object_image_render_pre(Evas_Object *obj) EINA_LIST_FREE(o->pixel_updates, r) eina_rectangle_free(r); - obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h); - evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj); + e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h); + evas_object_render_pre_prev_cur_add(&e->clip_changes, obj); goto done; } } @@ -2891,14 +3204,14 @@ evas_object_image_render_pre(Evas_Object *obj) if (evas_object_is_visible(obj) && evas_object_is_opaque(obj)) { - obj->layer->evas->engine.func->output_redraws_rect_del(obj->layer->evas->engine.data.output, + e->engine.func->output_redraws_rect_del(e->engine.data.output, obj->cur.cache.clip.x, obj->cur.cache.clip.y, obj->cur.cache.clip.w, obj->cur.cache.clip.h); } done: - evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v); + evas_object_render_pre_effect_updates(&e->clip_changes, obj, is_v, was_v); } static void @@ -2975,6 +3288,7 @@ evas_object_image_is_opaque(Evas_Object *obj) if (!o->engine_data) return 0; o->cur.opaque = 1; } + if (o->cur.source) return 0; /* FIXME: Should go poke at the object */ if ((obj->cur.map) && (obj->cur.usemap)) return 0; if (obj->cur.render_op == EVAS_RENDER_COPY) return 1; if (o->cur.has_alpha) return 0; @@ -3007,6 +3321,7 @@ evas_object_image_was_opaque(Evas_Object *obj) if (!o->engine_data) return 0; o->prev.opaque = 1; } + if (o->prev.source) return 0; /* FIXME: Should go poke at the object */ if (obj->prev.usemap) return 0; if (obj->prev.render_op == EVAS_RENDER_COPY) return 1; if (o->prev.has_alpha) return 0; @@ -3233,7 +3548,11 @@ static void evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *einfo __UNUSED__) { Evas_Coord w, h; + Evas_Object_Image *o; + o = obj->object_data; 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/src/lib/canvas/evas_object_main.c b/src/lib/canvas/evas_object_main.c index fe26a76..a6a70e1 100644 --- a/src/lib/canvas/evas_object_main.c +++ b/src/lib/canvas/evas_object_main.c @@ -21,11 +21,9 @@ evas_object_new(Evas *e __UNUSED__) obj = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object); if (!obj) return NULL; EVAS_MEMPOOL_PREP(_mp_obj, obj, Evas_Object); - obj->magic = MAGIC_OBJ; obj->cur.scale = 1.0; obj->prev.scale = 1.0; - return obj; } @@ -386,6 +384,8 @@ evas_object_del(Evas_Object *obj) evas_object_hide(obj); evas_object_grabs_cleanup(obj); while (obj->clip.clipees) evas_object_clip_unset(obj->clip.clipees->data); + while (obj->proxy.proxies) + evas_object_image_source_unset(obj->proxy.proxies->data); if (obj->cur.clipper) evas_object_clip_unset(obj); if (obj->smart.smart) evas_object_smart_del(obj); evas_object_map_set(obj, NULL); diff --git a/src/lib/canvas/evas_render.c b/src/lib/canvas/evas_render.c index 453a4fc..27599a9 100644 --- a/src/lib/canvas/evas_render.c +++ b/src/lib/canvas/evas_render.c @@ -191,6 +191,8 @@ _evas_render_phase1_direct(Evas *e, Eina_Array *render_objects) { unsigned int i; + Eina_List *l; + Evas_Object *proxy; RD(" [--- PHASE 1 DIRECT\n"); for (i = 0; i < render_objects->count; i++) @@ -201,12 +203,20 @@ _evas_render_phase1_direct(Evas *e, RD(" OBJ [%p] changed %i\n", obj, obj->changed); if (obj->changed) { + /* Flag need redraw on proxy too */ evas_object_clip_recalc(obj); obj->func->render_pre(obj); + if (obj->proxy.proxies) + { + RD(" has proxies:\n"); + obj->proxy.redraw = 1; + EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy) + proxy->func->render_pre(proxy); + } if (obj->pre_render_done) { RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n", - obj->smart.smart, + obj->smart.smart, evas_object_smart_members_get_direct(obj), obj->cur.map, obj->cur.usemap, obj->prev.map, obj->prev.usemap, @@ -647,7 +657,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; @@ -674,7 +687,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++) { @@ -687,6 +700,12 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, pt->v = p->v * 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) { @@ -862,9 +881,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 @@ -1213,6 +1233,17 @@ evas_render_updates_internal(Evas *e, obj->cur.cache.clip.w, obj->cur.cache.clip.h); } + if (obj->cur.mask) + e->engine.func->context_mask_set(e->engine.data.output, + e->engine.data.context, + obj->cur.mask->func->engine_data_get(obj->cur.mask), + obj->cur.mask->cur.geometry.x, + obj->cur.mask->cur.geometry.y, + obj->cur.mask->cur.geometry.w, + obj->cur.mask->cur.geometry.h); + else + e->engine.func->context_mask_unset(e->engine.data.output, + e->engine.data.context); if (obj->cur.clipper) e->engine.func->context_clip_set(e->engine.data.output, e->engine.data.context, @@ -1220,6 +1251,8 @@ evas_render_updates_internal(Evas *e, else e->engine.func->context_clip_unset(e->engine.data.output, e->engine.data.context); + + #if 1 /* FIXME: this can slow things down... figure out optimum... coverage */ for (j = offset; j < e->temporary_objects.count; ++j) { @@ -1605,3 +1638,6 @@ evas_render_object_recalc(Evas_Object *obj) obj->changed = 1; } } + + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/src/lib/engines/common/evas_blit_main.c b/src/lib/engines/common/evas_blit_main.c index 9322ffe..3f0bfee 100644 --- a/src/lib/engines/common/evas_blit_main.c +++ b/src/lib/engines/common/evas_blit_main.c @@ -7,9 +7,13 @@ #define ALIGN_FIX static void evas_common_copy_pixels_c (DATA32 *src, DATA32 *dst, int len); +#ifdef BUILD_MMX static void evas_common_copy_pixels_mmx (DATA32 *src, DATA32 *dst, int len); static void evas_common_copy_pixels_mmx2 (DATA32 *src, DATA32 *dst, int len); +#endif +#ifdef BUILD_SSE static void evas_common_copy_pixels_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len); +#endif #ifdef BUILD_NEON static void evas_common_copy_pixels_neon (DATA32 *src, DATA32 *dst, int len); @@ -17,8 +21,12 @@ static void evas_common_copy_pixels_rev_neon (DATA32 *src, DATA32 *dst, int len) #endif static void evas_common_copy_pixels_rev_c (DATA32 *src, DATA32 *dst, int len); +#ifdef BUILD_MMX static void evas_common_copy_pixels_rev_mmx (DATA32 *src, DATA32 *dst, int len); +#endif +#ifdef BUILD_SSE static void evas_common_copy_pixels_rev_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len); +#endif static void evas_common_copy_rev_pixels_c (DATA32 *src, DATA32 *dst, int len); diff --git a/src/lib/engines/common/evas_convert_colorspace.c b/src/lib/engines/common/evas_convert_colorspace.c index 75711bb..2886133 100644 --- a/src/lib/engines/common/evas_convert_colorspace.c +++ b/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) { @@ -68,3 +93,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/src/lib/engines/common/evas_draw.h b/src/lib/engines/common/evas_draw.h index 1c907d8..eb628c7 100644 --- a/src/lib/engines/common/evas_draw.h +++ b/src/lib/engines/common/evas_draw.h @@ -17,6 +17,9 @@ EAPI void evas_common_draw_context_unset_clip (RGBA_D EAPI void evas_common_draw_context_set_color (RGBA_Draw_Context *dc, int r, int g, int b, int a); EAPI void evas_common_draw_context_set_multiplier (RGBA_Draw_Context *dc, int r, int g, int b, int a); EAPI void evas_common_draw_context_unset_multiplier (RGBA_Draw_Context *dc); +EAPI void evas_common_draw_context_set_mask (RGBA_Draw_Context *dc, RGBA_Image *im, int x, int y, int w, int h); +EAPI void evas_common_draw_context_unset_mask (RGBA_Draw_Context *dc); + EAPI Cutout_Rects *evas_common_draw_context_cutouts_new (void); EAPI void evas_common_draw_context_cutouts_free (Cutout_Rects* rects); EAPI void evas_common_draw_context_cutouts_del (Cutout_Rects* rects, int index); diff --git a/src/lib/engines/common/evas_draw_main.c b/src/lib/engines/common/evas_draw_main.c index 8b8511a..e2d4568 100644 --- a/src/lib/engines/common/evas_draw_main.c +++ b/src/lib/engines/common/evas_draw_main.c @@ -153,6 +153,26 @@ evas_common_draw_context_unset_multiplier(RGBA_Draw_Context *dc) } EAPI void +evas_common_draw_context_set_mask(RGBA_Draw_Context *dc, RGBA_Image *mask, int x, int y, int w, int h) +{ + dc->mask.mask = mask; + dc->mask.x = x; + dc->mask.y = y; + dc->mask.w = w; + dc->mask.h = h; +} + +EAPI void +evas_common_draw_context_unset_mask(RGBA_Draw_Context *dc) +{ + dc->mask.mask = NULL; +} + + + + + +EAPI void evas_common_draw_context_add_cutout(RGBA_Draw_Context *dc, int x, int y, int w, int h) { // if (dc->cutout.rects > 512) return; diff --git a/src/lib/engines/common/evas_map_image.c b/src/lib/engines/common/evas_map_image.c index 40f4843..288f6a9 100644 --- a/src/lib/engines/common/evas_map_image.c +++ b/src/lib/engines/common/evas_map_image.c @@ -324,23 +324,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 @@ -362,11 +362,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; } @@ -386,11 +386,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/src/lib/engines/common/evas_map_image.h b/src/lib/engines/common/evas_map_image.h index 883b278..a7cb8cf 100644 --- a/src/lib/engines/common/evas_map_image.h +++ b/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/src/lib/engines/common/evas_pipe.h b/src/lib/engines/common/evas_pipe.h index e658e1f..de033f0 100644 --- a/src/lib/engines/common/evas_pipe.h +++ b/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_BiDi_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/src/lib/engines/common/evas_rectangle_main.c b/src/lib/engines/common/evas_rectangle_main.c index 28aaf16..222c6b7 100644 --- a/src/lib/engines/common/evas_rectangle_main.c +++ b/src/lib/engines/common/evas_rectangle_main.c @@ -54,20 +54,57 @@ rectangle_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, in RGBA_Gfx_Func func; int yy; DATA32 *ptr; + RGBA_Image *maskobj; + DATA8 *mask = NULL; RECTS_CLIP_TO_RECT(x, y, w, h, dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h); if ((w <= 0) || (h <= 0)) return; - func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, w, dc->render_op); + maskobj = dc->mask.mask; + if (maskobj) + { + func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, + dst, 1, dc->render_op); + mask = maskobj->mask.mask; + } + else + func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst, w, dc->render_op); ptr = dst->image.data + (y * dst->cache_entry.w) + x; - for (yy = 0; yy < h; yy++) + + if (!mask) { + for (yy = 0; yy < h; yy++) + { #ifdef EVAS_SLI - if (((yy + y) % dc->sli.h) == dc->sli.y) + if (((yy + y) % dc->sli.h) == dc->sli.y) #endif - { - func(NULL, NULL, dc->col.col, ptr, w); - } - ptr += dst->cache_entry.w; + { + func(NULL, NULL, dc->col.col, ptr, w); + } + ptr += dst->cache_entry.w; + } + } + else + { + /* X Adjust */ + mask += x - dc->mask.x; + /* Y Adjust */ + mask += (y - dc->mask.y) * maskobj->cache_entry.w; + /* Draw with mask */ + for (yy = 0; yy < h; yy++) + { +#ifdef EVAS_SLI + if (((yy + y) % dc->sli.h) == dc->sli.y) +#endif + { + func(NULL, mask, dc->col.col, ptr, w); + } + ptr += dst->cache_entry.w; + mask += maskobj->cache_entry.w; + } + } } + + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/src/lib/engines/common/evas_scale_sample.c b/src/lib/engines/common/evas_scale_sample.c index c6fa9f2..b544c05 100644 --- a/src/lib/engines/common/evas_scale_sample.c +++ b/src/lib/engines/common/evas_scale_sample.c @@ -94,6 +94,8 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h; int src_w, src_h, dst_w, dst_h; RGBA_Gfx_Func func; + RGBA_Image *maskobj; + DATA8 *mask = NULL; if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h))) return; @@ -235,7 +237,13 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, /* figure out dest start ptr */ dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_w); - if (dc->mul.use) + if (dc->mask.mask) + { + func = evas_common_gfx_func_composite_pixel_mask_span_get(src, dst, dst_clip_w, dc->render_op); + maskobj = dc->mask.mask; + mask = maskobj->mask.mask; + } + else if (dc->mul.use) func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op); else func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op); @@ -246,14 +254,20 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, for (y = 0; y < dst_clip_h; y++) { /* * blend here [clip_w *] ptr -> dst_ptr * */ + if (mask) + { + mask += dst_clip_x - dc->mask.x; + mask += (dst_clip_y - dc->mask.y) * maskobj->cache_entry.w; + } #ifdef EVAS_SLI if (((y + dst_clip_y) % dc->sli.h) == dc->sli.y) #endif { - func(ptr, NULL, dc->mul.col, dst_ptr, dst_clip_w); + func(ptr, mask, dc->mul.col, dst_ptr, dst_clip_w); } ptr += src_w; dst_ptr += dst_w; + if (mask) mask += maskobj->cache_entry.w; } } else diff --git a/src/lib/engines/common/evas_scale_smooth_scaler_noscale.c b/src/lib/engines/common/evas_scale_smooth_scaler_noscale.c index 957b6a3..fa3161f 100644 --- a/src/lib/engines/common/evas_scale_smooth_scaler_noscale.c +++ b/src/lib/engines/common/evas_scale_smooth_scaler_noscale.c @@ -1,27 +1,62 @@ { DATA32 *ptr; RGBA_Gfx_Func func; + RGBA_Image *maskobj; + DATA8 *mask = NULL; #ifdef EVAS_SLI int ysli = dst_clip_y; #endif ptr = src->image.data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x; - if (dc->mul.use) + if (dc->mask.mask) + { + func = evas_common_gfx_func_composite_pixel_mask_span_get(NULL, NULL, dst_clip_w, dc->render_op); + maskobj = dc->mask.mask; + mask = maskobj->mask.mask; + } + else if (dc->mul.use) func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, dst_clip_w, dc->render_op); else func = evas_common_gfx_func_composite_pixel_span_get(src, dst, dst_clip_w, dc->render_op); - while (dst_clip_h--) + + if (mask) + { + mask += dst_clip_x - dc->mask.x; + mask += (dst_clip_y - dc->mask.y) * maskobj->cache_entry.w; + while (dst_clip_h--) + { + +#ifdef EVAS_SLI + if (((ysli) % dc->sli.h) == dc->sli.y) +#endif + { + func(ptr, mask, dc->mul.col, dst_ptr, dst_clip_w); + } +#ifdef EVAS_SLI + ysli++; +#endif + ptr += src_w; + dst_ptr += dst_w; + mask += maskobj->cache_entry.w; + } + } + else { + while (dst_clip_h--) + { #ifdef EVAS_SLI - if (((ysli) % dc->sli.h) == dc->sli.y) + if (((ysli) % dc->sli.h) == dc->sli.y) #endif - { - func(ptr, NULL, dc->mul.col, dst_ptr, dst_clip_w); - } + { + func(ptr, NULL, dc->mul.col, dst_ptr, dst_clip_w); + } #ifdef EVAS_SLI - ysli++; + ysli++; #endif - ptr += src_w; - dst_ptr += dst_w; + ptr += src_w; + dst_ptr += dst_w; + } } } + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index 6168a9c..2043339 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -634,6 +634,10 @@ struct _RGBA_Draw_Context int x, y, w, h; Eina_Bool use : 1; } clip; + struct { + int x, y, w, h; + RGBA_Image *mask; + } mask; Cutout_Rects cutout; struct { struct { @@ -743,6 +747,11 @@ struct _RGBA_Image } image; struct { + DATA8 *mask; + Eina_Bool dirty: 1; + } mask; + + struct { LK(lock); Eina_List *list; unsigned long long orig_usage; diff --git a/src/lib/include/evas_inline.x b/src/lib/include/evas_inline.x index 8f74a63..653125f 100644 --- a/src/lib/include/evas_inline.x +++ b/src/lib/include/evas_inline.x @@ -57,6 +57,8 @@ static inline int evas_object_is_opaque(Evas_Object *obj) { if (obj->smart.smart) return 0; + /* If a mask: Assume alpha */ + if (obj->cur.mask) return 0; if (obj->cur.cache.clip.a == 255) { if (obj->func->is_opaque) diff --git a/src/lib/include/evas_private.h b/src/lib/include/evas_private.h index 737ab72..86909af 100644 --- a/src/lib/include/evas_private.h +++ b/src/lib/include/evas_private.h @@ -390,6 +390,7 @@ struct _Evas_Object struct { Evas_Map *map; Evas_Object *clipper; + Evas_Object *mask; Evas_Object *map_parent; double scale; Evas_Coord_Rectangle geometry; @@ -438,6 +439,13 @@ struct _Evas_Object Evas_Object *parent; } smart; + struct { + Eina_List *proxies; + void *surface; + int w,h; + Eina_Bool redraw; + } proxy; + Evas_Size_Hints *size_hints; int last_mouse_down_counter; @@ -578,6 +586,8 @@ struct _Evas_Func void (*context_clip_clip) (void *data, void *context, int x, int y, int w, int h); void (*context_clip_unset) (void *data, void *context); int (*context_clip_get) (void *data, void *context, int *x, int *y, int *w, int *h); + void (*context_mask_set) (void *data, void *context, void *mask, int x, int y, int w, int h); + void (*context_mask_unset) (void *data, void *context); void (*context_color_set) (void *data, void *context, int r, int g, int b, int a); int (*context_color_get) (void *data, void *context, int *r, int *g, int *b, int *a); void (*context_multiplier_set) (void *data, void *context, int r, int g, int b, int a); @@ -621,6 +631,7 @@ struct _Evas_Func char *(*image_format_get) (void *data, void *image); void (*image_colorspace_set) (void *data, void *image, int cspace); int (*image_colorspace_get) (void *data, void *image); + void (*image_mask_create) (void *data, void *image); void *(*image_native_set) (void *data, void *image, void *native); void *(*image_native_get) (void *data, void *image); @@ -660,7 +671,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_BiDi_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/src/modules/engines/gl_common/evas_gl_common.h b/src/modules/engines/gl_common/evas_gl_common.h index 5624e78..089adf6 100644 --- a/src/modules/engines/gl_common/evas_gl_common.h +++ b/src/modules/engines/gl_common/evas_gl_common.h @@ -97,6 +97,7 @@ #define SHAD_TEXUV 2 #define SHAD_TEXUV2 3 #define SHAD_TEXUV3 4 +#define SHAD_TEXM 5 typedef struct _Evas_GL_Program Evas_GL_Program; typedef struct _Evas_GL_Program_Source Evas_GL_Program_Source; @@ -193,6 +194,7 @@ struct _Evas_GL_Shared Evas_GL_Program img, img_nomul; Evas_GL_Program img_bgra, img_bgra_nomul; + Evas_GL_Program img_mask; Evas_GL_Program yuv, yuv_nomul; Evas_GL_Program tex, tex_nomul; } shader; @@ -210,6 +212,7 @@ struct _Evas_GL_Shared #define RTYPE_FONT 3 #define RTYPE_YUV 4 #define RTYPE_MAP 5 /* need to merge with image */ +#define RTYPE_IMASK 6 @@ -229,6 +232,7 @@ struct _Evas_GL_Context struct { GLuint cur_prog; GLuint cur_tex, cur_texu, cur_texv; + GLuint cur_texm, cur_texmu, cur_texmv; int render_op; int cx, cy, cw, ch; int smooth; @@ -249,7 +253,7 @@ struct _Evas_GL_Context struct { Evas_GL_Image *surface; GLuint cur_prog; - GLuint cur_tex, cur_texu, cur_texv; + GLuint cur_tex, cur_texu, cur_texv, cur_texm; int render_op; int cx, cy, cw, ch; int smooth; @@ -263,12 +267,14 @@ struct _Evas_GL_Context GLfloat *texuv; GLfloat *texuv2; GLfloat *texuv3; - Eina_Bool line : 1; + GLfloat *texm; + Eina_Bool line: 1; Eina_Bool use_vertex : 1; Eina_Bool use_color : 1; Eina_Bool use_texuv : 1; Eina_Bool use_texuv2 : 1; Eina_Bool use_texuv3 : 1; + Eina_Bool use_texm : 1; Evas_GL_Image *im; } array; } pipe[MAX_PIPES]; @@ -384,6 +390,8 @@ extern Evas_GL_Program_Source shader_img_bgra_frag_src; extern Evas_GL_Program_Source shader_img_bgra_vert_src; extern Evas_GL_Program_Source shader_img_bgra_nomul_frag_src; extern Evas_GL_Program_Source shader_img_bgra_nomul_vert_src; +extern Evas_GL_Program_Source shader_img_mask_frag_src; +extern Evas_GL_Program_Source shader_img_mask_vert_src; extern Evas_GL_Program_Source shader_yuv_frag_src; extern Evas_GL_Program_Source shader_yuv_vert_src; @@ -417,6 +425,16 @@ void evas_gl_common_context_image_push(Evas_GL_Context *gc, int x, int y, int w, int h, int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only); +void evas_gl_common_context_image_mask_push(Evas_GL_Context *gc, + Evas_GL_Texture *tex, + Evas_GL_Texture *texm, + double sx, double sy, double sw, double sh, + double sxm, double sym, double swm, double shm, + int x, int y, int w, int h, + int r, int g, int b, int a, + Eina_Bool smooth); + + void evas_gl_common_context_font_push(Evas_GL_Context *gc, Evas_GL_Texture *tex, double sx, double sy, double sw, double sh, diff --git a/src/modules/engines/gl_common/evas_gl_context.c b/src/modules/engines/gl_common/evas_gl_context.c index cd4d2cd..8bcb31b 100644 --- a/src/modules/engines/gl_common/evas_gl_context.c +++ b/src/modules/engines/gl_common/evas_gl_context.c @@ -464,6 +464,13 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc) glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_bgra_nomul.prog, "mvp"), 1, GL_FALSE, proj); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glUseProgram(gc->shared->shader.img_mask.prog); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_mask.prog, "mvp"), 1, + GL_FALSE, proj); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + + glUseProgram(gc->pipe[0].shader.cur_prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); @@ -695,6 +702,10 @@ evas_gl_common_context_new(void) &(shader_img_bgra_nomul_vert_src), &(shader_img_bgra_nomul_frag_src), "img_bgra_nomul")) goto error; + if (!evas_gl_common_shader_program_init(&(shared->shader.img_mask), + &(shader_img_mask_vert_src), + &(shader_img_mask_frag_src), + "img_mask")) goto error; if (!evas_gl_common_shader_program_init(&(shared->shader.tex), &(shader_tex_vert_src), &(shader_tex_frag_src), @@ -729,6 +740,16 @@ evas_gl_common_context_new(void) GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texv"), 2); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + + glUseProgram(shared->shader.img_mask.prog); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glUniform1i(glGetUniformLocation(shared->shader.img_mask.prog, "tex"), 0); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glUniform1i(glGetUniformLocation(shared->shader.img_mask.prog, "texm"), 1); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + + + glUseProgram(gc->pipe[0].shader.cur_prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); @@ -772,6 +793,7 @@ evas_gl_common_context_free(Evas_GL_Context *gc) if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex); if (gc->pipe[i].array.color) free(gc->pipe[i].array.color); if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv); + if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm); if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2); if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3); } @@ -785,6 +807,7 @@ evas_gl_common_context_free(Evas_GL_Context *gc) evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_nomul)); evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra)); evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra_nomul)); + evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_mask)); evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv)); evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv_nomul)); evas_gl_common_shader_program_shutdown(&(gc->shared->shader.tex)); @@ -843,6 +866,9 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc) gc->state.current.cur_tex = 0; gc->state.current.cur_texu = 0; gc->state.current.cur_texv = 0; + gc->state.current.cur_texm = 0; + gc->state.current.cur_texmu = 0; + gc->state.current.cur_texmv = 0; gc->state.current.render_op = 0; gc->state.current.smooth = 0; gc->state.current.blend = 0; @@ -869,6 +895,7 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc) gc->pipe[i].shader.cur_tex = 0; gc->pipe[i].shader.cur_texu = 0; gc->pipe[i].shader.cur_texv = 0; + gc->pipe[i].shader.cur_texm = 0; gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND; gc->pipe[i].shader.smooth = 0; gc->pipe[i].shader.blend = 0; @@ -921,12 +948,15 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc) GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glUseProgram(gc->pipe[0].shader.cur_prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - + + + glActiveTexture(GL_TEXTURE0); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + _evas_gl_common_viewport_set(gc); } @@ -1005,6 +1035,10 @@ evas_gl_common_context_target_surface_set(Evas_GL_Context *gc, #define PUSH_TEXUV3(n, u, v) \ gc->pipe[n].array.texuv3[nu3++] = u; \ gc->pipe[n].array.texuv3[nu3++] = v +#define PUSH_TEXM(n, u, v) \ + gc->pipe[n].array.texm[nm++] = u; \ + gc->pipe[n].array.texm[nm++] = v + static inline void array_alloc(Evas_GL_Context *gc, int n) @@ -1020,6 +1054,9 @@ array_alloc(Evas_GL_Context *gc, int n) if (gc->pipe[n].array.use_texuv) gc->pipe[n].array.texuv = realloc(gc->pipe[n].array.texuv, gc->pipe[n].array.alloc * sizeof(GLfloat) * 2); + if (gc->pipe[n].array.use_texm) + gc->pipe[n].array.texm = realloc(gc->pipe[n].array.texm, + gc->pipe[n].array.alloc * sizeof(GLfloat) * 2); if (gc->pipe[n].array.use_texuv2) gc->pipe[n].array.texuv2 = realloc(gc->pipe[n].array.texuv2, gc->pipe[n].array.alloc * sizeof(GLfloat) * 2); @@ -1165,7 +1202,7 @@ evas_gl_common_context_line_push(Evas_GL_Context *gc, } void -evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, +evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, int x, int y, int w, int h, int r, int g, int b, int a) { @@ -1173,10 +1210,23 @@ evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, Eina_Bool blend = 0; GLuint prog = gc->shared->shader.rect.prog; int pn = 0; - + + if (gc->dc->mask.mask) + { + RGBA_Draw_Context *dc; + dc = gc->dc; + Evas_GL_Image *im; + im = (void *)dc->mask.mask; + evas_gl_common_context_font_push(gc, im->tex, + x - dc->mask.x,y - dc->mask.y, + dc->mask.w,dc->mask.h, + x,y,w,h,r,g,b,a); + return; + } + if (a < 255) blend = 1; if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0; - + again: vertex_array_size_check(gc, gc->state.top_pipe, 6); pn = gc->state.top_pipe; @@ -1489,6 +1539,7 @@ again: // if nomul... dont need this gc->pipe[pn].array.use_color = 1; gc->pipe[pn].array.use_texuv = 1; + gc->pipe[pn].array.use_texuvm = 0; gc->pipe[pn].array.use_texuv2 = 0; gc->pipe[pn].array.use_texuv3 = 0; #endif @@ -1539,6 +1590,255 @@ again: } } + +void +evas_gl_common_context_image_mask_push(Evas_GL_Context *gc, + Evas_GL_Texture *tex, + Evas_GL_Texture *texm, + double sx, double sy, double sw, double sh, + double sxm, double sym, double swm,double shm, + int x, int y, int w, int h, + int r, int g, int b, int a, + Eina_Bool smooth) +{ + int pnum, nv, nc, nu, nm, nt, i; + GLfloat tx1, tx2, ty1, ty2; + GLfloat txm1, txm2, tym1, tym2; + Eina_Bool blend = 1; + GLuint prog = gc->shared->shader.img_mask.prog; + int pn = 0; + +#if 0 + if (tex->gc->shared->info.bgra) + { + prog = gc->shared->shader.img_mask.prog; + } + else + { +#warning Nash: FIXME: Need two shaders? + printf("Not good: Need other texture\n"); + prog = gc->shared->shader.img.prog; + } +#endif + +again: + vertex_array_size_check(gc, gc->state.top_pipe, 6); + pn = gc->state.top_pipe; +#ifdef GLPIPES + if ((pn == 0) && (gc->pipe[pn].array.num == 0)) + { + gc->pipe[pn].region.type = RTYPE_IMASK; + gc->pipe[pn].shader.cur_tex = tex->pt->texture; + gc->pipe[pn].shader.cur_texm = texm->pt->texture; + gc->pipe[pn].shader.cur_prog = prog; + gc->pipe[pn].shader.smooth = smooth; + gc->pipe[pn].shader.blend = blend; + gc->pipe[pn].shader.render_op = gc->dc->render_op; + gc->pipe[pn].shader.clip = 0; + gc->pipe[pn].shader.cx = 0; + gc->pipe[pn].shader.cy = 0; + gc->pipe[pn].shader.cw = 0; + gc->pipe[pn].shader.ch = 0; + gc->pipe[pn].array.line = 0; + gc->pipe[pn].array.use_vertex = 1; + // if nomul... dont need this + gc->pipe[pn].array.use_color = 1; + gc->pipe[pn].array.use_texuv = 1; + gc->pipe[pn].array.use_texuv2 = 0; + gc->pipe[pn].array.use_texuv3 = 0; + gc->pipe[pn].array.use_texm = 1; + } + else + { + int found = 0; + + for (i = pn; i >= 0; i--) + { + if ((gc->pipe[i].region.type == RTYPE_IMASK) + && (gc->pipe[i].shader.cur_tex == tex->pt->texture) + && (gc->pipe[i].shader.cur_texm == texm->pt->texture) + && (gc->pipe[i].shader.cur_prog == prog) + && (gc->pipe[i].shader.smooth == smooth) + && (gc->pipe[i].shader.blend == blend) + && (gc->pipe[i].shader.render_op == gc->dc->render_op) + && (gc->pipe[i].shader.clip == 0) + ) + { + found = 1; + pn = i; + break; + } + if (pipe_region_intersects(gc, i, x, y, w, h)) break; + } + if (!found) + { + pn = gc->state.top_pipe + 1; + if (pn >= gc->shared->info.tune.pipes.max) + { + shader_array_flush(gc); + goto again; + } + gc->state.top_pipe = pn; + gc->pipe[pn].region.type = RTYPE_IMASK; + gc->pipe[pn].shader.cur_tex = tex->pt->texture; + gc->pipe[pn].shader.cur_texm = texm->pt->texture; + gc->pipe[pn].shader.cur_prog = prog; + gc->pipe[pn].shader.smooth = smooth; + gc->pipe[pn].shader.blend = blend; + gc->pipe[pn].shader.render_op = gc->dc->render_op; + gc->pipe[pn].shader.clip = 0; + gc->pipe[pn].shader.cx = 0; + gc->pipe[pn].shader.cy = 0; + gc->pipe[pn].shader.cw = 0; + gc->pipe[pn].shader.ch = 0; + gc->pipe[pn].array.line = 0; + gc->pipe[pn].array.use_vertex = 1; + gc->pipe[pn].array.use_color = 1; + gc->pipe[pn].array.use_texuv = 1; + gc->pipe[pn].array.use_texuv2 = 0; + gc->pipe[pn].array.use_texuv3 = 0; + gc->pipe[pn].array.use_texm = 1; + + } + } + if ((tex->im) && (tex->im->native.data)) + { + if (gc->pipe[pn].array.im != tex->im) + { + shader_array_flush(gc); + pn = gc->state.top_pipe; + gc->pipe[pn].array.im = tex->im; + goto again; + } + } + if (tex->pt->dyn.img) + { + if (gc->pipe[pn].array.im != tex->im) + { + shader_array_flush(gc); + pn = gc->state.top_pipe; + gc->pipe[pn].array.im = tex->im; + goto again; + } + } +#else + if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture) + || (gc->pipe[pn].shader.cur_prog != prog) + || (gc->pipe[pn].shader.smooth != smooth) + || (gc->pipe[pn].shader.blend != blend) + || (gc->pipe[pn].shader.render_op != gc->dc->render_op) + || (gc->pipe[pn].shader.clip != 0) + ) + { + shader_array_flush(gc); + gc->pipe[pn].shader.cur_tex = tex->pt->texture; + gc->pipe[pn].shader.cur_texm = texm->pt->texture; + gc->pipe[pn].shader.cur_prog = prog; + gc->pipe[pn].shader.smooth = smooth; + gc->pipe[pn].shader.blend = blend; + gc->pipe[pn].shader.render_op = gc->dc->render_op; + gc->pipe[pn].shader.clip = 0; + gc->pipe[pn].shader.cx = 0; + gc->pipe[pn].shader.cy = 0; + gc->pipe[pn].shader.cw = 0; + gc->pipe[pn].shader.ch = 0; + } + if ((tex->im) && (tex->im->native.data)) + { + if (gc->pipe[pn].array.im != tex->im) + { + shader_array_flush(gc); + gc->pipe[pn].array.im = tex->im; + } + } + if (tex->pt->dyn.img) + { + if (gc->pipe[pn].array.im != tex->im) + { + shader_array_flush(gc); + gc->pipe[pn].array.im = tex->im; + } + } + + gc->pipe[pn].array.line = 0; + gc->pipe[pn].array.use_vertex = 1; + gc->pipe[pn].array.use_color = 1; + gc->pipe[pn].array.use_texuv = 1; + gc->pipe[pn].array.use_texuv2 = 0; + gc->pipe[pn].array.use_texuv3 = 0; + gc->pipe[pn].array.use_texm = 1; +#endif + + pipe_region_expand(gc, pn, x, y, w, h); + + pnum = gc->pipe[pn].array.num; + nv = pnum * 3; nc = pnum * 4; nm = pnum * 2; nu = pnum * 2; + nt = pnum * 4; + gc->pipe[pn].array.num += 6; + array_alloc(gc, pn); + + if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert)) + { + tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w; + ty1 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h; + tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w; + ty2 = ((double)(tex->y) + sy) / (double)tex->pt->h; + + txm1 = ((double)(texm->x) + sxm) / (double)texm->pt->w; + tym1 = ((double)(texm->y) + sym + shm) / (double)texm->pt->h; + txm2 = ((double)(texm->x) + sxm + swm) / (double)texm->pt->w; + tym2 = ((double)(texm->y) + sym) / (double)texm->pt->h; + } + else + { + printf("B:\n"); + tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w; + ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h; + tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w; + ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h; + + txm1 = (texm->x + sxm) / (double)texm->pt->w; + tym1 = (texm->y + sy) / (double)texm->pt->h; + txm2 = (texm->x + sxm + swm) / (double)texm->pt->w; + tym2 = (texm->y + sy + sh) / (double)texm->pt->h; + } + printf(" %3.6lf %3.6lf %3.6lf %3.6lf\n",sx,sy,sw,sh); + printf("m%3.6lf %3.6lf %3.6lf %3.6lf\n",sxm,sym,swm,shm); + printf(" %3f %3f %3f %3f\n",tx1,ty1,tx2,ty2); + printf("m%3f %3f %3f %3f\n",txm1,tym1,txm2,tym2); + + PUSH_VERTEX(pn, x , y , 0); + PUSH_VERTEX(pn, x + w, y , 0); + PUSH_VERTEX(pn, x , y + h, 0); + + PUSH_TEXUV(pn, tx1, ty1); + PUSH_TEXUV(pn, tx2, ty1); + PUSH_TEXUV(pn, tx1, ty2); + + PUSH_TEXM(pn, txm1, tym1); + PUSH_TEXM(pn, txm2, tym1); + PUSH_TEXM(pn, txm1, tym2); + + PUSH_VERTEX(pn, x + w, y , 0); + PUSH_VERTEX(pn, x + w, y + h, 0); + PUSH_VERTEX(pn, x , y + h, 0); + + PUSH_TEXUV(pn, tx2, ty1); + PUSH_TEXUV(pn, tx2, ty2); + PUSH_TEXUV(pn, tx1, ty2); + + PUSH_TEXM(pn, txm2, tym1); + PUSH_TEXM(pn, txm2, tym2); + PUSH_TEXM(pn, txm1, tym2); + + // if nomul... dont need this + for (i = 0; i < 6; i++) + { + PUSH_COLOR(pn, r, g, b, a); + } +} + + void evas_gl_common_context_font_push(Evas_GL_Context *gc, Evas_GL_Texture *tex, @@ -2321,11 +2621,13 @@ shader_array_flush(Evas_GL_Context *gc) GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } #endif + glActiveTexture(GL_TEXTURE0); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_tex); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } + if (gc->pipe[i].array.im) { #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) @@ -2481,7 +2783,7 @@ shader_array_flush(Evas_GL_Context *gc) { glDisableVertexAttribArray(SHAD_TEXUV); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - glDisableVertexAttribArray(SHAD_TEXUV2); + glDisableVertexAttribArray(SHAD_TEXUV2); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glDisableVertexAttribArray(SHAD_TEXUV3); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); @@ -2490,6 +2792,24 @@ shader_array_flush(Evas_GL_Context *gc) } else { + if (gc->pipe[i].array.use_texm) + { + printf("using tex m (%d)\n",gc->pipe[i].shader.cur_texm); + glEnableVertexAttribArray(SHAD_TEXM); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glVertexAttribPointer(SHAD_TEXM, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texm); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glActiveTexture(GL_TEXTURE1); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glActiveTexture(GL_TEXTURE0); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + } + else + { + glDisableVertexAttribArray(SHAD_TEXM); + } if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3)) { glEnableVertexAttribArray(SHAD_TEXUV2); @@ -2517,6 +2837,11 @@ shader_array_flush(Evas_GL_Context *gc) GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glActiveTexture(GL_TEXTURE1); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu); + glActiveTexture(GL_TEXTURE0); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } else { @@ -2568,12 +2893,14 @@ shader_array_flush(Evas_GL_Context *gc) if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex); if (gc->pipe[i].array.color) free(gc->pipe[i].array.color); if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv); + if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm); if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2); if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3); gc->pipe[i].array.vertex = NULL; gc->pipe[i].array.color = NULL; gc->pipe[i].array.texuv = NULL; + gc->pipe[i].array.texm = NULL; gc->pipe[i].array.texuv2 = NULL; gc->pipe[i].array.texuv3 = NULL; diff --git a/src/modules/engines/gl_common/evas_gl_image.c b/src/modules/engines/gl_common/evas_gl_image.c index fd24f5d..afed2a7 100644 --- a/src/modules/engines/gl_common/evas_gl_image.c +++ b/src/modules/engines/gl_common/evas_gl_image.c @@ -502,8 +502,10 @@ void evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth) { RGBA_Draw_Context *dc; + Evas_GL_Image *imm; int r, g, b, a; double ssx, ssy, ssw, ssh; + double mssx, mssy, mssw, mssh; Cutout_Rects *rects; Cutout_Rect *rct; int c, cx, cy, cw, ch; @@ -513,6 +515,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy if (sw < 1) sw = 1; if (sh < 1) sh = 1; dc = gc->dc; + imm = dc->mask.mask; if (dc->mul.use) { a = (dc->mul.col >> 24) & 0xff; @@ -531,26 +534,33 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy evas_gl_common_rect_draw(gc, dx, dy, dw, dh); return; } + if (imm) + { + _evas_gl_common_image_update(gc, imm); + if (!imm->tex) imm = NULL; /* Turn of mask on error */ + } if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) yuv = 1; - + im->tex->im = im; - if ((!gc->dc->cutout.rects) || + if (imm) imm->tex->im = imm; + if ((!gc->dc->cutout.rects) || ((gc->shared->info.tune.cutout.max > 0) && (gc->dc->cutout.active > gc->shared->info.tune.cutout.max))) { if (gc->dc->clip.use) { int nx, ny, nw, nh; - + double scalex,scaley; + nx = dx; ny = dy; nw = dw; nh = dh; - RECTS_CLIP_TO_RECT(nx, ny, nw, nh, + RECTS_CLIP_TO_RECT(nx, ny, nw, nh, gc->dc->clip.x, gc->dc->clip.y, gc->dc->clip.w, gc->dc->clip.h); if ((nw < 1) || (nh < 1)) return; - if ((nx == dx) && (ny == dy) && (nw == dw) && (nh == dh)) + if ((!imm) && (nx == dx) && (ny == dy) && (nw == dw) && (nh == dh)) { if (yuv) evas_gl_common_context_yuv_push(gc, @@ -568,12 +578,33 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy smooth, im->tex_only); return; } - + ssx = (double)sx + ((double)(sw * (nx - dx)) / (double)(dw)); ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh)); ssw = ((double)sw * (double)(nw)) / (double)(dw); ssh = ((double)sh * (double)(nh)) / (double)(dh); - if (yuv) + if (imm) + { + /* Correct ones here */ + scalex = imm->w / (double)dc->mask.w; + scaley = imm->h / (double)dc->mask.h; + mssx = scalex * (nx - dc->mask.x); + mssy = scaley * (ny - dc->mask.y); + mssw = scalex * nw; + mssh = scaley * nh; + + /* No yuv + imm I'm afraid */ + evas_gl_common_context_image_mask_push(gc, + im->tex, + imm->tex, + ssx, ssy, ssw, ssh, + mssx, mssy, mssw, mssh, + //dc->mask.x, dc->mask.y, dc->mask.w, dc->mask.h, + nx, ny, nw, nh, + r, g, b, a, + smooth); + } + else if (yuv) evas_gl_common_context_yuv_push(gc, im->tex, ssx, ssy, ssw, ssh, @@ -668,3 +699,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy /* restore clip info */ gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch; } + + + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/src/modules/engines/gl_common/evas_gl_shader.c b/src/modules/engines/gl_common/evas_gl_shader.c index 221fca8..ac6c22d 100644 --- a/src/modules/engines/gl_common/evas_gl_shader.c +++ b/src/modules/engines/gl_common/evas_gl_shader.c @@ -360,6 +360,48 @@ Evas_GL_Program_Source shader_img_bgra_vert_src = #endif }; + +///////////////////////////////////////////// +#if defined (GLES_VARIETY_S3C6410) +const unsigned int img_mask_frag_bin[] = +{ +# include "shader/img_mask_frag_bin_s3c6410.h" +}; +#endif + +const char img_mask_frag_glsl[] = +#include "shader/img_mask_frag.h" + ; +Evas_GL_Program_Source shader_img_mask_frag_src = +{ + img_mask_frag_glsl, +#if defined (GLES_VARIETY_S3C6410) + img_mask_frag_bin, sizeof(img_mask_frag_bin) +#else + NULL, 0 +#endif +}; + +#if defined (GLES_VARIETY_S3C6410) +const unsigned int img_mask_vert_bin[] = +{ +# include "shader/img_mask_vert_bin_s3c6410.h" +}; +#endif +const char img_mask_vert_glsl[] = +#include "shader/img_mask_vert.h" + ; +Evas_GL_Program_Source shader_img_mask_vert_src = +{ + img_mask_vert_glsl, +#if defined (GLES_VARIETY_S3C6410) + img_mask_vert_bin, sizeof(img_mask_vert_bin) +#else + NULL, 0 +#endif +}; + + ///////////////////////////////////////////// #if defined (GLES_VARIETY_S3C6410) const unsigned int img_bgra_nomul_frag_bin[] = @@ -495,6 +537,8 @@ evas_gl_common_shader_program_init(Evas_GL_Program *p, GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glBindAttribLocation(p->prog, SHAD_TEXUV3, "tex_coord3"); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glBindAttribLocation(p->prog, SHAD_TEXM, "tex_coordm"); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glLinkProgram(p->prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); diff --git a/src/modules/engines/gl_common/shader/img_mask_frag.h b/src/modules/engines/gl_common/shader/img_mask_frag.h new file mode 100644 index 0000000..0571c72 --- /dev/null +++ b/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/src/modules/engines/gl_common/shader/img_mask_frag.shd b/src/modules/engines/gl_common/shader/img_mask_frag.shd new file mode 100644 index 0000000..87aa2b7 --- /dev/null +++ b/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/src/modules/engines/gl_common/shader/img_mask_vert.h b/src/modules/engines/gl_common/shader/img_mask_vert.h new file mode 100644 index 0000000..5b52e41 --- /dev/null +++ b/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/src/modules/engines/gl_common/shader/img_mask_vert.shd b/src/modules/engines/gl_common/shader/img_mask_vert.shd new file mode 100644 index 0000000..f91b545 --- /dev/null +++ b/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/src/modules/engines/gl_x11/evas_engine.c b/src/modules/engines/gl_x11/evas_engine.c index 990c7a9..aa833ec 100644 --- a/src/modules/engines/gl_x11/evas_engine.c +++ b/src/modules/engines/gl_x11/evas_engine.c @@ -839,6 +839,20 @@ eng_image_colorspace_get(void *data __UNUSED__, void *image) return im->cs.space; } +static void +eng_image_mask_create(void *data __UNUSED__, void *image) +{ + Evas_GL_Image *im; + + if (!image) return; + im = image; + if (!im->im->image.data) + evas_cache_image_load_data(&im->im->cache_entry); + if (!im->tex) + im->tex = evas_gl_common_texture_new(im->gc, im->im); +} + + static void * eng_image_alpha_set(void *data, void *image, int has_alpha) { @@ -1669,7 +1683,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; @@ -1864,6 +1878,7 @@ module_open(Evas_Module *em) ORD(image_format_get); ORD(image_colorspace_set); ORD(image_colorspace_get); + ORD(image_mask_create); ORD(image_native_set); ORD(image_native_get); @@ -1873,7 +1888,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/src/modules/engines/software_generic/evas_engine.c b/src/modules/engines/software_generic/evas_engine.c index 9249943..f2bd395 100644 --- a/src/modules/engines/software_generic/evas_engine.c +++ b/src/modules/engines/software_generic/evas_engine.c @@ -97,6 +97,24 @@ eng_context_multiplier_get(void *data __UNUSED__, void *context, int *r, int *g, } static void +eng_context_mask_set(void *data __UNUSED__, void *context, void *mask, int x, int y, int w, int h) +{ + evas_common_draw_context_set_mask(context, mask, x, y, w, h); +} + +static void +eng_context_mask_unset(void *data __UNUSED__, void *context) +{ + evas_common_draw_context_unset_mask(context); +} + +static void * +eng_context_mask_get(void *data __UNUSED__, void *context) +{ + return ((RGBA_Draw_Context *)context)->mask.mask; +} + +static void eng_context_cutout_add(void *data __UNUSED__, void *context, int x, int y, int w, int h) { evas_common_draw_context_add_cutout(context, x, y, w, h); @@ -239,6 +257,31 @@ eng_image_colorspace_get(void *data __UNUSED__, void *image) return im->space; } +static void +eng_image_mask_create(void *data __UNUSED__, void *image) +{ + RGBA_Image *im; + int sz; + uint8_t *dst,*end; + uint32_t *src; + + if (!image) return; + im = image; + if (im->mask.mask && !im->mask.dirty) return; + + if (im->mask.mask) free(im->mask.mask); + sz = im->cache_entry.w * im->cache_entry.h; + im->mask.mask = malloc(sz); + dst = im->mask.mask; + if (!im->image.data) + evas_cache_image_load_data(&im->cache_entry); + src = im->image.data; + for (end = dst + sz ; dst < end ; dst ++, src ++) + *dst = *src >> 24; + im->mask.dirty = 0; +} + + static void * eng_image_alpha_set(void *data __UNUSED__, void *image, int has_alpha) { @@ -428,7 +471,6 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) if (!im->cs.no_free) free(im->cs.data); } im->cs.data = image_data; - evas_common_image_colorspace_dirty(im); } break; default: @@ -470,11 +512,11 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image, #endif ) { - evas_common_rgba_image_scalecache_prepare((Image_Entry *)(im), + evas_common_rgba_image_scalecache_prepare((Image_Entry *)(im), surface, context, smooth, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); - + evas_common_pipe_image_draw(im, surface, context, smooth, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); @@ -491,7 +533,7 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image, evas_common_rgba_image_scalecache_do(&im->cache_entry, surface, context, smooth, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); -/* +/* if (smooth) evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context, src_x, src_y, src_w, src_h, @@ -506,12 +548,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 +594,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 * @@ -808,6 +858,8 @@ static Evas_Func func = eng_context_clip_clip, eng_context_clip_unset, eng_context_clip_get, + eng_context_mask_set, + eng_context_mask_unset, eng_context_color_set, eng_context_color_get, eng_context_multiplier_set, @@ -851,6 +903,7 @@ static Evas_Func func = eng_image_format_get, eng_image_colorspace_set, eng_image_colorspace_get, + eng_image_mask_create, eng_image_native_set, eng_image_native_get, /* image cache funcs */ @@ -886,7 +939,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