Allow to use custom memory management functions for loaded images

Summary:
... and add imlib_create_image_using_data_and_memory_function().

For example, it allows to load an image in one process and then
pass it through shared memory to another process without extra
memory copy.

Reviewers: kwo

Differential Revision: https://phab.enlightenment.org/D10222
This commit is contained in:
Alexander Volkov 2019-09-30 19:11:31 +02:00 committed by Kim Woelders
parent 9977ac2026
commit 03665627db
19 changed files with 160 additions and 100 deletions

View File

@ -108,6 +108,7 @@ typedef int (*Imlib_Progress_Function) (Imlib_Image im, char percent,
int update_w, int update_h);
typedef void (*Imlib_Data_Destructor_Function) (Imlib_Image im,
void *data);
typedef void *(*Imlib_Image_Data_Memory_Function) (void *, size_t size);
/* *INDENT-OFF* */
#ifdef __cplusplus
@ -154,6 +155,8 @@ EAPI void imlib_context_set_color_cmya(int cyan, int magenta,
int yellow, int alpha);
EAPI void imlib_context_set_color_range(Imlib_Color_Range
color_range);
EAPI void imlib_context_set_image_data_memory_function(Imlib_Image_Data_Memory_Function
memory_function);
EAPI void imlib_context_set_progress_function(Imlib_Progress_Function
progress_function);
EAPI void imlib_context_set_progress_granularity(char
@ -190,6 +193,7 @@ EAPI void imlib_context_get_color_cmya(int *cyan, int *magenta,
int *yellow, int *alpha);
EAPI Imlib_Color *imlib_context_get_imlib_color(void);
EAPI Imlib_Color_Range imlib_context_get_color_range(void);
EAPI Imlib_Image_Data_Memory_Function imlib_context_get_image_data_memory_function(void);
EAPI Imlib_Progress_Function imlib_context_get_progress_function(void);
EAPI char imlib_context_get_progress_granularity(void);
EAPI Imlib_Image imlib_context_get_image(void);
@ -288,6 +292,9 @@ EAPI void imlib_blend_image_onto_image(Imlib_Image source_image,
EAPI Imlib_Image imlib_create_image(int width, int height);
EAPI Imlib_Image imlib_create_image_using_data(int width, int height,
DATA32 * data);
EAPI Imlib_Image imlib_create_image_using_data_and_memory_function(int width, int height,
DATA32 * data,
Imlib_Image_Data_Memory_Function func);
EAPI Imlib_Image imlib_create_image_using_copied_data(int width,
int height,
DATA32 * data);

View File

@ -96,6 +96,7 @@ struct _imlibcontext {
Imlib_Color color;
Imlib_Color_Range color_range;
Imlib_Image image;
Imlib_Image_Data_Memory_Function image_data_memory_func;
Imlib_Progress_Function progress_func;
char progress_granularity;
char dither_mask;
@ -188,6 +189,7 @@ imlib_context_new(void)
context->color.blue = 255;
context->color_range = NULL;
context->image = NULL;
context->image_data_memory_func = NULL;
context->progress_func = NULL;
context->progress_granularity = 0;
context->dither_mask = 0;
@ -1021,6 +1023,18 @@ imlib_context_get_color_range(void)
return ctx->color_range;
}
/**
* @param memory_function An image data memory management function.
*
* Sets the image data memory management function.
*/
EAPI void
imlib_context_set_image_data_memory_function(Imlib_Image_Data_Memory_Function memory_function)
{
CHECK_CONTEXT(ctx);
ctx->image_data_memory_func = memory_function;
}
/**
* @param progress_function A progress function.
*
@ -1035,6 +1049,18 @@ imlib_context_set_progress_function(Imlib_Progress_Function progress_function)
ctx->progress_func = progress_function;
}
/**
* @return The image data memory management function.
*
* Returns the current image data memeory management function being used.
*/
EAPI Imlib_Image_Data_Memory_Function
imlib_context_get_image_data_memory_function(void)
{
CHECK_CONTEXT(ctx);
return ctx->image_data_memory_func;
}
/**
* @return The current progress function.
*
@ -2082,6 +2108,37 @@ imlib_create_image_using_data(int width, int height, DATA32 * data)
return (Imlib_Image) im;
}
/**
* @param width The width of the image.
* @param height The height of the image.
* @param data The data.
* @param func The memory management function.
* @return A valid image, otherwise NULL.
*
* Creates an image from the image data specified with the width @p width and
* the height @p height specified. The image data @p data must be in the same format as
* imlib_image_get_data() would return. The memory management function @p func is
* responsible for freeing this image data once the image is freed. Imlib2 returns a
* valid image handle on success or NULL on failure.
*
**/
EAPI Imlib_Image
imlib_create_image_using_data_and_memory_function(int width, int height, DATA32 * data, Imlib_Image_Data_Memory_Function func)
{
ImlibImage *im;
CHECK_CONTEXT(ctx);
CHECK_PARAM_POINTER_RETURN("imlib_create_image_using_data_and_memory_function", "data", data,
NULL);
if (!IMAGE_DIMENSIONS_OK(width, height))
return NULL;
im = __imlib_CreateImage(width, height, data);
if (im)
im->data_memory_func = func;
return (Imlib_Image) im;
}
/**
* @param width The width of the image.
* @param height The height of the image.

View File

@ -237,6 +237,5 @@ __imlib_FilterImage(ImlibImage * im, ImlibFilter * fil)
p2++;
}
}
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}

View File

@ -27,6 +27,52 @@ static ImlibImagePixmap *pixmaps = NULL;
static ImlibLoader *loaders = NULL;
static int cache_size = 4096 * 1024;
__EXPORT__ DATA32 *
__imlib_AllocateData(ImlibImage *im, int w, int h)
{
if (im->data_memory_func)
im->data = im->data_memory_func(NULL, w * h * sizeof(DATA32));
else
im->data = malloc(w * h * sizeof(DATA32));
if (im->data)
{
im->w = w;
im->h = h;
}
return im->data;
}
__EXPORT__ void
__imlib_FreeData(ImlibImage *im)
{
if (im->data)
{
if (im->data_memory_func)
im->data_memory_func(im->data, im->w * im->h * sizeof(DATA32));
else
free(im->data);
im->data = NULL;
}
im->w = 0;
im->h = 0;
}
__EXPORT__ void
__imlib_ReplaceData(ImlibImage *im, unsigned int *new_data)
{
if (im->data)
{
if (im->data_memory_func)
im->data_memory_func(im->data, im->w * im->h * sizeof(DATA32));
else
free(im->data);
}
im->data = new_data;
im->data_memory_func = NULL;
}
/* attach a string key'd data and/or int value to an image that cna be */
/* looked up later by its string key */
__EXPORT__ void
@ -175,7 +221,7 @@ __imlib_ConsumeImage(ImlibImage * im)
if (im->key)
free(im->key);
if ((IMAGE_FREE_DATA(im)) && (im->data))
free(im->data);
__imlib_FreeData(im);
if (im->format)
free(im->format);
free(im);
@ -850,6 +896,7 @@ __imlib_LoadImageWrapper(const ImlibLoader * l, ImlibImage * im,
{
int rc;
im->data_memory_func = imlib_context_get_image_data_memory_function();
rc = l->load(im, progress, progress_granularity, immediate_load);
if (rc == 0)
{
@ -860,8 +907,7 @@ __imlib_LoadImageWrapper(const ImlibLoader * l, ImlibImage * im,
}
if (im->data)
{
free(im->data);
im->data = NULL;
__imlib_FreeData(im);
}
if (im->format)
{

View File

@ -25,6 +25,7 @@ typedef int (*ImlibProgressFunction) (ImlibImage * im, char percent,
int update_w, int update_h);
typedef void (*ImlibDataDestructorFunction) (ImlibImage * im,
void *data);
typedef void *(*ImlibImageDataMemoryFunction) (void *, size_t size);
enum _iflags {
F_NONE = 0,
@ -57,6 +58,7 @@ struct _imlibimage {
char *file;
int w, h;
DATA32 *data;
ImlibImageDataMemoryFunction data_memory_func;
ImlibImageFlags flags;
time_t moddate;
ImlibBorder border;
@ -103,6 +105,10 @@ struct _imlibloader {
ImlibLoader *next;
};
DATA32 *__imlib_AllocateData(ImlibImage * im, int w, int h);
void __imlib_FreeData(ImlibImage *im);
void __imlib_ReplaceData(ImlibImage *im, DATA32 *new_data);
void __imlib_AttachTag(ImlibImage * im, const char *key,
int val, void *data,
ImlibDataDestructorFunction destructor);

View File

@ -154,8 +154,7 @@ __imlib_FlipImageDiagonal(ImlibImage * im, int direction)
}
to += hw;
}
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}
void
@ -245,8 +244,7 @@ __imlib_BlurImage(ImlibImage * im, int rad)
free(rs);
free(gs);
free(bs);
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}
void
@ -302,8 +300,7 @@ __imlib_SharpenImage(ImlibImage * im, int rad)
}
}
}
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}
void
@ -376,8 +373,7 @@ __imlib_TileImageHoriz(ImlibImage * im)
p2++;
}
}
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}
void
@ -428,8 +424,7 @@ __imlib_TileImageVert(ImlibImage * im)
p2++;
}
}
free(im->data);
im->data = data;
__imlib_ReplaceData(im, data);
}
void

View File

@ -47,7 +47,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
char pper = 0;
/* must set the im->data member before callign progress function */
ptr = im->data = malloc(w * h * sizeof(DATA32));
ptr = __imlib_AllocateData(im, w, h);
if (!im->data)
{
im->w = 0;
@ -58,9 +58,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
{
if (fread(ptr, im->w, 4, f) != 4)
{
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
fclose(f);
return 0;
}

View File

@ -309,8 +309,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
fclose(f);
return 0;
}
im->data = malloc(w * h * sizeof(DATA32));
if (!im->data)
if (!__imlib_AllocateData(im, w, h))
{
im->w = 0;
free(buffer);
@ -320,9 +319,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
if (fread(buffer, imgsize, 1, f) != 1)
{
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
free(buffer);
fclose(f);
return 0;

View File

@ -47,12 +47,10 @@ load(ImlibImage * im, ImlibProgressFunction progress,
h = im->h;
rowlen = w * (sizeof("RGBA") - 1);
if (!(im->data = malloc(rowlen * h)) ||
if (!(__imlib_AllocateData(im, w, h)) ||
!(row = malloc(rowlen * sizeof(uint16_t))))
{
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
free(row);
fclose(f);
return 0;
@ -63,9 +61,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
{
if (fread(row, sizeof(uint16_t), rowlen, f) != rowlen)
{
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
free(row);
fclose(f);
return 0;

View File

@ -150,8 +150,8 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
colormap[transp] = bg >= 0 && bg < 256 ?
colormap[bg] & 0x00ffffff : 0x00000000;
}
im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h);
if (!im->data)
if (!__imlib_AllocateData(im, w, h))
goto quit;
ptr = im->data;
@ -195,11 +195,8 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
#endif
if (rc == 0)
{
free(im->data);
im->data = NULL;
im->w = 0;
}
__imlib_FreeData(im);
return rc;
}

View File

@ -315,14 +315,11 @@ ico_load(ico_t * ico, ImlibImage * im)
if (w <= 0 || h <= 0)
return 0;
im->data = malloc(sizeof(DATA32) * w * h);
if (!im->data)
if (!__imlib_AllocateData(im, w, h))
return 0;
D("Loading icon %d: WxHxD=%dx%dx%d\n", ic, w, h, ie->bih.bpp);
im->w = w;
im->h = h;
SET_FLAG(im->flags, F_HAS_ALPHA);
cmap = ie->cmap;
@ -427,8 +424,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
error:
ico_delete(ico);
free(im->data);
im->data = NULL;
__imlib_FreeData(im);
return 0;
}

View File

@ -97,7 +97,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
goto quit_error;
/* must set the im->data member before callign progress function */
ptr2 = im->data = malloc(w * h * sizeof(DATA32));
ptr2 = __imlib_AllocateData(im, w, h);
if (!im->data)
goto quit_error;
@ -180,9 +180,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
quit_error:
rc = 0; /* Error */
free(im->data);
im->data = NULL;
im->w = im->h = 0;
__imlib_FreeData(im);
goto quit;
}

View File

@ -542,7 +542,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
plane[0] = NULL;
gran = nexty = 0;
im->data = malloc(im->w * im->h * sizeof(DATA32));
__imlib_AllocateData(im, im->w, im->h);
n = ilbm.depth;
if (ilbm.mask == 1)
n++;
@ -595,12 +595,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
* the memory for im->data or plane[0].
*----------*/
if (!ok)
{
im->w = im->h = 0;
if (im->data)
free(im->data);
im->data = NULL;
}
__imlib_FreeData(im);
if (plane[0])
free(plane[0]);

View File

@ -134,10 +134,8 @@ load(ImlibImage * im, ImlibProgressFunction progress,
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
#endif
im->data = malloc(w * h * sizeof(DATA32));
if (!im->data)
if (!__imlib_AllocateData(im, w, h))
{
im->w = 0;
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(f);
return 0;
@ -146,9 +144,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
if (!lines)
{
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(f);
return 0;

View File

@ -138,7 +138,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
char pper = 0;
/* must set the im->data member before callign progress function */
ptr2 = im->data = malloc(w * h * sizeof(DATA32));
ptr2 = __imlib_AllocateData(im, w, h);
if (!im->data)
goto quit_error;
@ -427,11 +427,8 @@ load(ImlibImage * im, ImlibProgressFunction progress,
quit:
fclose(f);
if (rc == 0)
{
free(im->data);
im->data = NULL;
im->w = 0;
}
__imlib_FreeData(im);
return rc;
}

View File

@ -311,8 +311,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
int y;
/* allocate the destination buffer */
im->data = malloc(im->w * im->h * sizeof(DATA32));
if (!im->data)
if (!__imlib_AllocateData(im, im->w, im->h))
{
munmap(seg, ss.st_size);
im->w = 0;
@ -357,9 +356,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
if (bufptr + bpp / 8 > bufend)
{
munmap(seg, ss.st_size);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
close(fd);
return 0;
}
@ -419,9 +416,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
if ((bufptr + 1 + (bpp / 8)) > bufend)
{
munmap(seg, ss.st_size);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
close(fd);
return 0;
}
@ -484,9 +479,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
if ((bufptr + bpp / 8) > bufend)
{
munmap(seg, ss.st_size);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
close(fd);
return 0;
}

View File

@ -342,17 +342,14 @@ load(ImlibImage * im, ImlibProgressFunction progress,
rgba_image.pper = rgba_image.py = 0;
rgba_image.progress_granularity = progress_granularity;
rast = (uint32 *) _TIFFmalloc(sizeof(uint32) * num_pixels);
im->data = (DATA32 *) malloc(sizeof(DATA32) * num_pixels);
if ((!rast) || (!im->data)) /* Error checking */
if ((!rast) || (!__imlib_AllocateData(im, im->w, im->h))) /* Error checking */
{
fprintf(stderr, "imlib2-tiffloader: Out of memory\n");
if (rast)
_TIFFfree(rast);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
goto quit2;
}
@ -361,9 +358,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
fprintf(stderr, "imlib2-tiffloader: No put function");
_TIFFfree(rast);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
goto quit2;
}
@ -382,9 +377,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
rgba_image.rgba.width, rgba_image.rgba.height))
{
_TIFFfree(rast);
free(im->data);
im->data = NULL;
im->w = 0;
__imlib_FreeData(im);
goto quit2;
}

View File

@ -98,14 +98,13 @@ load(ImlibImage * im, ImlibProgressFunction progress,
{
size_t webp_buffer_size = sizeof(DATA32) * im->w * im->h;
im->data = malloc(webp_buffer_size);
__imlib_AllocateData(im, im->w, im->h);
if (WebPDecodeBGRAInto(encoded_data, stats.st_size,
(uint8_t *) im->data, webp_buffer_size,
im->w * 4) == NULL)
{
free(im->data);
im->data = NULL;
free(encoded_data);
__imlib_FreeData(im);
return 0;
}

View File

@ -214,9 +214,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
if (im->loader || immediate_load || progress)
{
im->data =
(DATA32 *) malloc(sizeof(DATA32) * im->w * im->h);
if (!im->data)
if (!__imlib_AllocateData(im, im->w, im->h))
goto quit;
ptr = im->data;
pixels = w * h;
@ -448,11 +446,8 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
quit:
if (rc == 0)
{
free(im->data);
im->data = NULL;
im->w = im->h = 0;
}
__imlib_FreeData(im);
fclose(f);
free(cmap);
free(line);