diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h index 0c2d9b3655..007c0acf8f 100644 --- a/src/lib/evas/Evas_Common.h +++ b/src/lib/evas/Evas_Common.h @@ -486,6 +486,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 */ diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h index 232483107b..63783c5b66 100644 --- a/src/lib/evas/Evas_Eo.h +++ b/src/lib/evas/Evas_Eo.h @@ -5592,6 +5592,8 @@ enum EVAS_OBJ_IMAGE_SUB_ID_COLORSPACE_GET, EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_SET, EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_GET, + EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_SET, + EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_GET, EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_SET, EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_GET, EVAS_OBJ_IMAGE_SUB_ID_SCALE_HINT_SET, @@ -6379,6 +6381,30 @@ enum */ #define evas_obj_image_video_surface_get(surf) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_GET), EO_TYPECHECK(const Evas_Video_Surface **, surf) +/** + * @def evas_obj_image_video_surface_caps_set + * @since 1.8 + * + * Set the video surface capabilities to a given image of the canvas + * + * @param[in] caps in + * + * @see evas_object_image_video_surface_caps_set + */ +#define evas_obj_image_video_surface_caps_set(caps) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_SET), EO_TYPECHECK(unsigned int, caps) + +/** + * @def evas_obj_image_video_surface_caps_get + * @since 1.8 + * + * Get the video surface capabilities to a given image of the canvas + * + * @param[out] caps out + * + * @see evas_object_image_video_surface_caps_get + */ +#define evas_obj_image_video_surface_caps_get(caps) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_GET), EO_TYPECHECK(unsigned int *, caps) + /** * @def evas_obj_image_native_surface_set * @since 1.8 diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index 5294ce7909..ffb3bb821e 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -4738,6 +4738,9 @@ EAPI void evas_object_image_video_surface_set(Evas_Obje */ EAPI const Evas_Video_Surface *evas_object_image_video_surface_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); +EAPI void evas_object_image_video_surface_caps_set(Evas_Object *obj, unsigned int caps) EINA_ARG_NONNULL(1); +EAPI unsigned int evas_object_image_video_surface_caps_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + /** * Set the scale hint of a given image of the canvas. * diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index af76f53fc2..00c1cf6fa6 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -64,6 +64,7 @@ struct _Evas_Object_Image_Pixels } func; Evas_Video_Surface video; + unsigned int video_caps; }; struct _Evas_Object_Image_State @@ -216,7 +217,7 @@ static const Evas_Object_Image_Load_Opts default_load_opts = { }; static const Evas_Object_Image_Pixels default_pixels = { - NULL, { NULL, NULL }, { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + NULL, { NULL, NULL }, { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, ~0x0 }; static const Evas_Object_Image_State default_state = { @@ -2578,6 +2579,52 @@ _image_video_surface_get(Eo *eo_obj EINA_UNUSED, void *_pd, va_list *list) *surf = (!o->video_surface ? NULL : &o->pixels->video); } +EAPI void +evas_object_image_video_surface_caps_set(Evas_Object *eo_obj, unsigned int caps) +{ + MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + eo_do(eo_obj, evas_obj_image_video_surface_caps_set(caps)); +} + +static void +_image_video_surface_caps_set(Eo *eo_obj, void *_pd, va_list *list) +{ + unsigned int caps = va_arg(*list, unsigned int); + Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS); + Evas_Object_Image *o = _pd; + + _evas_object_image_cleanup(eo_obj, obj, o); + + if (caps == o->pixels->video_caps) + return; + + EINA_COW_PIXEL_WRITE_BEGIN(o, pixi_write) + pixi_write->video_caps = caps; + EINA_COW_PIXEL_WRITE_END(o, pixi_write) +} + +EAPI unsigned int +evas_object_image_video_surface_caps_get(const Evas_Object *eo_obj) +{ + MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ); + return 0; + MAGIC_CHECK_END(); + unsigned int caps = ~0x0; + eo_do((Eo *)eo_obj, evas_obj_image_video_surface_caps_get(&caps)); + return caps; +} + +static void +_image_video_surface_caps_get(Eo *eo_obj EINA_UNUSED, void *_pd, va_list *list) +{ + unsigned int *caps = va_arg(*list, unsigned int *); + const Evas_Object_Image *o = _pd; + + *caps = (!o->video_surface ? 0 : o->pixels->video_caps); +} + EAPI void evas_object_image_native_surface_set(Evas_Object *eo_obj, Evas_Native_Surface *surf) { @@ -5359,6 +5406,8 @@ _class_constructor(Eo_Class *klass) EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_COLORSPACE_GET), _image_colorspace_get), EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_SET), _image_video_surface_set), EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_GET), _image_video_surface_get), + EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_SET), _image_video_surface_caps_set), + EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_GET), _image_video_surface_caps_get), EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_SET), _image_native_surface_set), EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_GET), _image_native_surface_get), EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_SCALE_HINT_SET), _image_scale_hint_set), @@ -5437,6 +5486,8 @@ static const Eo_Op_Description op_desc[] = { EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_COLORSPACE_GET, "Get the colorspace of a given image of the canvas."), EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_SET, "Set the video surface linked to a given image of the canvas."), EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_GET, "Get the video surface linekd to a given image of the canvas."), + EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_SET, "Set the surface capabilities (clip, resize, scale) of the video surface associated with this image."), + EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_VIDEO_SURFACE_CAPS_GET, "Get the surface capabilities (clip, resize, scale) of the video surface associated with this image."), EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_SET, "Set the native surface of a given image of the canvas."), EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_NATIVE_SURFACE_GET, "Get the native surface of a given image of the canvas."), EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_SCALE_HINT_SET, "Set the scale hint of a given image of the canvas."), diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 49fbefefe8..e1b824fa37 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -810,6 +810,10 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) Eina_Bool nooverlay; Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS); Evas_Object_Protected_Data *tmp = NULL; + Evas_Coord imgw, imgh; + unsigned int caps; + Eina_Bool surface_below, stacking_check, object_above = EINA_FALSE; + Eina_Bool ignore_window; video_parent = _evas_object_image_video_parent_get(eo_obj); @@ -832,6 +836,62 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) (obj->cur->cache.clip.a != 255)) return EINA_FALSE; + caps = evas_object_image_video_surface_caps_get(eo_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(eo_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(eo_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, @@ -878,6 +938,12 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) { Eina_Bool included = EINA_FALSE; + if (!surface_below) + { + object_above = EINA_TRUE; + break; + } + if (evas_object_is_opaque(eo_current, current) || ((current->func->has_opaque_rect) && (current->func->has_opaque_rect(eo_current, current, current->private_data)))) @@ -990,7 +1056,7 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) EINA_LIST_FREE(opaques, r) eina_rectangle_free(r); - if (nooverlay) + if (nooverlay || object_above) return EINA_FALSE; return EINA_TRUE;