forked from enlightenment/efl
Efl.Canvas.Image: Implement raw data_set/copy/get
No more refcount. This is only to initialize the data from an external buffer. data_get will only work if data_set was used (not even copy_set).
This commit is contained in:
parent
f78cbac9e6
commit
08c1160888
|
@ -157,10 +157,9 @@ interface Efl.Gfx.Buffer ()
|
|||
@in length: uint; [[Must be the same as returned by map.]]
|
||||
}
|
||||
}
|
||||
/* note: not a property because the refcount needs to be explicit
|
||||
* between set and get */
|
||||
/* FIXME: do we need writable flag? */
|
||||
buffer_set {
|
||||
|
||||
/* FIXME: naming: buffer_set, buffer_attach, external_data_set, ...? */
|
||||
buffer_data_set {
|
||||
[[Set the pixels for this buffer, or allocate a new memory region.
|
||||
|
||||
EFL will use $pixels directly, and update the GPU-side texture
|
||||
|
@ -170,15 +169,8 @@ interface Efl.Gfx.Buffer ()
|
|||
If the buffer already had pixel data, the previous image data will
|
||||
be dropped. This is the same as @.buffer_copy_set.
|
||||
|
||||
If $pixels is the return value of @.buffer_get then EFL will
|
||||
decrement its internal reference count on the buffer data. Call
|
||||
@.buffer_update_add to flush updates and indicate changes in
|
||||
the pixel data.
|
||||
|
||||
The memory buffer $pixels must be large enough to hold
|
||||
$width x $height pixels encoded in the colorspace $cspace.
|
||||
Alternatively $pixels must be larger than $height x $stride
|
||||
in bytes.
|
||||
|
||||
See also @.buffer_copy_set if you want EFL to copy the input buffer
|
||||
internally.
|
||||
|
@ -202,18 +194,12 @@ interface Efl.Gfx.Buffer ()
|
|||
|
||||
If $pixels is $null, then a new empty buffer will be allocated.
|
||||
If the buffer already had pixel data, the previous image data will
|
||||
be dropped. This is the same as @.buffer_set.
|
||||
be dropped. This is the same as @.buffer_data_set.
|
||||
|
||||
The memory buffer $pixels must be large enough to hold
|
||||
$width x $height pixels encoded in the colorspace $cspace.
|
||||
Alternatively $pixels must be larger than $height x $stride
|
||||
in bytes.
|
||||
|
||||
$pixels should not be the return value of @.buffer_get.
|
||||
|
||||
There is no copy equivalent to this function, as you can easily
|
||||
call @.buffer_get and allocate the proper buffer on your side,
|
||||
followed by a memory copy and @.buffer_set.
|
||||
$pixels should not be the return value of @.buffer_data_get.
|
||||
]]
|
||||
params {
|
||||
@in pixels: const(void)* @nullable; [[If $null, allocates an empty buffer]]
|
||||
|
@ -224,29 +210,15 @@ interface Efl.Gfx.Buffer ()
|
|||
}
|
||||
return: bool @warn_unused; [[This function returns $false in case of failure.]]
|
||||
}
|
||||
buffer_get {
|
||||
[[Get a direct pointer to the internal pixel data.
|
||||
buffer_data_get {
|
||||
[[Get a direct pointer to the internal pixel data, if available.
|
||||
|
||||
This will increment an internal reference counter on the internal
|
||||
buffer. If $to_write is $true, this may trigger a copy of the
|
||||
internal pixel data, and return a writable memory block.
|
||||
This will return $null unless @.buffer_data_set was used to pass in an
|
||||
external data pointer.
|
||||
|
||||
Call @.buffer_size.get to know the value of $width and $height.
|
||||
The memory buffer length in bytes is defined as $height x $stride.
|
||||
|
||||
Warning: @.buffer_set MUST be called as soon as possible after
|
||||
calling @.buffer_get. @.buffer_update_add should be called after
|
||||
@.buffer_set if $to_write was $true and the pixel data has been
|
||||
modified. Once @.buffer_set is called, the pointer returned by
|
||||
@.buffer_get is not valid anymore.
|
||||
Note: This is different from the legacy API data, which is now
|
||||
replaced by map/unmap.
|
||||
]]
|
||||
params {
|
||||
@in to_write: bool; [[If $true, requests write access]]
|
||||
@out width: int @optional;
|
||||
@out height: int @optional;
|
||||
@out stride: int @optional; [[Returns the length of one row of pixels in bytes, so that length = $height x $stride.]]
|
||||
@out cspace: Efl.Gfx.Colorspace @optional; [[Pixel encoding of the returned buffer.]]
|
||||
}
|
||||
return: void* @warn_unused;
|
||||
}
|
||||
/* Note: border, span and buffer flags not imported from ector buffer */
|
||||
|
|
|
@ -19,6 +19,7 @@ _evas_image_mmap_set(Eo *eo_obj, const Eina_File *f, const char *key)
|
|||
evas_object_async_block(obj);
|
||||
_evas_image_init_set(f, NULL, key, eo_obj, obj, o, &lo);
|
||||
o->engine_data = ENFN->image_mmap(ENDT, o->cur->u.f, o->cur->key, &o->load_error, &lo);
|
||||
o->buffer_data_set = EINA_FALSE;
|
||||
_evas_image_done_set(eo_obj, obj, o);
|
||||
|
||||
return EINA_TRUE;
|
||||
|
@ -67,6 +68,7 @@ _evas_image_file_set(Eo *eo_obj, const char *file, const char *key)
|
|||
evas_object_async_block(obj);
|
||||
_evas_image_init_set(NULL, file, key, eo_obj, obj, o, &lo);
|
||||
o->engine_data = ENFN->image_load(ENDT, o->cur->u.file, o->cur->key, &o->load_error, &lo);
|
||||
o->buffer_data_set = EINA_FALSE;
|
||||
_evas_image_done_set(eo_obj, obj, o);
|
||||
|
||||
return EINA_TRUE;
|
||||
|
@ -354,7 +356,7 @@ _evas_image_load_orientation_get(const Eo *eo_obj)
|
|||
{
|
||||
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
|
||||
|
||||
return o->load_opts->orientation;;
|
||||
return o->load_opts->orientation;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
|
@ -400,17 +402,15 @@ _efl_canvas_image_efl_image_animated_animated_get(Eo *eo_obj, void *_pd EINA_UNU
|
|||
int
|
||||
_evas_image_animated_frame_count_get(const Eo *eo_obj)
|
||||
{
|
||||
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);
|
||||
Evas_Object_Protected_Data *obj;
|
||||
int frame_count = -1;
|
||||
|
||||
if (!evas_object_image_animated_get(eo_obj)) return frame_count;
|
||||
if (!ENFN->image_animated_frame_count_get ||
|
||||
!evas_object_image_animated_get(eo_obj))
|
||||
return -1;
|
||||
|
||||
obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
|
||||
if (ENFN->image_animated_frame_count_get)
|
||||
frame_count = ENFN->image_animated_frame_count_get(ENDT, o->engine_data);
|
||||
|
||||
return frame_count;
|
||||
return ENFN->image_animated_frame_count_get(ENDT, o->engine_data);
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
|
@ -423,15 +423,13 @@ Efl_Image_Animated_Loop_Hint
|
|||
_evas_image_animated_loop_type_get(const Eo *eo_obj)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
|
||||
Efl_Image_Animated_Loop_Hint hint = EFL_IMAGE_ANIMATED_LOOP_HINT_NONE;
|
||||
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
|
||||
|
||||
if (!evas_object_image_animated_get(eo_obj)) return hint;
|
||||
if (!ENFN->image_animated_loop_type_get ||
|
||||
!evas_object_image_animated_get(eo_obj))
|
||||
return EFL_IMAGE_ANIMATED_LOOP_HINT_NONE;
|
||||
|
||||
if (ENFN->image_animated_loop_type_get)
|
||||
hint = (Efl_Image_Animated_Loop_Hint) ENFN->image_animated_loop_type_get(ENDT, o->engine_data);
|
||||
|
||||
return hint;
|
||||
return (Efl_Image_Animated_Loop_Hint) ENFN->image_animated_loop_type_get(ENDT, o->engine_data);
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Image_Animated_Loop_Hint
|
||||
|
@ -446,16 +444,11 @@ _evas_image_animated_loop_count_get(const Eo *eo_obj)
|
|||
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);
|
||||
|
||||
int loop_count;
|
||||
loop_count = -1;
|
||||
if (!evas_object_image_animated_get(eo_obj)) return loop_count;
|
||||
if (!ENFN->image_animated_loop_count_get ||
|
||||
!evas_object_image_animated_get(eo_obj))
|
||||
return -1;
|
||||
|
||||
loop_count =
|
||||
ENFN->image_animated_loop_count_get ?
|
||||
ENFN->image_animated_loop_count_get(ENDT, o->engine_data) :
|
||||
-1;
|
||||
|
||||
return loop_count;
|
||||
return ENFN->image_animated_loop_count_get(ENDT, o->engine_data);
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
|
@ -469,18 +462,17 @@ _evas_image_animated_frame_duration_get(const Eo *eo_obj, int start_frame, int f
|
|||
{
|
||||
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);
|
||||
double frame_duration = -1;
|
||||
int frame_count = 0;
|
||||
|
||||
if (!ENFN->image_animated_frame_count_get) return frame_duration;
|
||||
if (!ENFN->image_animated_frame_count_get ||
|
||||
!ENFN->image_animated_frame_duration_get)
|
||||
return -1.0;
|
||||
|
||||
frame_count = ENFN->image_animated_frame_count_get(ENDT, o->engine_data);
|
||||
if ((start_frame + frame_num) > frame_count)
|
||||
return -1.0;
|
||||
|
||||
if ((start_frame + frame_num) > frame_count) return frame_duration;
|
||||
if (ENFN->image_animated_frame_duration_get)
|
||||
frame_duration = ENFN->image_animated_frame_duration_get(ENDT, o->engine_data, start_frame, frame_num);
|
||||
|
||||
return frame_duration;
|
||||
return ENFN->image_animated_frame_duration_get(ENDT, o->engine_data, start_frame, frame_num);
|
||||
}
|
||||
|
||||
EOLIAN static double
|
||||
|
@ -547,6 +539,190 @@ _efl_canvas_image_efl_image_animated_animated_frame_get(Eo *eo_obj, void *_pd EI
|
|||
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)
|
||||
{
|
||||
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
|
||||
|
||||
if (w) *w = o->cur->image.w;
|
||||
if (h) *h = o->cur->image.h;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_image_pixels_set(Evas_Object_Protected_Data *obj, 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;
|
||||
int int_stride = 0;
|
||||
|
||||
// FIXME: buffer border support is not implemented
|
||||
|
||||
if (o->pixels_checked_out)
|
||||
{
|
||||
// is there anything to do?
|
||||
ERR("Calling buffer_data_set after evas_object_image_data_get is not "
|
||||
"valid. Discarding previous data pointer.");
|
||||
o->pixels_checked_out = 0;
|
||||
}
|
||||
|
||||
if (o->engine_data)
|
||||
{
|
||||
ENFN->image_free(ENDT, o->engine_data);
|
||||
o->engine_data = NULL;
|
||||
}
|
||||
|
||||
switch (cspace)
|
||||
{
|
||||
case EVAS_COLORSPACE_ARGB8888:
|
||||
case EVAS_COLORSPACE_AGRY88:
|
||||
case EVAS_COLORSPACE_GRY8:
|
||||
easy_copy = EINA_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int_stride = _evas_common_rgba_image_surface_size(w, 1, cspace, NULL, NULL, NULL, NULL);
|
||||
if (!stride) stride = int_stride;
|
||||
|
||||
if (!copy && (int_stride != stride))
|
||||
{
|
||||
// FIXME: Add proper support for stride inside the engines
|
||||
ERR("Unable to create an image with stride %d, got %d", stride, int_stride);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if ((o->cur->image.w != w) || (o->cur->image.h != h))
|
||||
resized = EINA_TRUE;
|
||||
|
||||
o->buffer_data_set = EINA_FALSE;
|
||||
if (pixels && !copy)
|
||||
{
|
||||
// direct use
|
||||
o->engine_data = ENFN->image_new_from_data(ENDT, w, h, pixels, o->cur->has_alpha, cspace);
|
||||
o->buffer_data_set = (o->engine_data != NULL);
|
||||
}
|
||||
else if (stride == int_stride)
|
||||
{
|
||||
// simple copy
|
||||
o->engine_data = ENFN->image_new_from_copied_data(ENDT, w, h, pixels, o->cur->has_alpha, cspace);
|
||||
}
|
||||
else if (easy_copy)
|
||||
{
|
||||
// copy each line. ouch.
|
||||
o->engine_data = ENFN->image_new_from_copied_data(ENDT, w, h, NULL, o->cur->has_alpha, cspace);
|
||||
if (o->engine_data)
|
||||
{
|
||||
uint8_t *data = NULL, *pixels_iter = pixels;
|
||||
void *engine_data;
|
||||
int y;
|
||||
|
||||
engine_data = ENFN->image_data_get(ENDT, o->engine_data, 0, (DATA32 **) &data, &o->load_error, NULL);
|
||||
if (!engine_data || !data)
|
||||
{
|
||||
ERR("Failed to copy image!");
|
||||
goto end;
|
||||
}
|
||||
o->engine_data = engine_data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(data + (y * int_stride), pixels_iter, int_stride);
|
||||
pixels_iter += stride;
|
||||
}
|
||||
o->engine_data = ENFN->image_data_put(ENDT, o->engine_data, (DATA32 *) data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// quite unlikely: non-standard cspace + stride
|
||||
ERR("Can not copy colorspace %d with stride %d", cspace, stride);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!o->engine_data)
|
||||
{
|
||||
ERR("Failed to create internal image (%dx%d, cspace: %d, pixels: %p)",
|
||||
w, h, cspace, pixels);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if (ENFN->image_scale_hint_set)
|
||||
ENFN->image_scale_hint_set(ENDT, o->engine_data, o->scale_hint);
|
||||
|
||||
if (ENFN->image_content_hint_set)
|
||||
ENFN->image_content_hint_set(ENDT, o->engine_data, o->content_hint);
|
||||
|
||||
if (ENFN->image_stride_get)
|
||||
ENFN->image_stride_get(ENDT, o->engine_data, &int_stride);
|
||||
|
||||
if (resized || o->cur->u.file || o->cur->key ||
|
||||
(o->cur->image.stride != int_stride) || (cspace != o->cur->cspace))
|
||||
{
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, cur)
|
||||
{
|
||||
cur->u.f = NULL;
|
||||
cur->key = NULL;
|
||||
cur->cspace = cspace;
|
||||
cur->image.w = w;
|
||||
cur->image.h = h;
|
||||
cur->image.stride = int_stride;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, cur)
|
||||
}
|
||||
|
||||
ret = EINA_TRUE;
|
||||
|
||||
end:
|
||||
o->written = EINA_TRUE;
|
||||
if (resized)
|
||||
evas_object_inform_call_image_resize(obj->object);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_canvas_image_efl_gfx_buffer_buffer_data_set(Eo *eo_obj, void *_pd EINA_UNUSED,
|
||||
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);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo *eo_obj, void *_pd EINA_UNUSED,
|
||||
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);
|
||||
}
|
||||
|
||||
EOLIAN static void *
|
||||
_efl_canvas_image_efl_gfx_buffer_buffer_data_get(Eo *eo_obj, void *_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);
|
||||
DATA32 *data = NULL;
|
||||
|
||||
if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_has)
|
||||
return NULL;
|
||||
|
||||
if (ENFN->image_data_has(ENDT, o->engine_data, NULL))
|
||||
{
|
||||
// FIXME: this is horrible code - need to store ptr somewhere safe
|
||||
o->engine_data = ENFN->image_data_get(ENDT, o->engine_data, 0, &data, &o->load_error, NULL);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
_image_preload_internal(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool cancel)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,10 @@ class Efl.Canvas.Image (Evas.Image, Efl.Image_Load, Efl.Image_Animated)
|
|||
]]
|
||||
data: null;
|
||||
implements {
|
||||
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.File.file.set;
|
||||
Efl.File.file.get;
|
||||
Efl.File.mmap.set;
|
||||
|
|
|
@ -157,7 +157,7 @@ EAPI int
|
|||
evas_object_image_stride_get(const Evas_Object *obj)
|
||||
{
|
||||
EVAS_IMAGE_API(obj, 0);
|
||||
Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS);
|
||||
Evas_Image_Data *o = eo_data_scope_get(obj, EVAS_IMAGE_CLASS);
|
||||
return o->cur->image.stride;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ struct _Evas_Image_Data
|
|||
Eina_Bool written : 1;
|
||||
Eina_Bool direct_render : 1;
|
||||
Eina_Bool has_filter : 1;
|
||||
Eina_Bool buffer_data_set : 1;
|
||||
struct
|
||||
{
|
||||
Eina_Bool video_move : 1;
|
||||
|
|
Loading…
Reference in New Issue