ImBuf: add IMB_allocFromBufferOwn that takes ownership of the buffer

Avoids duplicating the image buffer when saving thumbnails.
This commit is contained in:
Campbell Barton 2021-09-06 20:04:26 +10:00
parent a0912ff566
commit 687f70ceca
4 changed files with 51 additions and 12 deletions

View File

@ -439,17 +439,15 @@ static void studiolight_load_equirect_image(StudioLight *sl)
if (ctx.diffuse_pass != NULL) {
float *converted_pass = studiolight_multilayer_convert_pass(
ibuf, ctx.diffuse_pass, ctx.num_diffuse_channels);
diffuse_ibuf = IMB_allocFromBuffer(
diffuse_ibuf = IMB_allocFromBufferOwn(
NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_diffuse_channels);
MEM_freeN(converted_pass);
}
if (ctx.specular_pass != NULL) {
float *converted_pass = studiolight_multilayer_convert_pass(
ibuf, ctx.specular_pass, ctx.num_specular_channels);
specular_ibuf = IMB_allocFromBuffer(
specular_ibuf = IMB_allocFromBufferOwn(
NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_specular_channels);
MEM_freeN(converted_pass);
}
IMB_exr_close(ibuf->userdata);
@ -1148,12 +1146,11 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
}
ITER_PIXELS_END;
sl->equirect_irradiance_buffer = IMB_allocFromBuffer(NULL,
colbuf,
STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH,
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT,
4);
MEM_freeN(colbuf);
sl->equirect_irradiance_buffer = IMB_allocFromBufferOwn(NULL,
colbuf,
STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH,
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT,
4);
}
sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED;
}

View File

@ -148,6 +148,14 @@ struct ImBuf *IMB_allocImBuf(unsigned int x,
bool IMB_initImBuf(
struct ImBuf *ibuf, unsigned int x, unsigned int y, unsigned char planes, unsigned int flags);
/**
* Create a copy of a pixel buffer and wrap it to a new ImBuf
* (transferring ownership to the in imbuf).
* \attention Defined in allocimbuf.c
*/
struct ImBuf *IMB_allocFromBufferOwn(
unsigned int *rect, float *rectf, unsigned int w, unsigned int h, unsigned int channels);
/**
* Create a copy of a pixel buffer and wrap it to a new ImBuf
* \attention Defined in allocimbuf.c

View File

@ -430,6 +430,41 @@ bool imb_addrectImBuf(ImBuf *ibuf)
return false;
}
/**
* \param take_ownership: When true, the buffers become owned by the resulting image.
*/
struct ImBuf *IMB_allocFromBufferOwn(
unsigned int *rect, float *rectf, unsigned int w, unsigned int h, unsigned int channels)
{
ImBuf *ibuf = NULL;
if (!(rect || rectf)) {
return NULL;
}
ibuf = IMB_allocImBuf(w, h, 32, 0);
ibuf->channels = channels;
/* Avoid #MEM_dupallocN since the buffers might not be allocated using guarded-allocation. */
if (rectf) {
BLI_assert(MEM_allocN_len(rectf) == sizeof(float[4]) * w * h);
ibuf->rect_float = rectf;
ibuf->flags |= IB_rectfloat;
ibuf->mall |= IB_rectfloat;
}
if (rect) {
BLI_assert(MEM_allocN_len(rect) == sizeof(uchar[4]) * w * h);
ibuf->rect = rect;
ibuf->flags |= IB_rect;
ibuf->mall |= IB_rect;
}
return ibuf;
}
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
const float *rectf,
unsigned int w,

View File

@ -1539,7 +1539,7 @@ static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **thu
int win_size[2];
uint *buffer = WM_window_pixels_read(CTX_wm_manager(C), win, win_size);
ImBuf *ibuf = IMB_allocFromBuffer(buffer, NULL, win_size[0], win_size[1], 24);
ImBuf *ibuf = IMB_allocFromBufferOwn(buffer, NULL, win_size[0], win_size[1], 24);
if (ibuf) {
int ex, ey;
@ -1561,7 +1561,6 @@ static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **thu
BlendThumbnail *thumb = BKE_main_thumbnail_from_imbuf(NULL, thumb_ibuf);
IMB_freeImBuf(thumb_ibuf);
MEM_freeN(buffer);
*thumb_pt = thumb;
}
WM_cursor_wait(false);