efl/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c

261 lines
7.4 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/* this one is read-only buffer wrapping an existing evas_gl_image */
#define ECTOR_GL_BUFFER_BASE_PROTECTED
#include "evas_common_private.h"
#include "evas_gl_private.h"
#include <gl/Ector_GL.h>
#include "gl/ector_gl_private.h"
#include "evas_common_private.h"
#include "../gl_common/evas_gl_common.h"
#include "evas_private.h"
#include "ector_buffer.h"
#include "Evas_Engine_GL_Generic.h"
#include "evas_ector_buffer.eo.h"
#include "evas_ector_gl_buffer.eo.h"
#include "evas_ector_gl_image_buffer.eo.h"
#define MY_CLASS EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS
typedef struct _Ector_GL_Buffer_Map Ector_GL_Buffer_Map;
typedef struct _Evas_Ector_GL_Image_Buffer_Data Evas_Ector_GL_Image_Buffer_Data;
struct _Ector_GL_Buffer_Map
{
EINA_INLIST;
void *ptr;
unsigned int base_size; // in bytes
unsigned int x, y, w, h;
void *image_data, *base_data;
size_t length;
Efl_Gfx_Colorspace cspace;
Evas_GL_Image *im;
Eina_Bool allocated, free_image;
Ector_Buffer_Access_Flag mode;
};
struct _Evas_Ector_GL_Image_Buffer_Data
{
Evas_Public_Data *evas;
Evas_GL_Image *glim;
Ector_GL_Buffer_Map *maps;
};
#define ENFN pd->evas->engine.func
#define ENDT pd->evas->engine.data.output
// testing out some macros to maybe add to eina
#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0)
#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0)
/* FIXME: Conversion routines don't belong here */
static inline void
_pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len)
{
int k;
for (k = 0; k < len; k++)
{
const uint32_t *s = src++;
*dst++ = A_VAL(s);
}
}
EOLIAN static void
_evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd,
Evas *evas, void *image)
{
Evas_GL_Image *im = image;
EINA_SAFETY_ON_FALSE_RETURN(!pd->glim);
EINA_SAFETY_ON_NULL_RETURN(im);
pd->evas = efl_data_xref(evas, EVAS_CANVAS_CLASS, obj);
evas_gl_common_image_ref(im);
pd->glim = im;
}
EOLIAN static void *
_evas_ector_gl_image_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd)
{
evas_gl_common_image_ref(pd->glim);
return pd->glim;
}
EOLIAN static Eina_Bool
_evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_release(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd,
void *image)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->glim == image, EINA_FALSE);
evas_gl_common_image_free(pd->glim);
return EINA_TRUE;
}
EOLIAN static Ector_Buffer_Flag
_evas_ector_gl_image_buffer_ector_buffer_flags_get(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd EINA_UNUSED)
{
return ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_DRAWABLE;
}
EOLIAN static void
_evas_ector_gl_image_buffer_ector_buffer_size_get(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd,
int *w, int *h)
{
if (w) *w = pd->glim->w;
if (h) *h = pd->glim->h;
}
EOLIAN static Efl_Gfx_Colorspace
_evas_ector_gl_image_buffer_ector_buffer_cspace_get(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd EINA_UNUSED)
{
return EFL_GFX_COLORSPACE_ARGB8888;
}
EOLIAN static void *
_evas_ector_gl_image_buffer_ector_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd, unsigned int *length,
Ector_Buffer_Access_Flag mode,
unsigned int x, unsigned int y, unsigned int w, unsigned int h,
Efl_Gfx_Colorspace cspace, unsigned int *stride)
{
Ector_GL_Buffer_Map *map = NULL;
Eina_Bool tofree = EINA_FALSE;
Evas_GL_Image *im = NULL;
unsigned int W, H;
int len, err;
uint32_t *data;
int pxs;
if ((cspace != EFL_GFX_COLORSPACE_GRY8) && (cspace != EFL_GFX_COLORSPACE_ARGB8888))
{
ERR("Unsupported colorspace for map: %d", (int) cspace);
return NULL;
}
if (mode == EFL_GFX_BUFFER_ACCESS_MODE_NONE)
{
ERR("Invalid access mode for map (none)");
return NULL;
}
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
{
ERR("%s does not support write access for map", efl_class_name_get(MY_CLASS));
return NULL;
}
W = pd->glim->w;
H = pd->glim->h;
if (!w) w = W - x;
if (!h) h = H - y;
if ((x + w > W) || (y + h > H)) return NULL;
im = ENFN->image_data_get(ENDT, pd->glim, EINA_FALSE, &data, &err, &tofree);
if (!im) return NULL;
map = calloc(1, sizeof(*map));
map->mode = mode;
map->cspace = cspace;
map->x = x;
map->y = y;
map->w = w;
map->h = h;
map->image_data = data;
map->im = im;
map->free_image = tofree;
len = W * H;
if (cspace == EFL_GFX_COLORSPACE_GRY8)
{
uint8_t *data8 = malloc(len);
if (!data8) goto fail;
_pixels_argb_to_gry8_convert(data8, data, len);
map->allocated = EINA_TRUE;
map->base_data = data8;
map->ptr = data8 + x + (y * W);
pxs = 1;
}
else
{
map->allocated = EINA_FALSE;
map->base_data = data;
map->ptr = data + x + (y * W);
pxs = 4;
}
map->base_size = len * pxs;
map->length = (W * h + w - W) * pxs;
if (stride) *stride = W * pxs;
if (length) *length = map->length;
if (!tofree)
pd->glim = im;
EINA_INLIST_APPEND(pd->maps, map);
return map->ptr;
fail:
free(map);
return NULL;
}
EOLIAN static void
_evas_ector_gl_image_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED,
Evas_Ector_GL_Image_Buffer_Data *pd,
void *data, unsigned int length)
{
Ector_GL_Buffer_Map *map;
if (!data) return;
EINA_INLIST_FOREACH(pd->maps, map)
{
if ((map->base_data == data) && (map->length == length))
{
EINA_INLIST_REMOVE(pd->maps, map);
if (map->free_image)
ENFN->image_free(ENDT, map->im);
else
ENFN->image_data_put(ENDT, map->im, map->image_data);
if (map->allocated)
free(map->base_data);
free(map);
return;
}
}
ERR("Tried to unmap a non-mapped region: %p +%u", data, length);
}
EOLIAN static Efl_Object *
_evas_ector_gl_image_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd)
{
if (!pd->glim)
{
ERR("Buffer was not initialized properly!");
return NULL;
}
return efl_finalize(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_evas_ector_gl_image_buffer_efl_object_destructor(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd)
{
evas_gl_common_image_free(pd->glim);
efl_data_xunref(pd->evas->evas, pd->evas, obj);
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "evas_ector_gl_image_buffer.eo.c"