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.
This commit is contained in:
Rafael Antognolli 2013-09-26 13:49:18 -03:00
parent d1c6266c45
commit 9506fd5db7
5 changed files with 158 additions and 2 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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.
*

View File

@ -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."),

View File

@ -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;