evas: Switch EO APIs to Eina_Slice for gfx buffers (map)

This adds a plane and eina slice argument to the map/unmap
functions, instead of void_ptr + length.
This commit is contained in:
Jean-Philippe Andre 2016-09-01 21:46:42 +09:00
parent 1773ba5d82
commit 8ee431572d
10 changed files with 296 additions and 202 deletions

View File

@ -26,8 +26,8 @@
#define IMG_WIDTH 256 #define IMG_WIDTH 256
#define IMG_HEIGHT 256 #define IMG_HEIGHT 256
// TODO: remove this when map/unmap are fully supported (GL engine) // undef this to test the legacy API for images
#undef USE_EO_IMAGE #define USE_EO_IMAGE
typedef struct _Scene_Data typedef struct _Scene_Data
{ {
@ -73,7 +73,7 @@ _animate_scene(void *data)
static float angle = 0.0f; static float angle = 0.0f;
Scene_Data *scene = (Scene_Data *)data; Scene_Data *scene = (Scene_Data *)data;
unsigned int *pixels; unsigned int *pixels;
int i, j, stride, length; int i, j, stride;
angle += 0.5; angle += 0.5;
@ -83,11 +83,12 @@ _animate_scene(void *data)
if (angle > 360.0) angle -= 360.0f; if (angle > 360.0) angle -= 360.0f;
#ifdef USE_EO_IMAGE #ifdef USE_EO_IMAGE
pixels = efl_gfx_buffer_map(source, &length, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, 0, 0, 0, 0, Eina_Rw_Slice slice;
EFL_GFX_COLORSPACE_ARGB8888, &stride); if (!efl_gfx_buffer_map(source, &slice, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, 0, 0, 0, 0,
if (!pixels) return EINA_TRUE; EFL_GFX_COLORSPACE_ARGB8888, 0, &stride))
return EINA_TRUE;
pixels = slice.mem;
#else #else
(void) length;
pixels = evas_object_image_data_get(source, EINA_TRUE); pixels = evas_object_image_data_get(source, EINA_TRUE);
stride = evas_object_image_stride_get(source); stride = evas_object_image_stride_get(source);
#endif #endif
@ -103,7 +104,7 @@ _animate_scene(void *data)
} }
#ifdef USE_EO_IMAGE #ifdef USE_EO_IMAGE
efl_gfx_buffer_unmap(source, pixels, length); efl_gfx_buffer_unmap(source, &slice);
efl_gfx_buffer_update_add(source, 0, 0, IMG_WIDTH, IMG_HEIGHT); efl_gfx_buffer_update_add(source, 0, 0, IMG_WIDTH, IMG_HEIGHT);
#else #else
evas_object_image_data_set(source, pixels); evas_object_image_data_set(source, pixels);
@ -226,7 +227,7 @@ main(void)
/* Add a background image. */ /* Add a background image. */
#ifdef USE_EO_IMAGE #ifdef USE_EO_IMAGE
source = efl_add(EFL_CANVAS_IMAGE_CLASS, evas); source = efl_add(EFL_CANVAS_IMAGE_CLASS, evas);
efl_gfx_buffer_data_set(source, NULL, WIDTH, HEIGHT, 0, EFL_GFX_COLORSPACE_ARGB8888); efl_gfx_buffer_copy_set(source, NULL, IMG_WIDTH, IMG_HEIGHT, 0, EFL_GFX_COLORSPACE_ARGB8888, 0);
efl_gfx_position_set(source, (WIDTH / 2), (HEIGHT / 2)); efl_gfx_position_set(source, (WIDTH / 2), (HEIGHT / 2));
efl_gfx_size_set(source, (WIDTH / 2), (HEIGHT / 2)); efl_gfx_size_set(source, (WIDTH / 2), (HEIGHT / 2));
efl_gfx_visible_set(source, EINA_TRUE); efl_gfx_visible_set(source, EINA_TRUE);

View File

@ -1,4 +1,5 @@
import efl_gfx_types; import efl_gfx_types;
import eina_types;
/* FIXME: this is very very low level. expose to apps? */ /* FIXME: this is very very low level. expose to apps? */
enum Efl.Gfx.Buffer.Access_Mode { enum Efl.Gfx.Buffer.Access_Mode {
@ -8,6 +9,8 @@ enum Efl.Gfx.Buffer.Access_Mode {
cow = 0x4, [[Forces copy-on-write if already mapped as read-only. Requires write.]] cow = 0x4, [[Forces copy-on-write if already mapped as read-only. Requires write.]]
} }
/* FIXME: YUV and other planar formats are not properly handled in this API! */
interface Efl.Gfx.Buffer () interface Efl.Gfx.Buffer ()
{ {
[[Common APIs for all objects representing images and 2D pixel buffers.]] [[Common APIs for all objects representing images and 2D pixel buffers.]]
@ -129,7 +132,7 @@ interface Efl.Gfx.Buffer ()
be negative. be negative.
]] ]]
params { params {
@out length: int @nonull; [[Accessible buffer size in bytes, should not be $null.]] @out slice: Eina.Rw_Slice; [[Pointer to the top-left pixel data.]]
@in mode: Efl.Gfx.Buffer.Access_Mode; [[Specifies whether to map for read-only, @in mode: Efl.Gfx.Buffer.Access_Mode; [[Specifies whether to map for read-only,
write-only or read-write access (OR combinaison of flags).]] write-only or read-write access (OR combinaison of flags).]]
@in x: int @optional; [[X position of the top-left pixel to map, defaults to 0.]] @in x: int @optional; [[X position of the top-left pixel to map, defaults to 0.]]
@ -139,48 +142,25 @@ interface Efl.Gfx.Buffer ()
@in cspace: Efl.Gfx.Colorspace @optional; [[Requested colorspace. If differen from the internal cspace, @in cspace: Efl.Gfx.Colorspace @optional; [[Requested colorspace. If differen from the internal cspace,
map should try to convert the data into a new buffer. map should try to convert the data into a new buffer.
argb8888 by default.]] argb8888 by default.]]
@in plane: int @optional; [[Plane ID. 0 by default. Useful for planar formats only.]]
@out stride: int @optional; [[Returns the length in bytes of a mapped line]] @out stride: int @optional; [[Returns the length in bytes of a mapped line]]
} }
return: void_ptr @warn_unused; [[Pointer to the top-left pixel data. Returns $null in case of failure]] return: bool;
} }
buffer_unmap { buffer_unmap {
[[Unmap a region of this buffer, and update the internal data if needed. [[Unmap a region of this buffer, and update the internal data if needed.
EFL will update the internal image if the map had write access. EFL will update the internal image if the map had write access.
Note: The $slice struct does not need to be the one returned
by @.buffer_map, only its contents ($mem and $len) must match. But
after a call to @.buffer_unmap the original $slice structure is not
valid anymore.
]] ]]
params { params {
@in data: void_ptr; [[Data pointer returned by a previous call to map]] @in slice: const(Eina.Rw_Slice)*; [[Data slice returned by a previous call to map.]]
@in length: int; [[Must be the same as returned by map.]]
} }
return: bool; [[This will return $false in case of failure (invalid return: bool;
parameters or state of the object).]]
}
/* 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
if required. This will mark the image as dirty.
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_copy_set.
The memory buffer $pixels must be large enough to hold
$width x $height pixels encoded in the colorspace $cspace.
See also @.buffer_copy_set if you want EFL to copy the input buffer
internally.
]]
params {
@in pixels: void_ptr @nullable; [[If $null, allocates an empty buffer]]
@in width: int;
@in height: int;
@in stride: int @optional; [[If 0, automatically guessed from the $width.]]
@in cspace: Efl.Gfx.Colorspace @optional; [[argb8888 by default.]]
}
return: bool @warn_unused; [[This function returns $false in case of failure.]]
} }
buffer_copy_set { buffer_copy_set {
[[Set the pixels for this buffer by copying them, or allocate [[Set the pixels for this buffer by copying them, or allocate
@ -192,32 +172,61 @@ interface Efl.Gfx.Buffer ()
If $pixels is $null, then a new empty buffer will be allocated. If $pixels is $null, then a new empty buffer will be allocated.
If the buffer already had pixel data, the previous image data will If the buffer already had pixel data, the previous image data will
be dropped. This is the same as @.buffer_data_set. be dropped. This is the same as @.buffer_managed_set.
The memory buffer $pixels must be large enough to hold The memory buffer $pixels must be large enough to hold
$width x $height pixels encoded in the colorspace $cspace. $width x $height pixels encoded in the colorspace $cspace.
$pixels should not be the return value of @.buffer_data_get. $slice should not be the return value of @.buffer_managed_get.
]] ]]
params { params {
@in pixels: const(void_ptr) @nullable; [[If $null, allocates an empty buffer]] @in slice: const(Eina.Slice)* @nullable; [[If $null, allocates an empty buffer]]
@in width: int; @in width: int;
@in height: int; @in height: int;
@in stride: int @optional; [[If 0, automatically guessed from the $width.]] @in stride: int @optional; [[If 0, automatically guessed from the $width.]]
@in cspace: Efl.Gfx.Colorspace @optional; [[argb8888 by default.]] @in cspace: Efl.Gfx.Colorspace @optional; [[argb8888 by default.]]
@in plane: int @optional; [[Plane ID. 0 by default. Useful for planar formats only.]]
} }
return: bool @warn_unused; [[This function returns $false in case of failure.]] return: bool;
} }
buffer_data_get { buffer_managed_set {
[[Set the pixels for this buffer, managed externally by the client.
EFL will use the pixel data directly, and update the GPU-side
texture if required. This will mark the image as dirty. If $slice
is $null, this will detach the pixel data.
If the buffer already had pixel data, the previous image data will
be dropped. This is the same as @.buffer_copy_set.
The memory buffer $pixels must be large enough to hold
$width x $height pixels encoded in the colorspace $cspace.
See also @.buffer_copy_set if you want EFL to copy the input buffer
internally.
]]
params {
@in slice: const(Eina.Slice)* @nullable; [[If $null, detaches the previous buffer.]]
@in width: int;
@in height: int;
@in stride: int @optional; [[If 0, automatically guessed from the $width.]]
@in cspace: Efl.Gfx.Colorspace @optional; [[argb8888 by default.]]
@in plane: int @optional; [[Plane ID. 0 by default. Useful for planar formats only.]]
}
return: bool;
}
buffer_managed_get {
[[Get a direct pointer to the internal pixel data, if available. [[Get a direct pointer to the internal pixel data, if available.
This will return $null unless @.buffer_data_set was used to pass in an This will return $null unless @.buffer_managed_set was used to pass
external data pointer. in an external data pointer. The returned @Eina.Slice struct must be
freed by the caller.
Note: This is different from the legacy API data, which is now
replaced by map/unmap.
]] ]]
return: void_ptr @warn_unused; params {
@out slice: Eina.Slice;
@in plane: int @optional; [[Plane ID. 0 by default. Useful for planar formats only.]]
}
return: bool;
} }
/* Note: border, span and buffer flags not imported from ector buffer */ /* Note: border, span and buffer flags not imported from ector buffer */
} }

View File

@ -591,13 +591,22 @@ _efl_canvas_image_efl_gfx_buffer_buffer_size_get(Eo *eo_obj, void *_pd EINA_UNUS
static Eina_Bool static Eina_Bool
_image_pixels_set(Evas_Object_Protected_Data *obj, _image_pixels_set(Evas_Object_Protected_Data *obj,
Evas_Image_Data *o, void *pixels, int w, int h, int stride, Evas_Image_Data *o, const Eina_Slice *slice,
Efl_Gfx_Colorspace cspace, Eina_Bool copy) int w, int h, int stride, Efl_Gfx_Colorspace cspace, int plane,
Eina_Bool copy)
{ {
Eina_Bool resized = EINA_FALSE, ret = EINA_FALSE, easy_copy = EINA_FALSE; Eina_Bool resized = EINA_FALSE, ret = EINA_FALSE, easy_copy = EINA_FALSE;
int int_stride = 0; int int_stride = 0;
void *pixels = NULL;
// FIXME: buffer border support is not implemented // FIXME: buffer border support is not implemented
// FIXME: implement YUV support
if (plane)
{
ERR("planar formats not supported yet");
return EINA_FALSE;
}
if (ENFN->image_data_maps_get) if (ENFN->image_data_maps_get)
{ {
@ -627,6 +636,12 @@ _image_pixels_set(Evas_Object_Protected_Data *obj,
o->file_obj = NULL; o->file_obj = NULL;
} }
if (!slice && !copy)
{
ret = EINA_TRUE;
goto end;
}
switch (cspace) switch (cspace)
{ {
case EVAS_COLORSPACE_ARGB8888: case EVAS_COLORSPACE_ARGB8888:
@ -638,6 +653,20 @@ _image_pixels_set(Evas_Object_Protected_Data *obj,
break; break;
} }
// FIXME: Properly handle YUV and other planar formats
if (slice && easy_copy)
{
size_t len;
pixels = (void *) slice->mem;
len = _evas_common_rgba_image_surface_size(w, h, cspace, NULL, NULL, NULL, NULL);
if ((stride && (slice->len < (size_t) (stride * h))) || (slice->len < len))
{
ERR("data slice is too short! (%zub, %dx%d)", slice->len, w, h);
goto end;
}
}
int_stride = _evas_common_rgba_image_surface_size(w, 1, cspace, NULL, NULL, NULL, NULL); int_stride = _evas_common_rgba_image_surface_size(w, 1, cspace, NULL, NULL, NULL, NULL);
if (!stride) stride = int_stride; if (!stride) stride = int_stride;
@ -738,50 +767,82 @@ end:
} }
EOLIAN static Eina_Bool 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_managed_set(Eo *eo_obj, void *_pd EINA_UNUSED,
void *pixels, int w, int h, int stride, const Eina_Slice *slice,
Efl_Gfx_Colorspace cspace) int w, int h, int stride,
Efl_Gfx_Colorspace cspace,
int plane)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
return _image_pixels_set(obj, o, pixels, w, h, stride, cspace, EINA_FALSE); return _image_pixels_set(obj, o, slice, w, h, stride, cspace, plane, EINA_FALSE);
} }
EOLIAN static Eina_Bool 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, void *_pd EINA_UNUSED,
const void *pixels, int w, int h, int stride, const Eina_Slice *slice, int w, int h, int stride,
Efl_Gfx_Colorspace cspace) Efl_Gfx_Colorspace cspace, int plane)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
return _image_pixels_set(obj, o, (void *) pixels, w, h, stride, cspace, EINA_TRUE); return _image_pixels_set(obj, o, slice, w, h, stride, cspace, plane, EINA_TRUE);
} }
EOLIAN static void * EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_data_get(Eo *eo_obj, void *_pd EINA_UNUSED EINA_UNUSED) _efl_canvas_image_efl_gfx_buffer_buffer_managed_get(Eo *eo_obj, void *_pd EINA_UNUSED EINA_UNUSED,
Eina_Slice *slice, int plane)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
int w = 0, h = 0;
void *pixels;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (plane)
{
ERR("planar formats not supported yet!");
return EINA_FALSE;
}
if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_direct) if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_direct)
return NULL; return EINA_FALSE;
return ENFN->image_data_direct(ENDT, o->engine_data, NULL); pixels = ENFN->image_data_direct(ENDT, o->engine_data, &cspace);
if (!pixels) return EINA_FALSE;
slice->mem = pixels;
// note: length may not be same as what was originally given
ENFN->image_size_get(ENDT, o->engine_data, &w, &h);
slice->len = _evas_common_rgba_image_surface_size(w, h, cspace, NULL, NULL, NULL, NULL);
return EINA_TRUE;
} }
EOLIAN static void * EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED, _efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
int *length, Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode, Efl_Gfx_Buffer_Access_Mode mode,
int x, int y, int w, int h, int x, int y, int w, int h,
Efl_Gfx_Colorspace cspace, int *stride) Efl_Gfx_Colorspace cspace,
int plane, int *stride)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
int s = 0, width = 0, height = 0; int s = 0, width = 0, height = 0;
const Eina_Rw_Slice *slice = NULL; Eina_Bool ret = EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!ENFN->image_data_map) if (!ENFN->image_data_map)
goto end; // not implemented goto end; // not implemented
@ -807,34 +868,30 @@ _efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
goto end; goto end;
} }
slice = ENFN->image_data_map(ENDT, &o->engine_data, &s, x, y, w, h, cspace, mode); if (ENFN->image_data_map(ENDT, &o->engine_data, slice, &s, x, y, w, h, cspace, mode, plane))
if (slice)
{ {
DBG("map(%p, %d,%d %dx%d) -> %p (%zu bytes)", eo_obj, x, y, w, h, DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
slice->mem, slice->len); eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));
ret = EINA_TRUE;
} }
else DBG("map(%p, %d,%d %dx%d) -> (null)", eo_obj, x, y, w, h); else DBG("map(%p, %d,%d %dx%d plane:%d) -> (null)", eo_obj, x, y, w, h, plane);
end: end:
if (length) *length = slice->len;
if (stride) *stride = s; if (stride) *stride = s;
return slice->mem; return ret;
} }
EOLIAN static Eina_Bool EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED, _efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED,
void *data, int length) const Eina_Rw_Slice *slice)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
Eina_Rw_Slice slice;
if (!ENFN->image_data_unmap || !o->engine_data) if (!slice || !ENFN->image_data_unmap || !o->engine_data)
return EINA_FALSE; return EINA_FALSE;
slice.mem = data; if (!ENFN->image_data_unmap(ENDT, o->engine_data, slice))
slice.len = length;
if (!ENFN->image_data_unmap(ENDT, o->engine_data, &slice))
return EINA_FALSE; return EINA_FALSE;
return EINA_TRUE; return EINA_TRUE;

View File

@ -10,8 +10,8 @@ class Efl.Canvas.Image (Efl.Canvas.Image.Internal, Efl.Gfx.Buffer,
]] ]]
data: null; data: null;
implements { implements {
Efl.Gfx.Buffer.buffer_data_get; Efl.Gfx.Buffer.buffer_managed_get;
Efl.Gfx.Buffer.buffer_data_set; Efl.Gfx.Buffer.buffer_managed_set;
Efl.Gfx.Buffer.buffer_copy_set; Efl.Gfx.Buffer.buffer_copy_set;
Efl.Gfx.Buffer.buffer_size.get; Efl.Gfx.Buffer.buffer_size.get;
Efl.Gfx.Buffer.buffer_map; Efl.Gfx.Buffer.buffer_map;

View File

@ -259,25 +259,37 @@ _proxy_image_get(Evas_Image_Data *o)
return source->proxy->surface; return source->proxy->surface;
} }
EOLIAN static void * EOLIAN static Eina_Bool
_efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED, _efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
int *length, Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode, Efl_Gfx_Buffer_Access_Mode mode,
int x, int y, int w, int h, int x, int y, int w, int h,
Efl_Gfx_Colorspace cspace, int *stride) Efl_Gfx_Colorspace cspace, int plane,
int *stride)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
int len = 0, s = 0, width = 0, height = 0; int s = 0, width = 0, height = 0;
const Eina_Rw_Slice *slice = NULL; Eina_Bool ret = EINA_FALSE;
void *image, *data = NULL; void *image;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!ENFN->image_data_map) if (!ENFN->image_data_map)
goto end; // not implemented goto end; // not implemented
if (plane)
{
ERR("invalid plane id for proxy object");
goto end;
}
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE) if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
{ {
ERR("invalid map mode for Proxy object"); ERR("invalid map mode for proxy object");
goto end; goto end;
} }
@ -303,34 +315,30 @@ _efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
goto end; goto end;
} }
slice = ENFN->image_data_map(ENDT, &image, &s, x, y, w, h, cspace, mode); if (ENFN->image_data_map(ENDT, &o->engine_data, slice, &s, x, y, w, h, cspace, mode, plane))
if (slice)
{ {
DBG("map(%p, %d,%d %dx%d) -> %p (%zu bytes)", eo_obj, x, y, w, h, DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
slice->mem, slice->len); eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));
ret = EINA_TRUE;
} }
else DBG("map(%p, %d,%d %dx%d) -> (null)", eo_obj, x, y, w, h); else DBG("map(%p, %d,%d %dx%d plane:%d) -> (null)", eo_obj, x, y, w, h, plane);
end: end:
if (length) *length = len;
if (stride) *stride = s; if (stride) *stride = s;
return data; return ret;
} }
EOLIAN static Eina_Bool EOLIAN static Eina_Bool
_efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED, _efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED,
void *data, int length) const Eina_Rw_Slice *slice)
{ {
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
Eina_Rw_Slice slice;
if (!ENFN->image_data_unmap || !o->engine_data) if (!slice || !ENFN->image_data_unmap || !o->engine_data)
return EINA_FALSE; return EINA_FALSE;
slice.mem = data; if (!ENFN->image_data_unmap(ENDT, o->engine_data, slice))
slice.len = length;
if (!ENFN->image_data_unmap(ENDT, o->engine_data, &slice))
return EINA_FALSE; return EINA_FALSE;
return EINA_TRUE; return EINA_TRUE;

View File

@ -208,12 +208,13 @@ _evas_image_3d_unset(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data
EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data); EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);
} }
EOLIAN static void * EOLIAN static Eina_Bool
_efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED, _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
int *length EINA_UNUSED, Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode, Efl_Gfx_Buffer_Access_Mode mode,
int x, int y, int w, int h, int x, int y, int w, int h,
Efl_Gfx_Colorspace cspace, int *stride EINA_UNUSED) Efl_Gfx_Colorspace cspace, int plane,
int *stride)
{ {
Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
Evas_Public_Data *e; Evas_Public_Data *e;
@ -221,21 +222,27 @@ _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
Evas_Canvas3D_Scene_Data *pd_scene; Evas_Canvas3D_Scene_Data *pd_scene;
int width = -1, height = -1, ntex = -1; int width = -1, height = -1, ntex = -1;
unsigned char *pixels = NULL; unsigned char *pixels = NULL;
size_t len = 0;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!o->cur->scene) if (!o->cur->scene)
{ {
ERR("invalid scene data"); ERR("invalid scene data");
return NULL; return EINA_FALSE;
} }
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE) if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
{ {
ERR("invalid map access mode"); ERR("invalid map access mode");
return NULL; return EINA_FALSE;
} }
if (cspace != EFL_GFX_COLORSPACE_ARGB8888) if (cspace != EFL_GFX_COLORSPACE_ARGB8888)
{ {
ERR("invalid map colorspace. Only ARGB is supported"); ERR("invalid map colorspace. Only ARGB is supported");
return NULL; return EINA_FALSE;
} }
pd_parent = efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_OBJECT_CLASS); pd_parent = efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_OBJECT_CLASS);
@ -252,7 +259,7 @@ _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
{ {
ERR("Invalid map dimensions : %dx%d +%d,%d. Image is %dx%d.", ERR("Invalid map dimensions : %dx%d +%d,%d. Image is %dx%d.",
w, h, x, y, width, height); w, h, x, y, width, height);
return NULL; return EINA_FALSE;
} }
if (e->engine.func->drawable_texture_target_id_get) if (e->engine.func->drawable_texture_target_id_get)
@ -261,23 +268,30 @@ _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
if (e->engine.func->drawable_texture_rendered_pixels_get) if (e->engine.func->drawable_texture_rendered_pixels_get)
{ {
pixels = malloc(w * h * sizeof(DATA32)); //four component texture len = w * h * sizeof(DATA32); //four component texture
pixels = malloc(len + sizeof(*slice) + 8);
e->engine.func->drawable_texture_rendered_pixels_get(ntex, x, y, w, h, e->engine.func->drawable_texture_rendered_pixels_get(ntex, x, y, w, h,
pd_scene->surface, pixels); pd_scene->surface, pixels);
} }
else else
return NULL; return EINA_FALSE;
} }
else else
return NULL; return EINA_FALSE;
return pixels; if (stride) *stride = w * sizeof(DATA32);
slice->mem = pixels;
slice->len = len;
DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));
return EINA_TRUE;
} }
EOLIAN static Eina_Bool EOLIAN static Eina_Bool
_efl_canvas_scene3d_efl_gfx_buffer_buffer_unmap(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED, _efl_canvas_scene3d_efl_gfx_buffer_buffer_unmap(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED,
void *data, int length EINA_UNUSED) const Eina_Rw_Slice *slice)
{ {
free(data); free(slice->mem);
return EINA_TRUE; return EINA_TRUE;
} }

View File

@ -1369,7 +1369,7 @@ struct _Evas_Func
Eina_Bool (*image_can_region_get) (void *data, void *image); Eina_Bool (*image_can_region_get) (void *data, void *image);
/* image data map/unmap: direct or indirect access to pixels data */ /* image data map/unmap: direct or indirect access to pixels data */
const Eina_Rw_Slice *(*image_data_map) (void *data, void **image, int *stride, int x, int y, int w, int h, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode); Eina_Bool (*image_data_map) (void *data, void **image, Eina_Rw_Slice *slice, int *stride, int x, int y, int w, int h, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode, int plane);
Eina_Bool (*image_data_unmap) (void *data, void *image, const Eina_Rw_Slice *slice); Eina_Bool (*image_data_unmap) (void *data, void *image, const Eina_Rw_Slice *slice);
int (*image_data_maps_get) (void *data, const void *image, const Eina_Rw_Slice **slices); int (*image_data_maps_get) (void *data, const void *image, const Eina_Rw_Slice **slices);

View File

@ -2794,17 +2794,18 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
} }
} }
static const Eina_Rw_Slice * static Eina_Bool
eng_image_data_map(void *engdata EINA_UNUSED, void **image, eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice *slice,
int *stride, int x, int y, int w, int h, int *stride, int x, int y, int w, int h,
Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode) Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode,
int plane)
{ {
Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE; Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE;
Evas_GL_Image_Data_Map *map = NULL; Evas_GL_Image_Data_Map *map = NULL;
const Eina_Rw_Slice *slice = NULL;
Evas_GL_Image *im; Evas_GL_Image *im;
Eina_Bool ok;
EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image && slice, EINA_FALSE);
im = *image; im = *image;
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_COW) if (mode & EFL_GFX_BUFFER_ACCESS_MODE_COW)
@ -2818,9 +2819,9 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
int strid = 0; int strid = 0;
// Call sw generic implementation. Should work for simple cases. // Call sw generic implementation. Should work for simple cases.
slice = pfunc.image_data_map(NULL, (void **) &im->im, &strid, ok = pfunc.image_data_map(NULL, (void **) &im->im, slice, &strid,
x, y, w, h, cspace, mode); x, y, w, h, cspace, mode, plane);
if (slice) if (ok)
{ {
map = calloc(1, sizeof(*map)); map = calloc(1, sizeof(*map));
map->cspace = cspace; map->cspace = cspace;
@ -2835,12 +2836,12 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
im->maps = eina_inlist_prepend(im->maps, EINA_INLIST_GET(map)); im->maps = eina_inlist_prepend(im->maps, EINA_INLIST_GET(map));
} }
if (stride) *stride = strid; if (stride) *stride = strid;
return &map->slice; return ok;
} }
// TODO: glReadPixels from FBO if possible // TODO: glReadPixels from FBO if possible
return NULL; return EINA_FALSE;
} }
static Eina_Bool static Eina_Bool
@ -2850,7 +2851,7 @@ eng_image_data_unmap(void *engdata EINA_UNUSED, void *image, const Eina_Rw_Slice
Evas_GL_Image *im = image; Evas_GL_Image *im = image;
Eina_Bool found = EINA_FALSE; Eina_Bool found = EINA_FALSE;
if (!im || !slice) if (!(image && slice))
return EINA_FALSE; return EINA_FALSE;
EINA_INLIST_FOREACH(im->maps, map) EINA_INLIST_FOREACH(im->maps, map)

View File

@ -1453,10 +1453,11 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
return im; return im;
} }
static const Eina_Rw_Slice * static Eina_Bool
eng_image_data_map(void *engdata EINA_UNUSED, void **image, eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice *slice,
int *stride, int x, int y, int w, int h, int *stride, int x, int y, int w, int h,
Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode) Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode,
int plane)
{ {
Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE; Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE;
RGBA_Image_Data_Map *map; RGBA_Image_Data_Map *map;
@ -1465,17 +1466,26 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
int src_stride, src_offset; int src_stride, src_offset;
void *data; void *data;
EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image && slice, EINVAL);
im = *image; im = *image;
ie = &im->cache_entry; ie = &im->cache_entry;
slice->len = 0;
slice->mem = NULL;
// FIXME: implement planes support (YUV, RGB565, ETC1+Alpha) // FIXME: implement planes support (YUV, RGB565, ETC1+Alpha)
// FIXME: implement YUV support (im->cs.data) // FIXME: implement YUV support (im->cs.data)
if (plane)
{
ERR("planar formats support not implemented yet!");
return EINA_FALSE;
}
if (!im->image.data) if (!im->image.data)
{ {
int error = evas_cache_image_load_data(ie); int error = evas_cache_image_load_data(ie);
if (error != EVAS_LOAD_ERROR_NONE) if (error != EVAS_LOAD_ERROR_NONE)
return NULL; return EINA_FALSE;
} }
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_COW) if (mode & EFL_GFX_BUFFER_ACCESS_MODE_COW)
@ -1490,7 +1500,7 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
{ {
ERR("invalid region for colorspace %d: %dx%d + %d,%d, image: %dx%d", ERR("invalid region for colorspace %d: %dx%d + %d,%d, image: %dx%d",
cspace, w, h, x, y, ie->w, ie->h); cspace, w, h, x, y, ie->w, ie->h);
return NULL; return EINA_FALSE;
} }
src_stride = _evas_common_rgba_image_data_offset(ie->w, 0, 0, 0, 0, im); src_stride = _evas_common_rgba_image_data_offset(ie->w, 0, 0, 0, 0, im);
@ -1502,7 +1512,7 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
{ {
ERR("can't map shared image data multiple times with " ERR("can't map shared image data multiple times with "
"different COW flag"); "different COW flag");
return NULL; return EINA_FALSE;
} }
} }
@ -1510,7 +1520,7 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
if (cow) if (cow)
{ {
ie = evas_cache_image_alone(ie); ie = evas_cache_image_alone(ie);
if (!ie) return NULL; if (!ie) return EINA_FALSE;
im = (RGBA_Image *) ie; im = (RGBA_Image *) ie;
*image = im; *image = im;
} }
@ -1519,7 +1529,7 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
if (to_write && (ie->references > 1)) if (to_write && (ie->references > 1))
{ {
ERR("write map requires COW flag for shared images"); ERR("write map requires COW flag for shared images");
return NULL; return EINA_FALSE;
} }
} }
@ -1535,11 +1545,11 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
int dst_stride, dst_len, dst_offset = 0; int dst_stride, dst_len, dst_offset = 0;
cs_func = efl_draw_convert_func_get(ie->space, cspace, &can_region); cs_func = efl_draw_convert_func_get(ie->space, cspace, &can_region);
if (!cs_func) return NULL; if (!cs_func) return EINA_FALSE;
// make sure we can convert back, if map for writing // make sure we can convert back, if map for writing
if (to_write && !efl_draw_convert_func_get(cspace, ie->space, NULL)) if (to_write && !efl_draw_convert_func_get(cspace, ie->space, NULL))
return NULL; return EINA_FALSE;
if (can_region) if (can_region)
{ {
@ -1568,20 +1578,20 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
dst_len = rh * dst_stride; dst_len = rh * dst_stride;
data = malloc(dst_len); data = malloc(dst_len);
if (!data) return NULL; if (!data) return EINA_FALSE;
if (!cs_func(data, src_data, rw, rh, src_stride, dst_stride, ie->flags.alpha, ie->space, cspace)) if (!cs_func(data, src_data, rw, rh, src_stride, dst_stride, ie->flags.alpha, ie->space, cspace))
{ {
ERR("color conversion failed"); ERR("color conversion failed");
free(data); free(data);
return NULL; return EINA_FALSE;
} }
map = calloc(1, sizeof(*map)); map = calloc(1, sizeof(*map));
if (!map) if (!map)
{ {
free(data); free(data);
return NULL; return EINA_FALSE;
} }
map->allocated = EINA_TRUE; map->allocated = EINA_TRUE;
map->cspace = cspace; map->cspace = cspace;
@ -1603,7 +1613,7 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
// no copy // no copy
int end_offset = _evas_common_rgba_image_data_offset(x + w, y + h, 0, 0, 0, im) - src_stride; int end_offset = _evas_common_rgba_image_data_offset(x + w, y + h, 0, 0, 0, im) - src_stride;
map = calloc(1, sizeof(*map)); map = calloc(1, sizeof(*map));
if (!map) return NULL; if (!map) return EINA_FALSE;
map->baseptr = im->image.data8; map->baseptr = im->image.data8;
map->slice.mem = im->image.data8 + src_offset; map->slice.mem = im->image.data8 + src_offset;
@ -1614,12 +1624,12 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
// copy // copy
int size = _evas_common_rgba_image_data_offset(w, h, 0, 0, 0, im); int size = _evas_common_rgba_image_data_offset(w, h, 0, 0, 0, im);
data = malloc(size); data = malloc(size);
if (!data) return NULL; if (!data) return EINA_FALSE;
map = calloc(1, sizeof(*map)); map = calloc(1, sizeof(*map));
if (!map) if (!map)
{ {
free(data); free(data);
return NULL; return EINA_FALSE;
} }
memcpy(data, im->image.data8 + src_offset, size); memcpy(data, im->image.data8 + src_offset, size);
@ -1639,7 +1649,9 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
im->maps = (RGBA_Image_Data_Map *) im->maps = (RGBA_Image_Data_Map *)
eina_inlist_prepend(EINA_INLIST_GET(im->maps), EINA_INLIST_GET(map)); eina_inlist_prepend(EINA_INLIST_GET(im->maps), EINA_INLIST_GET(map));
if (stride) *stride = map->stride; if (stride) *stride = map->stride;
return &map->slice; slice->mem = map->slice.mem;
slice->len = map->slice.len;
return EINA_TRUE;
} }
static void static void
@ -1693,7 +1705,7 @@ eng_image_data_unmap(void *engdata EINA_UNUSED, void *image, const Eina_Rw_Slice
RGBA_Image_Data_Map *map; RGBA_Image_Data_Map *map;
RGBA_Image *im = image; RGBA_Image *im = image;
if (!im || !slice) if (!(image && slice))
return EINA_FALSE; return EINA_FALSE;
EINA_INLIST_FOREACH(EINA_INLIST_GET(im->maps), map) EINA_INLIST_FOREACH(EINA_INLIST_GET(im->maps), map)

View File

@ -659,15 +659,13 @@ START_TEST(evas_object_image_map_unmap)
{ {
Evas *e = _setup_evas(); Evas *e = _setup_evas();
Evas_Object *o, *o2; Evas_Object *o, *o2;
void *data; int stride, w, h, rx, ry, rw, rh;
int len, stride;
int w, h, rx, ry, rw, rh;
Efl_Gfx_Colorspace cs; Efl_Gfx_Colorspace cs;
Eina_Tmpstr *tmp; Eina_Tmpstr *tmp;
int fd; int fd;
uint32_t *data32; uint32_t *data32;
uint8_t *data8;
Eina_Bool all_white = 1, all_transparent = 1; Eina_Bool all_white = 1, all_transparent = 1;
Eina_Rw_Slice slice;
const char *imgpath = TESTS_IMG_DIR "/Pic4.png"; const char *imgpath = TESTS_IMG_DIR "/Pic4.png";
@ -682,26 +680,23 @@ START_TEST(evas_object_image_map_unmap)
rh = (h / 2) & ~3; rh = (h / 2) & ~3;
// same cspace, full image // same cspace, full image
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, cs, &stride); fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, cs, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// same cspace, partial image // same cspace, partial image
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, cs, &stride); fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, cs, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// argb cspace, full image // argb cspace, full image
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, &stride); fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
data32 = data; data32 = slice.mem;
for (int k = 0; (k < len) && (all_white || all_transparent); k++) for (int k = 0; (k < slice.len) && (all_white || all_transparent); k++)
{ {
if (data32[k]) if (data32[k])
all_transparent = 0; all_transparent = 0;
@ -709,49 +704,45 @@ START_TEST(evas_object_image_map_unmap)
all_white = 0; all_white = 0;
} }
fail_if(all_white || all_transparent); fail_if(all_white || all_transparent);
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// argb cspace, partial image // argb cspace, partial image
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, &stride); fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// argb cspace, partial image, write // argb cspace, partial image, write
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, &stride); fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
data32 = data; data32 = slice.mem;
for (int y = 0; y < rh; y += 2) for (int y = 0; y < rh; y += 2)
for (int x = 0; x < rw; x++) for (int x = 0; x < rw; x++)
{ {
data32[y*stride/4 + x] = 0xFF00FF00; data32[y*stride/4 + x] = 0xFF00FF00;
data32[(y+1)*stride/4 + x] = 0xFFFF0000; data32[(y+1)*stride/4 + x] = 0xFFFF0000;
} }
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// argb cspace, partial image, write // argb cspace, partial image, write
data = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ| EFL_GFX_BUFFER_ACCESS_MODE_WRITE, fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ| EFL_GFX_BUFFER_ACCESS_MODE_WRITE,
rx, ry, rw, rh / 2, EFL_GFX_COLORSPACE_GRY8, &stride); rx, ry, rw, rh / 2, EFL_GFX_COLORSPACE_GRY8, 0, &stride));
fail_if(!data); fail_if(!slice.len || !slice.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
data8 = data;
for (int y = 0; y < rh / 4; y++) for (int y = 0; y < rh / 4; y++)
for (int x = 0; x < rw; x++) for (int x = 0; x < rw; x++)
data8[y*stride + x] = x & 0xFF; slice.bytes[y*stride + x] = x & 0xFF;
efl_gfx_buffer_unmap(o, data, len); efl_gfx_buffer_unmap(o, &slice);
// save file, verify its pixels // save file, verify its pixels
fd = eina_file_mkstemp("/tmp/evas-test.XXXXXX.png", &tmp); fd = eina_file_mkstemp("/tmp/evas-test.XXXXXX.png", &tmp);
close(fd); close(fd);
if (efl_file_save(o, tmp, NULL, NULL)) if (efl_file_save(o, tmp, NULL, NULL))
{ {
int w2, h2, stride2, len2; Eina_Rw_Slice sorig, sdest;
uint32_t *data2, *orig; int w2, h2, stride2, x, y;
int x, y; uint32_t *dest, *orig;
o2 = efl_add(EFL_CANVAS_IMAGE_CLASS, e); o2 = efl_add(EFL_CANVAS_IMAGE_CLASS, e);
efl_file_set(o2, tmp, NULL); efl_file_set(o2, tmp, NULL);
@ -763,20 +754,21 @@ START_TEST(evas_object_image_map_unmap)
fail_if(w2 != w); fail_if(w2 != w);
fail_if(h2 != h); fail_if(h2 != h);
orig = efl_gfx_buffer_map(o, &len, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, &stride); fail_if(!efl_gfx_buffer_map(o, &sorig, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
fail_if(!orig); fail_if(!sorig.len || !sorig.mem);
fail_if(!len);
fail_if(!stride); fail_if(!stride);
data2 = efl_gfx_buffer_map(o2, &len2, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w2, h2, EFL_GFX_COLORSPACE_ARGB8888, &stride2); fail_if(!efl_gfx_buffer_map(o2, &sdest, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w2, h2, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride2));
fail_if(!data2); fail_if(sorig.len != sdest.len);
fail_if(len2 != len);
fail_if(stride2 != stride); fail_if(stride2 != stride);
dest = sdest.mem;
orig = sorig.mem;
// first quarter: same image // first quarter: same image
for (y = 0; y < h / 4; y++) for (y = 0; y < h / 4; y++)
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
fail_if(orig[y*stride/4 + x] != data2[y*stride2/4+x], "pixels differ [1]"); fail_if(orig[y*stride/4 + x] != dest[y*stride2/4+x], "pixels differ [1]");
// middle zone top: grey gradient // middle zone top: grey gradient
for (y = ry; y < (ry + rh / 4); y++) for (y = ry; y < (ry + rh / 4); y++)
@ -784,28 +776,28 @@ START_TEST(evas_object_image_map_unmap)
{ {
uint32_t c = (x - rx) & 0xFF; uint32_t c = (x - rx) & 0xFF;
c = 0xFF000000 | (c << 16) | (c << 8) | c; c = 0xFF000000 | (c << 16) | (c << 8) | c;
fail_if(data2[y*stride/4 + x] != c, "pixels differ [2]"); fail_if(dest[y*stride/4 + x] != c, "pixels differ [2]");
} }
// middle zone: grey image // middle zone: grey image
for (y = (ry + rh / 4 + 1); y < (ry + rh / 2); y++) for (y = (ry + rh / 4 + 1); y < (ry + rh / 2); y++)
for (x = rx; x < rx + rw; x++) for (x = rx; x < rx + rw; x++)
{ {
uint32_t c = data2[y*stride/4 + x] & 0xFF; uint32_t c = dest[y*stride/4 + x] & 0xFF;
c = 0xFF000000 | (c << 16) | (c << 8) | c; c = 0xFF000000 | (c << 16) | (c << 8) | c;
fail_if(data2[y*stride/4 + x] != c, "pixels differ [2bis]"); fail_if(dest[y*stride/4 + x] != c, "pixels differ [2bis]");
} }
// next lines: green & red // next lines: green & red
y = ry + rh / 2; y = ry + rh / 2;
for (x = rx; x < rx + rw; x++) for (x = rx; x < rx + rw; x++)
{ {
fail_if(data2[y*stride/4 + x] != 0xFF00FF00, "pixels differ [3]"); fail_if(dest[y*stride/4 + x] != 0xFF00FF00, "pixels differ [3]");
fail_if(data2[(y+1)*stride/4 + x] != 0xFFFF0000, "pixels differ [4]"); fail_if(dest[(y+1)*stride/4 + x] != 0xFFFF0000, "pixels differ [4]");
} }
efl_gfx_buffer_unmap(o, orig, len); efl_gfx_buffer_unmap(o, &sorig);
efl_gfx_buffer_unmap(o2, data2, len2); efl_gfx_buffer_unmap(o2, &sdest);
} }
else unlink(tmp); else unlink(tmp);
eina_tmpstr_del(tmp); eina_tmpstr_del(tmp);