forked from enlightenment/efl
ector buffer: add COW access mode
In case you map a buffer once for read-only and once for write, we can generate a temporary copy and return that instead. This buffer will be copied back to the original surface once the COW surface is unmapped.
This commit is contained in:
parent
5e075c193c
commit
1f25b523b4
|
@ -10,9 +10,10 @@ enum Ector.Buffer.Flag {
|
|||
}
|
||||
|
||||
enum Ector.Buffer.Access_Flag {
|
||||
none = 0x0,
|
||||
read = 0x1,
|
||||
write = 0x2,
|
||||
none = 0x0,
|
||||
read = 0x1,
|
||||
write = 0x2,
|
||||
cow = 0x4, [[Forces copy-on-write if already mapped as read-only. Requires write.]]
|
||||
}
|
||||
|
||||
mixin Ector.Generic.Buffer
|
||||
|
@ -62,7 +63,7 @@ mixin Ector.Generic.Buffer
|
|||
[[Unmap a region of this buffer, and upload data to the GPU (if needed).]]
|
||||
params {
|
||||
@in data: void*; [[Data pointer returned by a previous call to map]]
|
||||
@in length: uint; [[Must be the same as returned
|
||||
@in length: uint; [[Must be the same as returned by map.]]
|
||||
}
|
||||
}
|
||||
pixels_set {
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
typedef struct _Ector_Software_Buffer_Map
|
||||
{
|
||||
EINA_INLIST;
|
||||
void *ptr;
|
||||
uint8_t *ptr;
|
||||
unsigned int size; // in bytes
|
||||
unsigned int x, y, w, h;
|
||||
Efl_Gfx_Colorspace cspace;
|
||||
Eina_Bool allocated;
|
||||
Ector_Buffer_Access_Flag mode;
|
||||
} Ector_Software_Buffer_Map;
|
||||
|
||||
static inline int
|
||||
|
@ -84,6 +87,12 @@ _ector_software_buffer_base_ector_generic_buffer_pixels_set(Eo *obj, Ector_Softw
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (pd->internal.maps)
|
||||
{
|
||||
ERR("Can not call pixels_set when the buffer is mapped.");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
// safety check
|
||||
px = _min_stride_calc(1, cspace);
|
||||
if (px && ((unsigned long long)(uintptr_t)pixels) & (px - 1))
|
||||
|
@ -143,7 +152,8 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
|
|||
Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride)
|
||||
{
|
||||
Ector_Software_Buffer_Map *map = NULL;
|
||||
unsigned int off, k;
|
||||
Eina_Bool need_cow = EINA_FALSE;
|
||||
unsigned int off, k, dst_stride;
|
||||
|
||||
if (!w) w = pd->generic->w;
|
||||
if (!h) h = pd->generic->h;
|
||||
|
@ -158,10 +168,29 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
|
|||
if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) && !pd->writable)
|
||||
fail("Can not map a read-only buffer for writing");
|
||||
|
||||
if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) &&
|
||||
(mode & ECTOR_BUFFER_ACCESS_FLAG_COW))
|
||||
{
|
||||
EINA_INLIST_FOREACH(pd->internal.maps, map)
|
||||
if (map->mode == ECTOR_BUFFER_ACCESS_FLAG_READ)
|
||||
{
|
||||
need_cow = EINA_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
map = calloc(1, sizeof(*map));
|
||||
if (!map) fail("Out of memory");
|
||||
|
||||
map->mode = mode;
|
||||
map->cspace = cspace;
|
||||
map->x = x;
|
||||
map->y = y;
|
||||
map->w = w;
|
||||
map->h = h;
|
||||
|
||||
off = _min_stride_calc(x + pd->generic->l, pd->generic->cspace) + (pd->stride * (y + pd->generic->t));
|
||||
dst_stride = _min_stride_calc(w, cspace);
|
||||
|
||||
if (cspace != pd->generic->cspace)
|
||||
{
|
||||
|
@ -170,7 +199,6 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
|
|||
map->allocated = EINA_TRUE;
|
||||
map->ptr = malloc(map->size);
|
||||
if (!map->ptr) fail("Out of memory");
|
||||
if (stride) *stride = _min_stride_calc(w, cspace);
|
||||
|
||||
if (cspace == EFL_GFX_COLORSPACE_ARGB8888)
|
||||
{
|
||||
|
@ -180,18 +208,30 @@ _ector_software_buffer_base_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Ector_
|
|||
else
|
||||
{
|
||||
for (k = 0; k < h; k++)
|
||||
_pixels_argb_to_gry8_convert((uint8_t *) map->ptr + (k * w), (uint32_t *) (pd->pixels.u8 + off + (k * pd->stride)), w);
|
||||
_pixels_argb_to_gry8_convert(map->ptr + (k * w), (uint32_t *) (pd->pixels.u8 + off + (k * pd->stride)), w);
|
||||
}
|
||||
}
|
||||
else if (need_cow)
|
||||
{
|
||||
// copy-on-write access
|
||||
map->size = _min_stride_calc(w, cspace) * h;
|
||||
map->allocated = EINA_TRUE;
|
||||
map->ptr = malloc(map->size);
|
||||
if (!map->ptr) fail("Out of memory");
|
||||
for (k = 0; k < h; k++)
|
||||
memcpy(map->ptr + k * dst_stride, pd->pixels.u8 + x + (k + y) * pd->stride, dst_stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
// direct access, zero-copy
|
||||
map->size = (pd->stride * h) - off;
|
||||
map->ptr = pd->pixels.u8 + off;
|
||||
if (stride) *stride = pd->stride;
|
||||
dst_stride = pd->stride;
|
||||
}
|
||||
|
||||
pd->internal.maps = eina_inlist_prepend(pd->internal.maps, EINA_INLIST_GET(map));
|
||||
if (length) *length = map->size;
|
||||
if (stride) *stride = dst_stride;
|
||||
return map->ptr;
|
||||
|
||||
on_fail:
|
||||
|
@ -214,7 +254,41 @@ _ector_software_buffer_base_ector_generic_buffer_unmap(Eo *obj EINA_UNUSED, Ecto
|
|||
{
|
||||
pd->internal.maps = eina_inlist_remove(pd->internal.maps, EINA_INLIST_GET(map));
|
||||
if (map->allocated)
|
||||
free(map->ptr);
|
||||
{
|
||||
if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE)
|
||||
{
|
||||
unsigned k, dst_stride;
|
||||
|
||||
if (map->cspace != pd->generic->cspace)
|
||||
{
|
||||
if (pd->generic->cspace == EFL_GFX_COLORSPACE_ARGB8888)
|
||||
{
|
||||
for (k = 0; k < map->h; k++)
|
||||
_pixels_gry8_to_argb_convert((uint32_t *) (pd->pixels.u8 + (k + map->y) * pd->stride),
|
||||
map->ptr + (k * map->w),
|
||||
map->w);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = 0; k < map->h; k++)
|
||||
_pixels_argb_to_gry8_convert(pd->pixels.u8 + (k + map->y) * pd->stride,
|
||||
(uint32_t *) map->ptr + (k * map->w),
|
||||
map->w);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_stride = _min_stride_calc(map->w, map->cspace);
|
||||
for (k = 0; k < map->h; k++)
|
||||
{
|
||||
memcpy(pd->pixels.u8 + map->x + (k + map->y) * pd->stride,
|
||||
map->ptr + k * dst_stride,
|
||||
dst_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(map->ptr);
|
||||
}
|
||||
free(map);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue