kwo pushed a commit to branch master. http://git.enlightenment.org/legacy/imlib2.git/commit/?id=03665627dbe0e6fbf497158b2538a8d69a362617
commit 03665627dbe0e6fbf497158b2538a8d69a362617 Author: Alexander Volkov <a.vol...@rusbitech.ru> Date: Mon Sep 30 19:11:31 2019 +0200 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 --- src/lib/Imlib2.h | 7 +++++ src/lib/api.c | 57 +++++++++++++++++++++++++++++++++++++++ src/lib/filter.c | 3 +-- src/lib/image.c | 52 ++++++++++++++++++++++++++++++++--- src/lib/image.h | 6 +++++ src/lib/rgbadraw.c | 15 ++++------- src/modules/loaders/loader_argb.c | 6 ++--- src/modules/loaders/loader_bmp.c | 7 ++--- src/modules/loaders/loader_ff.c | 10 +++---- src/modules/loaders/loader_gif.c | 11 +++----- src/modules/loaders/loader_ico.c | 8 ++---- src/modules/loaders/loader_jpeg.c | 6 ++--- src/modules/loaders/loader_lbm.c | 9 ++----- src/modules/loaders/loader_png.c | 8 ++---- src/modules/loaders/loader_pnm.c | 9 +++---- src/modules/loaders/loader_tga.c | 15 +++-------- src/modules/loaders/loader_tiff.c | 15 +++-------- src/modules/loaders/loader_webp.c | 5 ++-- src/modules/loaders/loader_xpm.c | 11 +++----- 19 files changed, 160 insertions(+), 100 deletions(-) diff --git a/src/lib/Imlib2.h b/src/lib/Imlib2.h index eefd514..fba01af 100644 --- a/src/lib/Imlib2.h +++ b/src/lib/Imlib2.h @@ -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); diff --git a/src/lib/api.c b/src/lib/api.c index 7c51d8e..de499b6 100644 --- a/src/lib/api.c +++ b/src/lib/api.c @@ -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. diff --git a/src/lib/filter.c b/src/lib/filter.c index 7cf9b27..3942ec7 100644 --- a/src/lib/filter.c +++ b/src/lib/filter.c @@ -237,6 +237,5 @@ __imlib_FilterImage(ImlibImage * im, ImlibFilter * fil) p2++; } } - free(im->data); - im->data = data; + __imlib_ReplaceData(im, data); } diff --git a/src/lib/image.c b/src/lib/image.c index 2caeb6a..dd23d93 100644 --- a/src/lib/image.c +++ b/src/lib/image.c @@ -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) { diff --git a/src/lib/image.h b/src/lib/image.h index 868cc45..5fef4df 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -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); diff --git a/src/lib/rgbadraw.c b/src/lib/rgbadraw.c index 6ac5e21..7a4e932 100644 --- a/src/lib/rgbadraw.c +++ b/src/lib/rgbadraw.c @@ -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 diff --git a/src/modules/loaders/loader_argb.c b/src/modules/loaders/loader_argb.c index 049e5d3..5ba2015 100644 --- a/src/modules/loaders/loader_argb.c +++ b/src/modules/loaders/loader_argb.c @@ -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; } diff --git a/src/modules/loaders/loader_bmp.c b/src/modules/loaders/loader_bmp.c index 2cc791e..f6a8888 100644 --- a/src/modules/loaders/loader_bmp.c +++ b/src/modules/loaders/loader_bmp.c @@ -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; diff --git a/src/modules/loaders/loader_ff.c b/src/modules/loaders/loader_ff.c index 0b7ba58..3c97ad6 100644 --- a/src/modules/loaders/loader_ff.c +++ b/src/modules/loaders/loader_ff.c @@ -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; diff --git a/src/modules/loaders/loader_gif.c b/src/modules/loaders/loader_gif.c index b9ac53f..6b3f724 100644 --- a/src/modules/loaders/loader_gif.c +++ b/src/modules/loaders/loader_gif.c @@ -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; } diff --git a/src/modules/loaders/loader_ico.c b/src/modules/loaders/loader_ico.c index efc8eb3..1bc19c7 100644 --- a/src/modules/loaders/loader_ico.c +++ b/src/modules/loaders/loader_ico.c @@ -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; } diff --git a/src/modules/loaders/loader_jpeg.c b/src/modules/loaders/loader_jpeg.c index de16168..cbd61c6 100644 --- a/src/modules/loaders/loader_jpeg.c +++ b/src/modules/loaders/loader_jpeg.c @@ -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; } diff --git a/src/modules/loaders/loader_lbm.c b/src/modules/loaders/loader_lbm.c index 2c6c801..7fe0b83 100644 --- a/src/modules/loaders/loader_lbm.c +++ b/src/modules/loaders/loader_lbm.c @@ -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]); diff --git a/src/modules/loaders/loader_png.c b/src/modules/loaders/loader_png.c index 865bb14..fb9541f 100644 --- a/src/modules/loaders/loader_png.c +++ b/src/modules/loaders/loader_png.c @@ -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; diff --git a/src/modules/loaders/loader_pnm.c b/src/modules/loaders/loader_pnm.c index 38d9fa9..1b63b3c 100644 --- a/src/modules/loaders/loader_pnm.c +++ b/src/modules/loaders/loader_pnm.c @@ -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; } diff --git a/src/modules/loaders/loader_tga.c b/src/modules/loaders/loader_tga.c index d3a72f9..2bb6b73 100644 --- a/src/modules/loaders/loader_tga.c +++ b/src/modules/loaders/loader_tga.c @@ -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; } diff --git a/src/modules/loaders/loader_tiff.c b/src/modules/loaders/loader_tiff.c index b7a2a05..3001d2d 100644 --- a/src/modules/loaders/loader_tiff.c +++ b/src/modules/loaders/loader_tiff.c @@ -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; } diff --git a/src/modules/loaders/loader_webp.c b/src/modules/loaders/loader_webp.c index 4abbc93..7b6342a 100644 --- a/src/modules/loaders/loader_webp.c +++ b/src/modules/loaders/loader_webp.c @@ -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; } diff --git a/src/modules/loaders/loader_xpm.c b/src/modules/loaders/loader_xpm.c index 44b2bce..c18faa2 100644 --- a/src/modules/loaders/loader_xpm.c +++ b/src/modules/loaders/loader_xpm.c @@ -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); --