merged evas image masking code from brett
authorChunEon Park <chuneon.park@samsung.com>
Tue, 14 Dec 2010 06:24:18 +0000 (15:24 +0900)
committerChunEon Park <chuneon.park@samsung.com>
Tue, 14 Dec 2010 06:24:18 +0000 (15:24 +0900)
29 files changed:
src/lib/Evas.h
src/lib/canvas/evas_clip.c
src/lib/canvas/evas_map.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_main.c
src/lib/canvas/evas_render.c
src/lib/engines/common/evas_blit_main.c
src/lib/engines/common/evas_convert_colorspace.c
src/lib/engines/common/evas_draw.h
src/lib/engines/common/evas_draw_main.c
src/lib/engines/common/evas_map_image.c
src/lib/engines/common/evas_map_image.h
src/lib/engines/common/evas_pipe.h
src/lib/engines/common/evas_rectangle_main.c
src/lib/engines/common/evas_scale_sample.c
src/lib/engines/common/evas_scale_smooth_scaler_noscale.c
src/lib/include/evas_common.h
src/lib/include/evas_inline.x
src/lib/include/evas_private.h
src/modules/engines/gl_common/evas_gl_common.h
src/modules/engines/gl_common/evas_gl_context.c
src/modules/engines/gl_common/evas_gl_image.c
src/modules/engines/gl_common/evas_gl_shader.c
src/modules/engines/gl_common/shader/img_mask_frag.h [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_frag.shd [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_vert.h [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_vert.shd [new file with mode: 0644]
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/software_generic/evas_engine.c

index 36a5739..1ff699d 100644 (file)
@@ -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
  *
index 88defd6..55f7dad 100644 (file)
@@ -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);
+}
+
+
+
 /**
  * @}
  */
index a623912..7051ee4 100644 (file)
@@ -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;
index b5dcfd5..b6a67d5 100644 (file)
@@ -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 :*/
index fe26a76..a6a70e1 100644 (file)
@@ -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);
index 453a4fc..27599a9 100644 (file)
@@ -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 :*/
index 9322ffe..3f0bfee 100644 (file)
@@ -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);
 
index 75711bb..2886133 100644 (file)
@@ -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 :*/
index 1c907d8..eb628c7 100644 (file)
@@ -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);
index 8b8511a..e2d4568 100644 (file)
@@ -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;
index 40f4843..288f6a9 100644 (file)
@@ -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);
index 883b278..a7cb8cf 100644 (file)
@@ -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 */
index e658e1f..de033f0 100644 (file)
@@ -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);
index 28aaf16..222c6b7 100644 (file)
@@ -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 :*/
index c6fa9f2..b544c05 100644 (file)
@@ -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
index 957b6a3..fa3161f 100644 (file)
@@ -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 :*/
index 6168a9c..2043339 100644 (file)
@@ -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;
index 8f74a63..653125f 100644 (file)
@@ -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)
index 737ab72..86909af 100644 (file)
@@ -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);
 
index 5624e78..089adf6 100644 (file)
@@ -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,
index cd4d2cd..8bcb31b 100644 (file)
@@ -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;
 
index fd24f5d..afed2a7 100644 (file)
@@ -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 :*/
index 221fca8..ac6c22d 100644 (file)
@@ -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 (file)
index 0000000..0571c72
--- /dev/null
@@ -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 (file)
index 0000000..87aa2b7
--- /dev/null
@@ -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 (file)
index 0000000..5b52e41
--- /dev/null
@@ -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 (file)
index 0000000..f91b545
--- /dev/null
@@ -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;
+}
index 990c7a9..aa833ec 100644 (file)
@@ -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);
    
index 9249943..f2bd395 100644 (file)
@@ -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