oop, better sync sinkscreen fix
This commit is contained in:
parent
197877e32c
commit
404778cc3c
2
TODO
2
TODO
@ -1,3 +1,5 @@
|
|||||||
|
- sinkscreen sync mode is single-threaded :( can we safely unlock around the
|
||||||
|
prepare?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,11 +144,6 @@ typedef struct _Render {
|
|||||||
/* Hash of tiles with positions. Tiles can be dirty or painted.
|
/* Hash of tiles with positions. Tiles can be dirty or painted.
|
||||||
*/
|
*/
|
||||||
GHashTable *tiles;
|
GHashTable *tiles;
|
||||||
|
|
||||||
/* In synchronous mode (notify == NULL), generate tiles with this
|
|
||||||
* REGION.
|
|
||||||
*/
|
|
||||||
REGION *synchronous_reg;
|
|
||||||
} Render;
|
} Render;
|
||||||
|
|
||||||
/* Our per-thread state.
|
/* Our per-thread state.
|
||||||
@ -245,7 +240,6 @@ render_free( Render *render )
|
|||||||
render->ntiles = 0;
|
render->ntiles = 0;
|
||||||
IM_FREEF( g_slist_free, render->dirty );
|
IM_FREEF( g_slist_free, render->dirty );
|
||||||
IM_FREEF( g_hash_table_destroy, render->tiles );
|
IM_FREEF( g_hash_table_destroy, render->tiles );
|
||||||
IM_FREEF( im_region_free, render->synchronous_reg );
|
|
||||||
|
|
||||||
im_free( render );
|
im_free( render );
|
||||||
|
|
||||||
@ -624,8 +618,6 @@ render_new( VipsImage *in, VipsImage *out, VipsImage *mask,
|
|||||||
|
|
||||||
render->tiles = g_hash_table_new( tile_hash, tile_equal );
|
render->tiles = g_hash_table_new( tile_hash, tile_equal );
|
||||||
|
|
||||||
render->synchronous_reg = NULL;
|
|
||||||
|
|
||||||
render->dirty = NULL;
|
render->dirty = NULL;
|
||||||
|
|
||||||
/* Both out and mask must close before we can free the render.
|
/* Both out and mask must close before we can free the render.
|
||||||
@ -646,13 +638,6 @@ render_new( VipsImage *in, VipsImage *out, VipsImage *mask,
|
|||||||
render_ref( render );
|
render_ref( render );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In synchronous mode we need a region to generate pixels with.
|
|
||||||
*/
|
|
||||||
if( !notify ) {
|
|
||||||
if( !(render->synchronous_reg = im_region_create( in )) )
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
VIPS_DEBUG_MSG_AMBER( "render_new: %p\n", render );
|
VIPS_DEBUG_MSG_AMBER( "render_new: %p\n", render );
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG_AMBER
|
#ifdef VIPS_DEBUG_AMBER
|
||||||
@ -761,7 +746,7 @@ tile_touch( Tile *tile )
|
|||||||
/* Queue a tile for calculation.
|
/* Queue a tile for calculation.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
tile_queue( Tile *tile )
|
tile_queue( Tile *tile, REGION *reg )
|
||||||
{
|
{
|
||||||
Render *render = tile->render;
|
Render *render = tile->render;
|
||||||
|
|
||||||
@ -788,10 +773,18 @@ tile_queue( Tile *tile )
|
|||||||
"painting tile %p %dx%d synchronously\n",
|
"painting tile %p %dx%d synchronously\n",
|
||||||
tile, tile->area.left, tile->area.top );
|
tile, tile->area.left, tile->area.top );
|
||||||
|
|
||||||
if( im_prepare_to( render->synchronous_reg, tile->region,
|
/* While we're computing, let other threads use the cache.
|
||||||
|
* This tile won't get pulled out from under us since it's not
|
||||||
|
* marked as "painted", and it's not on the dirty list.
|
||||||
|
*/
|
||||||
|
g_mutex_unlock( render->lock );
|
||||||
|
|
||||||
|
if( im_prepare_to( reg, tile->region,
|
||||||
&tile->area, tile->area.left, tile->area.top ) )
|
&tile->area, tile->area.left, tile->area.top ) )
|
||||||
VIPS_DEBUG_MSG_RED( "tile_queue: prepare failed\n" );
|
VIPS_DEBUG_MSG_RED( "tile_queue: prepare failed\n" );
|
||||||
|
|
||||||
|
g_mutex_lock( render->lock );
|
||||||
|
|
||||||
tile->painted = TRUE;
|
tile->painted = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -827,7 +820,7 @@ render_tile_get_painted( Render *render )
|
|||||||
* or if we've no threads or no notify, calculate immediately.
|
* or if we've no threads or no notify, calculate immediately.
|
||||||
*/
|
*/
|
||||||
static Tile *
|
static Tile *
|
||||||
render_tile_request( Render *render, Rect *area )
|
render_tile_request( Render *render, REGION *reg, Rect *area )
|
||||||
{
|
{
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
|
||||||
@ -839,7 +832,7 @@ render_tile_request( Render *render, Rect *area )
|
|||||||
* ask for a repaint.
|
* ask for a repaint.
|
||||||
*/
|
*/
|
||||||
if( tile->region->invalid )
|
if( tile->region->invalid )
|
||||||
tile_queue( tile );
|
tile_queue( tile, reg );
|
||||||
else
|
else
|
||||||
tile_touch( tile );
|
tile_touch( tile );
|
||||||
}
|
}
|
||||||
@ -853,7 +846,7 @@ render_tile_request( Render *render, Rect *area )
|
|||||||
|
|
||||||
render_tile_add( tile, area );
|
render_tile_add( tile, area );
|
||||||
|
|
||||||
tile_queue( tile );
|
tile_queue( tile, reg );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Need to reuse a tile. Try for an old painted tile first,
|
/* Need to reuse a tile. Try for an old painted tile first,
|
||||||
@ -868,7 +861,7 @@ render_tile_request( Render *render, Rect *area )
|
|||||||
|
|
||||||
render_tile_move( tile, area );
|
render_tile_move( tile, area );
|
||||||
|
|
||||||
tile_queue( tile );
|
tile_queue( tile, reg );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( tile );
|
return( tile );
|
||||||
@ -912,12 +905,21 @@ tile_copy( Tile *tile, REGION *to )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
image_start( IMAGE *out, void *a, void *b )
|
||||||
|
{
|
||||||
|
Render *render = (Render *) a;
|
||||||
|
|
||||||
|
return( im_region_create( render->in ) );
|
||||||
|
}
|
||||||
|
|
||||||
/* Loop over the output region, filling with data from cache.
|
/* Loop over the output region, filling with data from cache.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
region_fill( REGION *out, void *seq, void *a, void *b )
|
image_fill( REGION *out, void *seq, void *a, void *b )
|
||||||
{
|
{
|
||||||
Render *render = (Render *) a;
|
Render *render = (Render *) a;
|
||||||
|
REGION *reg = (REGION *) seq;
|
||||||
Rect *r = &out->valid;
|
Rect *r = &out->valid;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
@ -926,7 +928,7 @@ region_fill( REGION *out, void *seq, void *a, void *b )
|
|||||||
int xs = (r->left / render->tile_width) * render->tile_width;
|
int xs = (r->left / render->tile_width) * render->tile_width;
|
||||||
int ys = (r->top / render->tile_height) * render->tile_height;
|
int ys = (r->top / render->tile_height) * render->tile_height;
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "region_fill: left = %d, top = %d, "
|
VIPS_DEBUG_MSG( "image_fill: left = %d, top = %d, "
|
||||||
"width = %d, height = %d\n",
|
"width = %d, height = %d\n",
|
||||||
r->left, r->top, r->width, r->height );
|
r->left, r->top, r->width, r->height );
|
||||||
|
|
||||||
@ -949,11 +951,11 @@ region_fill( REGION *out, void *seq, void *a, void *b )
|
|||||||
area.width = render->tile_width;
|
area.width = render->tile_width;
|
||||||
area.height = render->tile_height;
|
area.height = render->tile_height;
|
||||||
|
|
||||||
tile = render_tile_request( render, &area );
|
tile = render_tile_request( render, reg, &area );
|
||||||
if( tile )
|
if( tile )
|
||||||
tile_copy( tile, out );
|
tile_copy( tile, out );
|
||||||
else
|
else
|
||||||
VIPS_DEBUG_MSG_RED( "region_fill: argh!\n" );
|
VIPS_DEBUG_MSG_RED( "image_fill: argh!\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_unlock( render->lock );
|
g_mutex_unlock( render->lock );
|
||||||
@ -961,6 +963,16 @@ region_fill( REGION *out, void *seq, void *a, void *b )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
image_stop( void *seq, void *a, void *b )
|
||||||
|
{
|
||||||
|
REGION *reg = (REGION *) seq;
|
||||||
|
|
||||||
|
im_region_free( reg );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* The mask image is 255 / 0 for the state of painted for each tile.
|
/* The mask image is 255 / 0 for the state of painted for each tile.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -1100,7 +1112,8 @@ vips_sink_screen( VipsImage *in, VipsImage *out, VipsImage *mask,
|
|||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips_sink_screen: max = %d, %p\n", max_tiles, render );
|
VIPS_DEBUG_MSG( "vips_sink_screen: max = %d, %p\n", max_tiles, render );
|
||||||
|
|
||||||
if( im_generate( out, NULL, region_fill, NULL, render, NULL ) )
|
if( im_generate( out,
|
||||||
|
image_start, image_fill, image_stop, render, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( mask &&
|
if( mask &&
|
||||||
im_generate( mask, NULL, mask_fill, NULL, render, NULL ) )
|
im_generate( mask, NULL, mask_fill, NULL, render, NULL ) )
|
||||||
|
Loading…
Reference in New Issue
Block a user