evas/image: Add video surface caps. 84/10784/1 accepted/tizen/20131018.135929 accepted/tizen/20131112.015524 submit/tizen/20131017.152452
authorRafael Antognolli <rafael.antognolli@intel.com>
Fri, 11 Oct 2013 19:43:50 +0000 (16:43 -0300)
committerRafael Antognolli <rafael.antognolli@intel.com>
Fri, 11 Oct 2013 19:53:35 +0000 (16:53 -0300)
Wayland subsurfaces can be used as video surfaces too, similarly to
Ecore_X windows. However, they support a different set of features. Some
of them, like subsurface clipping and scaling, might be added in the
future, but so far we must work with what we have.

This commit allows to set an enum bitfield to the Video_Surface, with
the default value being one that will keep the same behavior as before,
for Ecore_X window. Thus, backward compatibility should not be broken.

It's possible to inform Evas that the surface in question is not able to
resize or scale, or that it's above or below the original canvas
surface. This allows Evas to show the surface itself, or use a buffer of
pixels instead, when the capabilities are not available.

Change-Id: I35764b72c31792e8af8c8d83a3f4694a1ae5fa87

src/lib/Evas.h
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_render.c

index 7772d5b..5a1f631 100644 (file)
@@ -810,6 +810,16 @@ struct _Evas_Video_Surface
    void               *data;
 };
 
+typedef enum _Evas_Video_Surface_Caps
+{
+   EVAS_VIDEO_SURFACE_MOVE = 1,
+   EVAS_VIDEO_SURFACE_RESIZE = 2,
+   EVAS_VIDEO_SURFACE_CLIP = 4,
+   EVAS_VIDEO_SURFACE_BELOW = 8,
+   EVAS_VIDEO_SURFACE_STACKING_CHECK = 16,
+   EVAS_VIDEO_SURFACE_IGNORE_WINDOW = 32,
+} Evas_Video_Surface_Caps;
+
 #define EVAS_LAYER_MIN                   -32768 /**< bottom-most layer number */
 #define EVAS_LAYER_MAX                   32767 /**< top-most layer number */
 
@@ -7348,6 +7358,28 @@ EAPI void                          evas_object_image_native_surface_set(Evas_Obj
 EAPI Evas_Native_Surface          *evas_object_image_native_surface_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
 
 /**
+ * @def evas_obj_image_video_surface_caps_set
+ *
+ * Set the video surface capabilities to a given image of the canvas
+ *
+ * @param[in] caps in
+ *
+ * @see evas_object_image_video_surface_caps_set
+ */
+EAPI void                          evas_object_image_video_surface_caps_set(Evas_Object *obj, unsigned int caps) EINA_ARG_NONNULL(1);
+
+/**
+ * @def evas_obj_image_video_surface_caps_get
+ *
+ * Get the video surface capabilities to a given image of the canvas
+ *
+ * @param[out] caps out
+ *
+ * @see evas_object_image_video_surface_caps_get
+ */
+EAPI unsigned int                  evas_object_image_video_surface_caps_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+
+/**
  * Set the video surface linked to a given image of the canvas
  *
  * @param obj The given canvas pointer.
index 64b2daf..c27b381 100644 (file)
@@ -73,6 +73,7 @@ struct _Evas_Object_Image
    } func;
 
    Evas_Video_Surface video;
+   unsigned int video_caps;
 
    const char             *tmpf;
    int                     tmpf_fd;
@@ -1816,6 +1817,38 @@ evas_object_image_video_surface_get(const Evas_Object *obj)
 }
 
 EAPI void
+evas_object_image_video_surface_caps_set(Evas_Object *obj, unsigned int caps)
+{
+   Evas_Object_Image *o;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+
+   o = (Evas_Object_Image *)(obj->object_data);
+
+   _evas_object_image_cleanup(obj, o);
+
+   if (caps == o->video_caps)
+      return;
+
+   o->video_caps = caps;
+}
+
+EAPI unsigned int
+evas_object_image_video_surface_caps_get(const Evas_Object *obj)
+{
+   Evas_Object_Image *o;
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return 0;
+   MAGIC_CHECK_END();
+
+   o = (Evas_Object_Image *)(obj->object_data);
+
+   return (!o->video_surface ? 0 : o->video_caps);
+}
+
+EAPI void
 evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf)
 {
    Evas_Object_Image *o;
@@ -2746,6 +2779,7 @@ evas_object_image_new(void)
    o->cur.source = NULL;
    o->prev = o->cur;
    o->tmpf_fd = -1;
+   o->video_caps = ~0x0;
    return o;
 }
 
index 1036285..d729f40 100644 (file)
@@ -638,6 +638,11 @@ _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
    Evas_Coord xc1, yc1, xc2, yc2;
    unsigned int i;
    Eina_Bool nooverlay;
+   Evas_Coord imgw, imgh;
+   unsigned int caps;
+   Eina_Bool surface_below, stacking_check;
+   Eina_Bool ignore_window;
+
 
    video_parent = _evas_object_image_video_parent_get(obj);
 
@@ -657,6 +662,63 @@ _evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
        (obj->cur.cache.clip.a != 255))
      return EINA_FALSE;
 
+   caps = evas_object_image_video_surface_caps_get(obj);
+
+   /* check if surface is above the canvas */
+   surface_below = !!(caps & EVAS_VIDEO_SURFACE_BELOW);
+   if (!surface_below)
+     {
+        /* above canvas, must support resize and clipping */
+
+        /* check if video surface supports resize */
+        evas_object_image_size_get(obj, &imgw, &imgh);
+        if ((obj->cur.geometry.w != imgw) ||
+            (obj->cur.geometry.h != imgh))
+          {
+             if (!(caps & EVAS_VIDEO_SURFACE_RESIZE))
+                return EINA_FALSE;
+          }
+        /* check if video surface supports clipping */
+        evas_object_image_size_get(obj, &imgw, &imgh);
+        if ((obj->cur.cache.clip.x != obj->cur.geometry.x) ||
+            (obj->cur.cache.clip.y != obj->cur.geometry.y) ||
+            (obj->cur.cache.clip.w != obj->cur.geometry.w) ||
+            (obj->cur.cache.clip.h != obj->cur.geometry.h))
+          {
+             if (!(caps & EVAS_VIDEO_SURFACE_CLIP))
+                return EINA_FALSE;
+          }
+     }
+
+   /* check for window/surface/canvas limits */
+   ignore_window = !!(caps & EVAS_VIDEO_SURFACE_IGNORE_WINDOW);
+   if (!ignore_window)
+     {
+        Evas_Coord x1, x2, y1, y2;
+        Evas_Coord fx, fy, fw, fh;
+
+        fx = e->framespace.x;
+        fy = e->framespace.y;
+        fw = e->framespace.w;
+        fh = e->framespace.h;
+
+        x1 = obj->cur.geometry.x + fx;
+        y1 = obj->cur.geometry.y + fy;
+        x2 = obj->cur.geometry.x + obj->cur.geometry.w + fx;
+        y2 = obj->cur.geometry.y + obj->cur.geometry.h + fy;
+
+        if ((x1 < fx) || (y1 < fy) ||
+            (x2 > e->output.w - (fw - fx)) ||
+            (y2 > e->output.h - (fh - fy)))
+          return EINA_FALSE;
+     }
+
+   /* check if there are other objects above the video object? */
+   stacking_check = !!(caps & EVAS_VIDEO_SURFACE_STACKING_CHECK);
+   if (!stacking_check)
+     return EINA_TRUE;
+
+
    /* Check presence of transparent object on top of the video object */
    EINA_RECTANGLE_SET(&zone,
                       obj->cur.cache.clip.x,