diff --git a/libvips/include/vips/private.h b/libvips/include/vips/private.h index bde61ed9..75682b3f 100644 --- a/libvips/include/vips/private.h +++ b/libvips/include/vips/private.h @@ -127,6 +127,7 @@ typedef struct im__buffer_t { void im_buffer_done( im_buffer_t *buffer ); void im_buffer_undone( im_buffer_t *buffer ); void im_buffer_unref( im_buffer_t *buffer ); +im_buffer_t *im_buffer_new( struct _VipsImage *im, Rect *area ); im_buffer_t *im_buffer_ref( struct _VipsImage *im, Rect *area ); im_buffer_t *im_buffer_unref_ref( im_buffer_t *buffer, struct _VipsImage *im, Rect *area ); diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index 8e98d372..bf450986 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -292,8 +292,8 @@ im_buffer_unref( im_buffer_t *buffer ) /* Make a new buffer. */ -static im_buffer_t * -buffer_new( IMAGE *im, Rect *area ) +im_buffer_t * +im_buffer_new( IMAGE *im, Rect *area ) { im_buffer_t *buffer; @@ -313,7 +313,7 @@ buffer_new( IMAGE *im, Rect *area ) } #ifdef DEBUG - printf( "** buffer_new: left = %d, top = %d, " + printf( "** im_buffer_new: left = %d, top = %d, " "width = %d, height = %d (%p)\n", buffer->area.left, buffer->area.top, buffer->area.width, buffer->area.height, @@ -413,7 +413,7 @@ im_buffer_ref( IMAGE *im, Rect *area ) if( !(buffer = buffer_find( im, area )) ) /* No existing buffer ... make a new one. */ - if( !(buffer = buffer_new( im, area )) ) + if( !(buffer = im_buffer_new( im, area )) ) return( NULL ); return( buffer ); @@ -456,7 +456,7 @@ im_buffer_unref_ref( im_buffer_t *old_buffer, IMAGE *im, Rect *area ) /* Fallback ... unref the old one, make a new one. */ IM_FREEF( im_buffer_unref, old_buffer ); - if( !(buffer = buffer_new( im, area )) ) + if( !(buffer = im_buffer_new( im, area )) ) return( NULL ); return( buffer ); diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c index 76022923..2bc17633 100644 --- a/libvips/iofuncs/region.c +++ b/libvips/iofuncs/region.c @@ -452,18 +452,27 @@ im_region_buffer( REGION *reg, Rect *r ) return( -1 ); } - /* Don't call im_region_reset() ... we combine buffer unref and new - * buffer ref in one call to reduce malloc/free cycling. - */ - IM_FREEF( im_window_unref, reg->window ); - if( !(reg->buffer = im_buffer_unref_ref( reg->buffer, im, &clipped )) ) - return( -1 ); - /* If we've been asked to drop caches, flag this as undone. + /* Have we been asked to drop caches? We want to throw everything + * away. + * + * If not, try to reuse the current buffer. */ if( reg->invalid ) { + im_region_reset( reg ); + if( !(reg->buffer = im_buffer_ref( im, &clipped )) ) + return( -1 ); im_buffer_undone( reg->buffer ); - reg->invalid = FALSE; + } + else { + /* Don't call im_region_reset() ... we combine buffer unref + * and new buffer ref in one call to reduce malloc/free + * cycling. + */ + IM_FREEF( im_window_unref, reg->window ); + if( !(reg->buffer = + im_buffer_unref_ref( reg->buffer, im, &clipped )) ) + return( -1 ); } /* Init new stuff.