evas: Use Eina.Slice on the stack (gfx.buffer)

This commit is contained in:
Jean-Philippe Andre 2017-09-18 19:59:11 +09:00
parent 1f242afdef
commit 2df8ad36b4
7 changed files with 89 additions and 108 deletions

View File

@ -84,10 +84,10 @@ _animate_scene(void *data)
#ifdef USE_EO_IMAGE
Eina_Rw_Slice slice;
if (!efl_gfx_buffer_map(source, &slice, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, NULL,
EFL_GFX_COLORSPACE_ARGB8888, 0, &stride))
return EINA_TRUE;
slice = efl_gfx_buffer_map(source, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, NULL,
EFL_GFX_COLORSPACE_ARGB8888, 0, &stride);
pixels = slice.mem;
if (!pixels) return EINA_TRUE;
#else
pixels = evas_object_image_data_get(source, EINA_TRUE);
stride = evas_object_image_stride_get(source);
@ -104,7 +104,7 @@ _animate_scene(void *data)
}
#ifdef USE_EO_IMAGE
efl_gfx_buffer_unmap(source, &slice);
efl_gfx_buffer_unmap(source, slice);
efl_gfx_buffer_update_add(source, NULL);
#else
evas_object_image_data_set(source, pixels);

View File

@ -129,7 +129,6 @@ interface Efl.Gfx.Buffer ()
be negative.
]]
params {
@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,
write-only or read-write access (OR combination of flags).]]
@in region: const(ptr(Eina.Rect)) @optional; [[The region to map.]]
@ -139,7 +138,8 @@ interface Efl.Gfx.Buffer ()
@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]]
}
return: bool; [[$true on success, $false otherwise]]
return: Eina.Rw_Slice; [[The data slice. In case of failure, the
memory pointer will be $null.]]
}
buffer_unmap {
[[Unmap a region of this buffer, and update the internal data if needed.
@ -152,7 +152,7 @@ interface Efl.Gfx.Buffer ()
valid anymore.
]]
params {
@in slice: ptr(const(Eina.Rw_Slice)); [[Data slice returned by a previous call to map.]]
@in slice: Eina.Rw_Slice; [[Data slice returned by a previous call to map.]]
}
return: bool; [[$true on success, $false otherwise]]
}
@ -211,14 +211,14 @@ interface Efl.Gfx.Buffer ()
[[Get a direct pointer to the internal pixel data, if available.
This will return $null unless @.buffer_managed_set was used to pass
in an external data pointer. The returned @Eina.Slice struct must be
freed by the caller.
in an external data pointer.
]]
params {
@out slice: Eina.Slice; [[Data slice]]
@in plane: int @optional; [[Plane ID. 0 by default. Useful for planar formats only.]]
@in plane: int @optional; [[Plane ID. 0 by default. Useful for
planar formats only.]]
}
return: bool; [[$true on success, $false otherwise]]
return: Eina.Slice; [[The data slice. The memory pointer will be $null
in case of failure.]]
}
/* Note: border, span and buffer flags not imported from ector buffer */
}

View File

@ -3290,9 +3290,9 @@ _elm_win_xwin_update(Efl_Ui_Win_Data *sd)
unmap = EINA_TRUE;
rect.size = efl_gfx_buffer_size_get(image);
efl_gfx_buffer_map(image, &sl, EFL_GFX_BUFFER_ACCESS_MODE_READ,
&rect, EFL_GFX_COLORSPACE_ARGB8888, 0,
&stride);
sl = efl_gfx_buffer_map(image, EFL_GFX_BUFFER_ACCESS_MODE_READ,
&rect, EFL_GFX_COLORSPACE_ARGB8888, 0,
&stride);
w = rect.w;
h = rect.h;
}
@ -3340,7 +3340,7 @@ _elm_win_xwin_update(Efl_Ui_Win_Data *sd)
}
}
}
if (unmap) efl_gfx_buffer_unmap(image, &sl);
if (unmap) efl_gfx_buffer_unmap(image, sl);
else evas_object_image_data_set(image, sl.mem);
}
}

View File

@ -758,28 +758,24 @@ _efl_canvas_image_efl_gfx_buffer_buffer_copy_set(Eo *eo_obj, void *_pd EINA_UNUS
return _image_pixels_set(obj, o, slice, size.w, size.h, stride, cspace, plane, EINA_TRUE);
}
EOLIAN static Eina_Bool
EOLIAN static Eina_Slice
_efl_canvas_image_efl_gfx_buffer_buffer_managed_get(Eo *eo_obj, void *_pd EINA_UNUSED EINA_UNUSED,
Eina_Slice *slice, int plane)
int plane)
{
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_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
Eina_Slice slice = {};
if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_direct_get)
return EINA_FALSE;
return slice;
return ENFN->image_data_direct_get(ENC, o->engine_data, plane, slice, &cspace, EINA_FALSE);
ENFN->image_data_direct_get(ENC, o->engine_data, plane, &slice, &cspace, EINA_FALSE);
return slice;
}
EOLIAN static Eina_Bool
EOLIAN static Eina_Rw_Slice
_efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode,
const Eina_Rect *region,
Efl_Gfx_Colorspace cspace,
@ -788,14 +784,9 @@ _efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
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);
int s = 0, width = 0, height = 0;
Eina_Bool ret = EINA_FALSE;
Eina_Rw_Slice slice = {};
int x, y, w, h;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!ENFN->image_data_map)
goto end; // not implemented
@ -831,30 +822,29 @@ _efl_canvas_image_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
goto end;
}
if (ENFN->image_data_map(ENC, &o->engine_data, slice, &s, x, y, w, h, cspace, mode, plane))
if (ENFN->image_data_map(ENC, &o->engine_data, &slice, &s, x, y, w, h, cspace, mode, plane))
{
DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));
ret = EINA_TRUE;
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(slice));
}
else DBG("map(%p, %d,%d %dx%d plane:%d) -> (null)", eo_obj, x, y, w, h, plane);
end:
if (stride) *stride = s;
return ret;
return slice;
}
EOLIAN static Eina_Bool
_efl_canvas_image_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED,
const Eina_Rw_Slice *slice)
Eina_Rw_Slice slice)
{
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);
if (!slice || !ENFN->image_data_unmap || !o->engine_data)
if (!slice.mem || !ENFN->image_data_unmap || !o->engine_data)
return EINA_FALSE;
if (!ENFN->image_data_unmap(ENC, o->engine_data, slice))
if (!ENFN->image_data_unmap(ENC, o->engine_data, &slice))
return EINA_FALSE;
return EINA_TRUE;

View File

@ -259,9 +259,8 @@ _proxy_image_get(Evas_Image_Data *o)
return source->proxy->surface;
}
EOLIAN static Eina_Bool
EOLIAN static Eina_Rw_Slice
_efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode,
const Eina_Rect *region,
Efl_Gfx_Colorspace cspace, int plane,
@ -270,15 +269,10 @@ _efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
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);
int s = 0, width = 0, height = 0;
Eina_Bool ret = EINA_FALSE;
Eina_Rw_Slice slice = {};
int x, y, w, h;
void *image;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!ENFN->image_data_map)
goto end; // not implemented
@ -327,30 +321,29 @@ _efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
goto end;
}
if (ENFN->image_data_map(ENC, &o->engine_data, slice, &s, x, y, w, h, cspace, mode, plane))
if (ENFN->image_data_map(ENC, &o->engine_data, &slice, &s, x, y, w, h, cspace, mode, plane))
{
DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));
ret = EINA_TRUE;
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(slice));
}
else DBG("map(%p, %d,%d %dx%d plane:%d) -> (null)", eo_obj, x, y, w, h, plane);
end:
if (stride) *stride = s;
return ret;
return slice;
}
EOLIAN static Eina_Bool
_efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED,
const Eina_Rw_Slice *slice)
const Eina_Rw_Slice slice)
{
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);
if (!slice || !ENFN->image_data_unmap || !o->engine_data)
if (!slice.mem || !ENFN->image_data_unmap || !o->engine_data)
return EINA_FALSE;
if (!ENFN->image_data_unmap(ENC, o->engine_data, slice))
if (!ENFN->image_data_unmap(ENC, o->engine_data, &slice))
return EINA_FALSE;
return EINA_TRUE;

View File

@ -208,9 +208,8 @@ _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);
}
EOLIAN static Eina_Bool
EOLIAN static Eina_Rw_Slice
_efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
Eina_Rw_Slice *slice,
Efl_Gfx_Buffer_Access_Mode mode,
const Eina_Rect *region,
Efl_Gfx_Colorspace cspace, int plane,
@ -222,28 +221,24 @@ _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
Evas_Canvas3D_Scene_Data *pd_scene;
int width = -1, height = -1, ntex = -1;
unsigned char *pixels = NULL;
Eina_Rw_Slice slice = {};
int x, y, w, h;
size_t len = 0;
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);
slice->len = 0;
slice->mem = NULL;
if (!o->cur->scene)
{
ERR("invalid scene data");
return EINA_FALSE;
return slice;
}
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
{
ERR("invalid map access mode");
return EINA_FALSE;
return slice;
}
if (cspace != EFL_GFX_COLORSPACE_ARGB8888)
{
ERR("invalid map colorspace. Only ARGB is supported");
return EINA_FALSE;
return slice;
}
pd_parent = efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_OBJECT_CLASS);
@ -274,7 +269,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.",
w, h, x, y, width, height);
return EINA_FALSE;
return slice;
}
if (e->engine.func->drawable_texture_target_id_get)
@ -284,29 +279,29 @@ _efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
if (e->engine.func->drawable_texture_rendered_pixels_get)
{
len = w * h * sizeof(DATA32); //four component texture
pixels = malloc(len + sizeof(*slice) + 8);
pixels = malloc(len + sizeof(slice) + 8);
e->engine.func->drawable_texture_rendered_pixels_get(ntex, x, y, w, h,
pd_scene->surface, pixels);
}
else
return EINA_FALSE;
return slice;
}
else
return EINA_FALSE;
return slice;
if (stride) *stride = w * sizeof(DATA32);
slice->mem = pixels;
slice->len = len;
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));
eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(slice));
return EINA_TRUE;
return slice;
}
EOLIAN static Eina_Bool
_efl_canvas_scene3d_efl_gfx_buffer_buffer_unmap(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED,
const Eina_Rw_Slice *slice)
const Eina_Rw_Slice slice)
{
free(slice->mem);
free(slice.mem);
return EINA_TRUE;
}

View File

@ -667,13 +667,14 @@ START_TEST(evas_object_image_map_unmap)
{
Evas *e = _setup_evas();
Evas_Object *o, *o2;
int stride, w, h, rx, ry, rw, rh;
int stride, w, h;
Efl_Gfx_Colorspace cs;
Eina_Tmpstr *tmp;
int fd;
uint32_t *data32;
Eina_Bool all_white = 1, all_transparent = 1;
Eina_Rw_Slice slice;
Eina_Rect r, r2;
const char *imgpath = TESTS_IMG_DIR "/Pic4.png";
@ -682,25 +683,25 @@ START_TEST(evas_object_image_map_unmap)
efl_gfx_view_size_get(o, &w, &h);
cs = efl_gfx_buffer_colorspace_get(o);
rx = (w / 4) & ~3;
ry = (h / 4) & ~3;
rw = (w / 2) & ~3;
rh = (h / 2) & ~3;
r.x = (w / 4) & ~3;
r.y = (h / 4) & ~3;
r.w = (w / 2) & ~3;
r.h = (h / 2) & ~3;
// same cspace, full image
fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, cs, 0, &stride));
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ, NULL, cs, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// same cspace, partial image
fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, cs, 0, &stride));
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ, &r, cs, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// argb cspace, full image
fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ, NULL, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
data32 = slice.mem;
@ -712,36 +713,38 @@ START_TEST(evas_object_image_map_unmap)
all_white = 0;
}
fail_if(all_white || all_transparent);
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// argb cspace, partial image
fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_READ, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ, &r, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// argb cspace, partial image, write
fail_if(!efl_gfx_buffer_map(o, &slice, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, rx, ry, rw, rh, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_WRITE, &r, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
data32 = slice.mem;
for (int y = 0; y < rh; y += 2)
for (int x = 0; x < rw; x++)
for (int y = 0; y < r.h; y += 2)
for (int x = 0; x < r.w; x++)
{
data32[y*stride/4 + x] = 0xFF00FF00;
data32[(y+1)*stride/4 + x] = 0xFFFF0000;
}
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// argb cspace, partial image, 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, 0, &stride));
r2 = r;
r2.h = r.h / 2;
slice = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ | EFL_GFX_BUFFER_ACCESS_MODE_WRITE,
&r2, EFL_GFX_COLORSPACE_GRY8, 0, &stride);
fail_if(!slice.len || !slice.mem);
fail_if(!stride);
for (int y = 0; y < rh / 4; y++)
for (int x = 0; x < rw; x++)
for (int y = 0; y < r.h / 4; y++)
for (int x = 0; x < r.w; x++)
slice.bytes[y*stride + x] = x & 0xFF;
efl_gfx_buffer_unmap(o, &slice);
efl_gfx_buffer_unmap(o, slice);
// save file, verify its pixels
fd = eina_file_mkstemp("/tmp/evas-test.XXXXXX.png", &tmp);
@ -762,11 +765,11 @@ START_TEST(evas_object_image_map_unmap)
fail_if(w2 != w);
fail_if(h2 != h);
fail_if(!efl_gfx_buffer_map(o, &sorig, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w, h, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride));
sorig = efl_gfx_buffer_map(o, EFL_GFX_BUFFER_ACCESS_MODE_READ, NULL, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride);
fail_if(!sorig.len || !sorig.mem);
fail_if(!stride);
fail_if(!efl_gfx_buffer_map(o2, &sdest, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0, 0, w2, h2, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride2));
sdest = efl_gfx_buffer_map(o2, EFL_GFX_BUFFER_ACCESS_MODE_READ, NULL, EFL_GFX_COLORSPACE_ARGB8888, 0, &stride2);
fail_if(sorig.len != sdest.len);
fail_if(stride2 != stride);
@ -779,17 +782,17 @@ START_TEST(evas_object_image_map_unmap)
fail_if(orig[y*stride/4 + x] != dest[y*stride2/4+x], "pixels differ [1]");
// middle zone top: grey gradient
for (y = ry; y < (ry + rh / 4); y++)
for (x = rx; x < rx + rw; x++)
for (y = r.y; y < (r.y + r.h / 4); y++)
for (x = r.x; x < r.x + r.w; x++)
{
uint32_t c = (x - rx) & 0xFF;
uint32_t c = (x - r.x) & 0xFF;
c = 0xFF000000 | (c << 16) | (c << 8) | c;
fail_if(dest[y*stride/4 + x] != c, "pixels differ [2]");
}
// middle zone: grey image
for (y = (ry + rh / 4 + 1); y < (ry + rh / 2); y++)
for (x = rx; x < rx + rw; x++)
for (y = (r.y + r.h / 4 + 1); y < (r.y + r.h / 2); y++)
for (x = r.x; x < r.x + r.w; x++)
{
uint32_t c = dest[y*stride/4 + x] & 0xFF;
c = 0xFF000000 | (c << 16) | (c << 8) | c;
@ -797,15 +800,15 @@ START_TEST(evas_object_image_map_unmap)
}
// next lines: green & red
y = ry + rh / 2;
for (x = rx; x < rx + rw; x++)
y = r.y + r.h / 2;
for (x = r.x; x < r.x + r.w; x++)
{
fail_if(dest[y*stride/4 + x] != 0xFF00FF00, "pixels differ [3]");
fail_if(dest[(y+1)*stride/4 + x] != 0xFFFF0000, "pixels differ [4]");
}
efl_gfx_buffer_unmap(o, &sorig);
efl_gfx_buffer_unmap(o2, &sdest);
efl_gfx_buffer_unmap(o, sorig);
efl_gfx_buffer_unmap(o2, sdest);
}
else unlink(tmp);
eina_tmpstr_del(tmp);