/* Make a new buffer. */ VipsBuffer * vips_buffer_new( VipsImage *im, VipsRect *area ) { VipsBufferCache *cache; VipsBuffer *buffer; if( (cache = buffer_cache_get( im )) && cache->reserve ) { buffer = (VipsBuffer *) cache->reserve->data; cache->reserve = g_slist_remove( cache->reserve, buffer ); cache->n_reserve -= 1; g_assert( buffer->im == im ); g_assert( buffer->done == FALSE ); g_assert( buffer->cache ); buffer->ref_count = 1; buffer->cache = NULL; } else { buffer = g_new0( VipsBuffer, 1 ); buffer->ref_count = 1; buffer->im = im; buffer->done = FALSE; buffer->cache = NULL; buffer->buf = NULL; buffer->bsize = 0; #ifdef DEBUG g_mutex_lock( vips__global_lock ); vips__buffer_all = g_slist_prepend( vips__buffer_all, buffer ); g_mutex_unlock( vips__global_lock ); #endif /*DEBUG*/ } if( buffer_move( buffer, area ) ) { vips_buffer_free( buffer ); return( NULL ); } return( buffer ); }
void vips_buffer_unref( VipsBuffer *buffer ) { #ifdef DEBUG_VERBOSE printf( "** vips_buffer_unref: left = %d, top = %d, " "width = %d, height = %d (%p)\n", buffer->area.left, buffer->area.top, buffer->area.width, buffer->area.height, buffer ); #endif /*DEBUG_VERBOSE*/ g_assert( buffer->ref_count > 0 ); buffer->ref_count -= 1; if( buffer->ref_count == 0 ) { VipsBufferCache *cache; #ifdef DEBUG_VERBOSE if( !buffer->done ) printf( "vips_buffer_unref: buffer was not done\n" ); #endif /*DEBUG_VERBOSE*/ vips_buffer_undone( buffer ); /* Place on this thread's reserve list for reuse. */ if( (cache = buffer_cache_get( buffer->im )) && cache->n_reserve < buffer_cache_max_reserve ) { g_assert( !buffer->cache ); cache->reserve = g_slist_prepend( cache->reserve, buffer ); cache->n_reserve += 1; buffer->cache = cache; buffer->area.width = 0; buffer->area.height = 0; } else vips_buffer_free( buffer ); } }
/* Find an existing buffer that encloses area and return a ref. */ static VipsBuffer * buffer_find( VipsImage *im, VipsRect *r ) { VipsBufferCache *cache = buffer_cache_get( im ); VipsBuffer *buffer; GSList *p; VipsRect *area; /* This needs to be quick :-( don't use * vips_slist_map2()/vips_rect_includesrect(), do the search inline. * * FIXME we return the first enclosing buffer, perhaps we should * search for the largest? */ for( p = cache->buffers; p; p = p->next ) { buffer = (VipsBuffer *) p->data; area = &buffer->area; if( area->left <= r->left && area->top <= r->top && area->left + area->width >= r->left + r->width && area->top + area->height >= r->top + r->height ) { buffer->ref_count += 1; #ifdef DEBUG_VERBOSE printf( "vips_buffer_find: left = %d, top = %d, " "width = %d, height = %d, count = %d (%p)\n", buffer->area.left, buffer->area.top, buffer->area.width, buffer->area.height, buffer->ref_count, buffer ); #endif /*DEBUG_VERBOSE*/ return( buffer ); } } return( NULL ); }
/* Pixels have been calculated: publish for other parts of this thread to see. */ void vips_buffer_done( VipsBuffer *buffer ) { if( !buffer->done ) { VipsImage *im = buffer->im; VipsBufferCache *cache = buffer_cache_get( im ); #ifdef DEBUG_VERBOSE printf( "vips_buffer_done: thread %p adding to cache %p\n", g_thread_self(), cache ); vips_buffer_print( buffer ); #endif /*DEBUG_VERBOSE*/ g_assert( !g_slist_find( cache->buffers, buffer ) ); g_assert( !buffer->cache ); buffer->done = TRUE; buffer->cache = cache; cache->buffers = g_slist_prepend( cache->buffers, buffer ); } }