From 89d19f48a65082120fbe0e26b21a6cacdc47e161 Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Fri, 11 Oct 2013 16:43:50 -0300 Subject: [PATCH] evas/image: Add video surface caps. 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 | 32 ++++++++++++++++++++ src/lib/canvas/evas_object_image.c | 34 +++++++++++++++++++++ src/lib/canvas/evas_render.c | 62 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/src/lib/Evas.h b/src/lib/Evas.h index 7772d5b..5a1f631 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -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. diff --git a/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index 64b2daf..c27b381 100644 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -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; } diff --git a/src/lib/canvas/evas_render.c b/src/lib/canvas/evas_render.c index 1036285..d729f40 100644 --- a/src/lib/canvas/evas_render.c +++ b/src/lib/canvas/evas_render.c @@ -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, -- 2.7.4