Efl.Canvas.Image: Implement support for map/unmap

Now the real hard work is to actually implement support inside
the engines: SW and GL generic.
This commit is contained in:
Jean-Philippe Andre 2016-03-22 11:13:55 +09:00
parent 91e0bdb1e7
commit 326ff9ae82
4 changed files with 178 additions and 57 deletions

View File

@ -1,6 +1,42 @@
#include "evas_image_private.h"
#include "efl_canvas_image.eo.h"
static void _image_preload_internal(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool cancel);
#define MY_CLASS EFL_CANVAS_IMAGE_CLASS
// see also: ector_software_buffer
typedef struct {
EINA_INLIST;
unsigned char *ptr;
unsigned int size; // in bytes
} Map_Data;
typedef struct {
Map_Data *maps;
} Map_Data_Cow;
typedef struct {
const Map_Data_Cow *map_data;
} Efl_Canvas_Image_Data;
static Eina_Cow *_map_data_cow = NULL;
static const Map_Data_Cow _map_data_cow_default = { NULL };
EOLIAN static void
_efl_canvas_image_class_constructor(Eo_Class *eo_class EINA_UNUSED)
{
if (!_map_data_cow)
{
_map_data_cow = eina_cow_add("image_map_data", sizeof(Map_Data_Cow),
1, &_map_data_cow_default, EINA_FALSE);
}
}
EOLIAN static void
_efl_canvas_image_class_destructor(Eo_Class *eo_class EINA_UNUSED)
{
eina_cow_del(_map_data_cow);
_map_data_cow = NULL;
}
Eina_Bool
_evas_image_mmap_set(Eo *eo_obj, const Eina_File *f, const char *key)
@ -26,7 +62,7 @@ _evas_image_mmap_set(Eo *eo_obj, const Eina_File *f, const char *key)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_file_mmap_set(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_file_mmap_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED,
const Eina_File *f, const char *key)
{
return _evas_image_mmap_set(eo_obj, f, key);
@ -44,7 +80,7 @@ _evas_image_mmap_get(const Eo *eo_obj, const Eina_File **f, const char **key)
}
EOLIAN static void
_efl_canvas_image_efl_file_mmap_get(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_file_mmap_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED,
const Eina_File **f, const char **key)
{
_evas_image_mmap_get(eo_obj, f, key);
@ -75,7 +111,7 @@ _evas_image_file_set(Eo *eo_obj, const char *file, const char *key)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_file_file_set(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_file_file_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED,
const char *file, const char *key)
{
return _evas_image_file_set(eo_obj, file, key);
@ -97,7 +133,7 @@ _evas_image_file_get(const Eo *eo_obj, const char **file, const char **key)
}
EOLIAN static void
_efl_canvas_image_efl_file_file_get(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_file_file_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED,
const char **file, const char **key)
{
_evas_image_file_get(eo_obj, file, key);
@ -112,11 +148,41 @@ _evas_image_load_error_get(const Eo *eo_obj)
}
EOLIAN static Efl_Image_Load_Error
_efl_canvas_image_efl_image_load_load_error_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_error_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_load_error_get(eo_obj);
}
static void
_image_preload_internal(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool cancel)
{
if (!o->engine_data)
{
o->preloading = EINA_TRUE;
evas_object_inform_call_image_preloaded(eo_obj);
return;
}
// FIXME: if already busy preloading, then dont request again until
// preload done
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if (cancel)
{
if (o->preloading)
{
o->preloading = EINA_FALSE;
ENFN->image_data_preload_cancel(ENDT, o->engine_data, eo_obj);
}
}
else
{
if (!o->preloading)
{
o->preloading = EINA_TRUE;
ENFN->image_data_preload_request(ENDT, o->engine_data, eo_obj);
}
}
}
void
_evas_image_load_async_start(Eo *eo_obj)
{
@ -128,7 +194,7 @@ _evas_image_load_async_start(Eo *eo_obj)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_async_start(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_async_start(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
_evas_image_load_async_start(eo_obj);
}
@ -144,7 +210,7 @@ _evas_image_load_async_cancel(Eo *eo_obj)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_async_cancel(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_async_cancel(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
_evas_image_load_async_cancel(eo_obj);
}
@ -172,7 +238,7 @@ _evas_image_load_dpi_set(Eo *eo_obj, double dpi)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_dpi_set(Eo *eo_obj, void *_pd EINA_UNUSED, double dpi)
_efl_canvas_image_efl_image_load_load_dpi_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, double dpi)
{
_evas_image_load_dpi_set(eo_obj, dpi);
}
@ -186,7 +252,7 @@ _evas_image_load_dpi_get(const Eo *eo_obj)
}
EOLIAN static double
_efl_canvas_image_efl_image_load_load_dpi_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_dpi_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_load_dpi_get(eo_obj);
}
@ -218,7 +284,7 @@ _evas_image_load_size_set(Eo *eo_obj, int w, int h)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_size_set(Eo *eo_obj, void *_pd EINA_UNUSED, int w, int h)
_efl_canvas_image_efl_image_load_load_size_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int w, int h)
{
_evas_image_load_size_set(eo_obj, w, h);
}
@ -233,7 +299,7 @@ _evas_image_load_size_get(const Eo *eo_obj, int *w, int *h)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_size_get(Eo *eo_obj, void *_pd EINA_UNUSED, int *w, int *h)
_efl_canvas_image_efl_image_load_load_size_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int *w, int *h)
{
_evas_image_load_size_get(eo_obj, w, h);
}
@ -261,7 +327,7 @@ _evas_image_load_scale_down_set(Eo *eo_obj, int scale_down)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_scale_down_set(Eo *eo_obj, void *_pd EINA_UNUSED, int scale_down)
_efl_canvas_image_efl_image_load_load_scale_down_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int scale_down)
{
_evas_image_load_scale_down_set(eo_obj, scale_down);
}
@ -275,7 +341,7 @@ _evas_image_load_scale_down_get(const Eo *eo_obj)
}
EOLIAN static int
_efl_canvas_image_efl_image_load_load_scale_down_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_scale_down_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_load_scale_down_get(eo_obj);
}
@ -309,7 +375,7 @@ _evas_image_load_region_set(Eo *eo_obj, int x, int y, int w, int h)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_region_set(Eo *eo_obj, void *_pd EINA_UNUSED, int x, int y, int w, int h)
_efl_canvas_image_efl_image_load_load_region_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int x, int y, int w, int h)
{
_evas_image_load_region_set(eo_obj, x, y, w, h);
}
@ -326,7 +392,7 @@ _evas_image_load_region_get(const Eo *eo_obj, int *x, int *y, int *w, int *h)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_region_get(Eo *eo_obj, void *_pd EINA_UNUSED, int *x, int *y, int *w, int *h)
_efl_canvas_image_efl_image_load_load_region_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int *x, int *y, int *w, int *h)
{
_evas_image_load_region_get(eo_obj, x, y, w, h);
}
@ -346,7 +412,7 @@ _evas_image_load_orientation_set(Eo *eo_obj, Eina_Bool enable)
}
EOLIAN static void
_efl_canvas_image_efl_image_load_load_orientation_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enable)
_efl_canvas_image_efl_image_load_load_orientation_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, Eina_Bool enable)
{
_evas_image_load_orientation_set(eo_obj, enable);
}
@ -360,7 +426,7 @@ _evas_image_load_orientation_get(const Eo *eo_obj)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_image_load_load_orientation_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_orientation_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_load_orientation_get(eo_obj);
}
@ -375,7 +441,7 @@ _evas_image_load_region_support_get(const Eo *eo_obj)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_image_load_load_region_support_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_load_load_region_support_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_load_region_support_get(eo_obj);
}
@ -394,7 +460,7 @@ _evas_image_animated_get(const Eo *eo_obj)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_image_animated_animated_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_animated_animated_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_animated_get(eo_obj);
}
@ -414,7 +480,7 @@ _evas_image_animated_frame_count_get(const Eo *eo_obj)
}
EOLIAN static int
_efl_canvas_image_efl_image_animated_animated_frame_count_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_animated_animated_frame_count_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_animated_frame_count_get(eo_obj);
}
@ -433,7 +499,7 @@ _evas_image_animated_loop_type_get(const Eo *eo_obj)
}
EOLIAN static Efl_Image_Animated_Loop_Hint
_efl_canvas_image_efl_image_animated_animated_loop_type_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_animated_animated_loop_type_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_animated_loop_type_get(eo_obj);
}
@ -452,7 +518,7 @@ _evas_image_animated_loop_count_get(const Eo *eo_obj)
}
EOLIAN static int
_efl_canvas_image_efl_image_animated_animated_loop_count_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_animated_animated_loop_count_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_animated_loop_count_get(eo_obj);
}
@ -476,7 +542,7 @@ _evas_image_animated_frame_duration_get(const Eo *eo_obj, int start_frame, int f
}
EOLIAN static double
_efl_canvas_image_efl_image_animated_animated_frame_duration_get(Eo *eo_obj, void *_pd EINA_UNUSED, int start_frame, int frame_num)
_efl_canvas_image_efl_image_animated_animated_frame_duration_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int start_frame, int frame_num)
{
return _evas_image_animated_frame_duration_get(eo_obj, start_frame, frame_num);
}
@ -518,7 +584,7 @@ _evas_image_animated_frame_set(Eo *eo_obj, int frame_index)
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_image_animated_animated_frame_set(Eo *eo_obj, void *_pd EINA_UNUSED, int frame_index)
_efl_canvas_image_efl_image_animated_animated_frame_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int frame_index)
{
return _evas_image_animated_frame_set(eo_obj, frame_index);
}
@ -534,13 +600,13 @@ _evas_image_animated_frame_get(const Eo *eo_obj)
}
EOLIAN static int
_efl_canvas_image_efl_image_animated_animated_frame_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_image_animated_animated_frame_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
return _evas_image_animated_frame_get(eo_obj);
}
EOLIAN static void
_efl_canvas_image_efl_gfx_buffer_buffer_size_get(Eo *eo_obj, void *_pd EINA_UNUSED, int *w, int *h)
_efl_canvas_image_efl_gfx_buffer_buffer_size_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED, int *w, int *h)
{
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
@ -549,8 +615,8 @@ _efl_canvas_image_efl_gfx_buffer_buffer_size_get(Eo *eo_obj, void *_pd EINA_UNUS
}
static Eina_Bool
_image_pixels_set(Evas_Object_Protected_Data *obj, Evas_Image_Data *o,
void *pixels, int w, int h, int stride,
_image_pixels_set(Evas_Object_Protected_Data *obj, Efl_Canvas_Image_Data *pd,
Evas_Image_Data *o, void *pixels, int w, int h, int stride,
Efl_Gfx_Colorspace cspace, Eina_Bool copy)
{
Eina_Bool resized = EINA_FALSE, ret = EINA_FALSE, easy_copy = EINA_FALSE;
@ -558,6 +624,12 @@ _image_pixels_set(Evas_Object_Protected_Data *obj, Evas_Image_Data *o,
// FIXME: buffer border support is not implemented
if (pd->map_data->maps)
{
ERR("Can not call buffer_data_set after buffer_map.");
return EINA_FALSE;
}
if (o->pixels_checked_out)
{
// is there anything to do?
@ -683,29 +755,29 @@ end:
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_data_set(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_gfx_buffer_buffer_data_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd,
void *pixels, int w, int h, int stride,
Efl_Gfx_Colorspace cspace)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
return _image_pixels_set(obj, o, pixels, w, h, stride, cspace, EINA_FALSE);
return _image_pixels_set(obj, pd, o, pixels, w, h, stride, cspace, EINA_FALSE);
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo *eo_obj, void *_pd EINA_UNUSED,
_efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo *eo_obj, Efl_Canvas_Image_Data *pd,
const void *pixels, int w, int h, int stride,
Efl_Gfx_Colorspace cspace)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
return _image_pixels_set(obj, o, (void *) pixels, w, h, stride, cspace, EINA_TRUE);
return _image_pixels_set(obj, pd, o, (void *) pixels, w, h, stride, cspace, EINA_TRUE);
}
EOLIAN static void *
_efl_canvas_image_efl_gfx_buffer_buffer_data_get(Eo *eo_obj, void *_pd EINA_UNUSED)
_efl_canvas_image_efl_gfx_buffer_buffer_data_get(Eo *eo_obj, Efl_Canvas_Image_Data *pd EINA_UNUSED)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
@ -716,34 +788,75 @@ _efl_canvas_image_efl_gfx_buffer_buffer_data_get(Eo *eo_obj, void *_pd EINA_UNUS
return ENFN->image_data_direct(ENDT, o->engine_data, NULL);
}
static void
_image_preload_internal(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool cancel)
EOLIAN static unsigned char *
_efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, Efl_Canvas_Image_Data *pd,
unsigned int *length,
Efl_Gfx_Buffer_Access_Mode mode,
int x, int y, unsigned int w, unsigned int h,
Efl_Gfx_Colorspace cspace, unsigned int *stride)
{
if (!o->engine_data)
{
o->preloading = EINA_TRUE;
evas_object_inform_call_image_preloaded(eo_obj);
return;
}
// FIXME: if already busy preloading, then dont request again until
// preload done
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if (cancel)
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
unsigned int len = 0, str = 0;
Map_Data *map = NULL;
void *data;
if (!ENFN->image_data_map)
goto end; // not implemented
if (!o->engine_data)
goto end;
if ((x < 0) || (y < 0) || ((x + (int) w) > (int) o->cur->image.w) || ((y + (int) h) > (int) o->cur->image.h))
{
if (o->preloading)
{
o->preloading = EINA_FALSE;
ENFN->image_data_preload_cancel(ENDT, o->engine_data, eo_obj);
}
ERR("Invalid map dimensions: %dx%d +%d,%d. Image is %dx%d.",
w, h, x, y, o->cur->image.w, o->cur->image.h);
goto end;
}
else
data = ENFN->image_data_map(ENDT, &o->engine_data, &len, &str, x, y, w, h, cspace, mode);
if (data)
{
if (!o->preloading)
{
o->preloading = EINA_TRUE;
ENFN->image_data_preload_request(ENDT, o->engine_data, eo_obj);
}
map = calloc(1, sizeof(*map));
map->ptr = data;
map->size = len;
EINA_COW_WRITE_BEGIN(_map_data_cow, pd->map_data, Map_Data_Cow, mdata)
mdata->maps = (Map_Data *) eina_inlist_append(EINA_INLIST_GET(mdata->maps), EINA_INLIST_GET(map));
EINA_COW_WRITE_END(_map_data_cow, pd->map_data, mdata);
}
end:
if (length) *length = len;
if (stride) *stride = str;
return map ? map->ptr : NULL;
}
EOLIAN static void
_efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, Efl_Canvas_Image_Data *pd,
unsigned char *data, unsigned int length)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
Map_Data *map;
if (!ENFN->image_data_map)
goto fail; // not implemented
if (!o->engine_data)
goto fail;
EINA_INLIST_FOREACH(pd->map_data->maps, map)
if ((map->ptr == data) && (map->size == length))
{
EINA_COW_WRITE_BEGIN(_map_data_cow, pd->map_data, Map_Data_Cow, mdata)
mdata->maps = (Map_Data *) eina_inlist_remove(EINA_INLIST_GET(mdata->maps), EINA_INLIST_GET(map));
EINA_COW_WRITE_END(_map_data_cow, pd->map_data, mdata);
o->engine_data = ENFN->image_data_unmap(ENDT, o->engine_data, data, length);
free(map);
}
fail:
ERR("unmap failed");
}
#include "efl_canvas_image.eo.c"

View File

@ -6,12 +6,15 @@ class Efl.Canvas.Image (Evas.Image, Efl.Image_Load, Efl.Image_Animated)
interfaces: file and data images only. This object does not implement
any special features such as proxy, snapshot or GL.
]]
data: null;
implements {
class.constructor;
class.destructor;
Efl.Gfx.Buffer.buffer_data_get;
Efl.Gfx.Buffer.buffer_data_set;
Efl.Gfx.Buffer.buffer_copy_set;
Efl.Gfx.Buffer.buffer_size.get;
Efl.Gfx.Buffer.buffer_map;
Efl.Gfx.Buffer.buffer_unmap;
Efl.File.file.set;
Efl.File.file.get;
Efl.File.mmap.set;

View File

@ -1364,6 +1364,9 @@ struct _Evas_Func
Evas_Colorspace (*image_file_colorspace_get)(void *data, void *image);
Eina_Bool (*image_can_region_get) (void *data, void *image);
void *(*image_data_map) (void *data, void **image, unsigned int *length, unsigned int *stride, int x, int y, int w, int h, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode);
void *(*image_data_unmap) (void *data, void *image, void *map, unsigned int length);
int (*image_native_init) (void *data, Evas_Native_Surface_Type type);
void (*image_native_shutdown) (void *data, Evas_Native_Surface_Type type);
void *(*image_native_set) (void *data, void *image, void *native);

View File

@ -4159,6 +4159,8 @@ static Evas_Func func =
eng_image_colorspace_get,
eng_image_file_colorspace_get,
eng_image_can_region_get,
NULL, // image_data_map
NULL, // image_data_unmap
eng_image_native_init,
eng_image_native_shutdown,
eng_image_native_set,