Skip to content

Commit 88df5f3

Browse files
committed
fix tile recomp issue
splitting request from collect stops recomp cancelling itself all the time
1 parent 2a9e645 commit 88df5f3

File tree

5 files changed

+101
-57
lines changed

5 files changed

+101
-57
lines changed

TODO

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
- nip4 ~/pics/a1.bmp, free rotate, open imagewindow, drag slider
1+
- investigate tile recomp for test.ws, are we optimal now?
22

3-
updates often hitch badly, what's it doing?
43

5-
perhaps it's not discarding out of date updates quickly enough?
64

7-
test nip2 on the same task
8-
9-
always seems to be making useful pixels
10-
11-
in nip4, drag alisder a lot, end on -61, open image view window, never
12-
updates
13-
14-
you need to press 1, wait for update, then press 0 to see anything
5+
- very long formula (eg. Group [G1, G2, etc]) are not truncated
156

167
- check all batch mode flags
178

src/tilecache.c

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ tilecache_dispose(GObject *object)
9494

9595
FREESID(tilecache->tilesource_changed_sid, tilecache->tilesource);
9696
FREESID(tilecache->tilesource_tiles_changed_sid, tilecache->tilesource);
97-
FREESID(tilecache->tilesource_area_changed_sid, tilecache->tilesource);
97+
FREESID(tilecache->tilesource_collect_sid, tilecache->tilesource);
9898
VIPS_UNREF(tilecache->tilesource);
9999
VIPS_UNREF(tilecache->background_texture);
100100

@@ -334,11 +334,11 @@ tilecache_find(Tilecache *tilecache, VipsRect *tile_rect, int z)
334334
return NULL;
335335
}
336336

337-
/* Fetch a single tile. If we have this tile already, refresh if there are new
337+
/* Request a single tile. If we have this tile already, refresh if there are new
338338
* pixels available.
339339
*/
340340
static void
341-
tilecache_get(Tilecache *tilecache, VipsRect *tile_rect, int z)
341+
tilecache_request(Tilecache *tilecache, VipsRect *tile_rect, int z)
342342
{
343343
Tile *tile;
344344

@@ -356,29 +356,30 @@ tilecache_get(Tilecache *tilecache, VipsRect *tile_rect, int z)
356356
}
357357

358358
if (!tile->valid) {
359-
/* The tile might have no pixels, or might need refreshing
360-
* because the bg render has finished with it.
361-
*/
362359
#ifdef DEBUG_VERBOSE
363-
printf("tilecache_get: fetching left = %d, top = %d, "
360+
printf("tilecache_request: fetching left = %d, top = %d, "
364361
"width = %d, height = %d, z = %d\n",
365362
tile_rect->left, tile_rect->top,
366363
tile_rect->width, tile_rect->height,
367364
z);
368365
#endif /*DEBUG_VERBOSE*/
369366

370-
tilesource_fill_tile(tilecache->tilesource, tile);
367+
tilesource_request_tile(tilecache->tilesource, tile);
371368
}
372369
}
373370

374-
/* Fetch the tiles in an area.
371+
/* Request tiles from an area. If they are not in cache, they will be computed
372+
* in the bg and delivered via _collect().
375373
*
376374
* render processes tiles in FIFO order, so we need to add in reverse order
377375
* of processing. We want repaint to happen in a spiral from the centre out,
378376
* so we have to add in a spiral from the outside in.
377+
*
378+
* We must be careful not to change tilesource if we have all these tiles
379+
* already (very common for thumbnails, for example).
379380
*/
380381
static void
381-
tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
382+
tilecache_request_area(Tilecache *tilecache, VipsRect *viewport, int z)
382383
{
383384
int size0 = TILE_SIZE << z;
384385

@@ -412,7 +413,7 @@ tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
412413
for (x = left; x < right; x += size0) {
413414
tile_rect.left = x;
414415
tile_rect.top = top;
415-
tilecache_get(tilecache, &tile_rect, z);
416+
tilecache_request(tilecache, &tile_rect, z);
416417
}
417418

418419
top += size0;
@@ -425,7 +426,7 @@ tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
425426
for (x = left; x < right; x += size0) {
426427
tile_rect.left = x;
427428
tile_rect.top = bottom - size0;
428-
tilecache_get(tilecache, &tile_rect, z);
429+
tilecache_request(tilecache, &tile_rect, z);
429430
}
430431

431432
bottom -= size0;
@@ -438,7 +439,7 @@ tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
438439
for (y = top; y < bottom; y += size0) {
439440
tile_rect.left = left;
440441
tile_rect.top = y;
441-
tilecache_get(tilecache, &tile_rect, z);
442+
tilecache_request(tilecache, &tile_rect, z);
442443
}
443444

444445
left += size0;
@@ -451,7 +452,7 @@ tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
451452
for (y = top; y < bottom; y += size0) {
452453
tile_rect.left = right - size0;
453454
tile_rect.top = y;
454-
tilecache_get(tilecache, &tile_rect, z);
455+
tilecache_request(tilecache, &tile_rect, z);
455456
}
456457

457458
right -= size0;
@@ -461,33 +462,35 @@ tilecache_fetch_area(Tilecache *tilecache, VipsRect *viewport, int z)
461462
}
462463
}
463464

464-
/* The bg render thread says some tiles have fresh pixels.
465+
/* A new tile is available from the bg render and must be collected.
465466
*/
466467
static void
467-
tilecache_source_area_changed(Tilesource *tilesource,
468+
tilecache_source_collect(Tilesource *tilesource,
468469
VipsRect *dirty, int z, Tilecache *tilecache)
469470
{
470471
#ifdef DEBUG_VERBOSE
471-
printf("tilecache_source_area_changed: left = %d, top = %d, "
472+
printf("tilecache_source_collect: left = %d, top = %d, "
472473
"width = %d, height = %d, z = %d\n",
473474
dirty->left, dirty->top,
474475
dirty->width, dirty->height, z);
475476
#endif /*DEBUG_VERBOSE*/
476477

477-
/* Immediately fetch the updated tile. If we wait for snapshot, the
478-
* animation page may have changed.
479-
*/
480-
tilecache_fetch_area(tilecache, dirty, z);
478+
Tile *tile = tilecache_find(tilecache, dirty, z);
479+
if (tile &&
480+
!tile->valid) {
481+
tilesource_collect_tile(tilecache->tilesource, tile);
481482

482-
tilecache_area_changed(tilecache, dirty, z);
483+
// things displaying us will need to redraw
484+
tilecache_area_changed(tilecache, dirty, z);
485+
}
483486
}
484487

485488
static void
486489
tilecache_set_tilesource(Tilecache *tilecache, Tilesource *tilesource)
487490
{
488491
FREESID(tilecache->tilesource_changed_sid, tilecache->tilesource);
489492
FREESID(tilecache->tilesource_tiles_changed_sid, tilecache->tilesource);
490-
FREESID(tilecache->tilesource_area_changed_sid, tilecache->tilesource);
493+
FREESID(tilecache->tilesource_collect_sid, tilecache->tilesource);
491494
VIPS_UNREF(tilecache->tilesource);
492495

493496
tilecache->tilesource = tilesource;
@@ -503,9 +506,9 @@ tilecache_set_tilesource(Tilecache *tilecache, Tilesource *tilesource)
503506
tilecache->tilesource_tiles_changed_sid =
504507
g_signal_connect(tilesource, "tiles-changed",
505508
G_CALLBACK(tilecache_source_tiles_changed), tilecache);
506-
tilecache->tilesource_area_changed_sid =
507-
g_signal_connect(tilesource, "area-changed",
508-
G_CALLBACK(tilecache_source_area_changed), tilecache);
509+
tilecache->tilesource_collect_sid =
510+
g_signal_connect(tilesource, "collect",
511+
G_CALLBACK(tilecache_source_collect), tilecache);
509512

510513
/* Any tiles must be invalidated.
511514
*/
@@ -946,7 +949,7 @@ tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot,
946949
/* Fetch any tiles we are missing, update any tiles we have that have
947950
* been flagged as having pixels ready for fetching.
948951
*/
949-
tilecache_fetch_area(tilecache, &viewport, z);
952+
tilecache_request_area(tilecache, &viewport, z);
950953

951954
/* Find the set of visible tiles, sorted back to front.
952955
*

src/tilecache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ typedef struct _Tilecache {
8787
*/
8888
GdkTexture *background_texture;
8989

90-
/* The signals we watcgh tilesource with.
90+
/* The signals we watch tilesource with.
9191
*/
9292
guint tilesource_changed_sid;
9393
guint tilesource_tiles_changed_sid;
94-
guint tilesource_area_changed_sid;
94+
guint tilesource_collect_sid;
9595

9696
} Tilecache;
9797

src/tilesource.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ enum {
6262
SIG_POSTEVAL,
6363
SIG_CHANGED,
6464
SIG_TILES_CHANGED,
65-
SIG_AREA_CHANGED,
65+
SIG_COLLECT,
6666
SIG_PAGE_CHANGED,
6767

6868
SIG_LAST
@@ -111,10 +111,9 @@ tilesource_tiles_changed(Tilesource *tilesource)
111111
}
112112

113113
static void
114-
tilesource_area_changed(Tilesource *tilesource, VipsRect *dirty, int z)
114+
tilesource_collect(Tilesource *tilesource, VipsRect *dirty, int z)
115115
{
116-
g_signal_emit(tilesource,
117-
tilesource_signals[SIG_AREA_CHANGED], 0, dirty, z);
116+
g_signal_emit(tilesource, tilesource_signals[SIG_COLLECT], 0, dirty, z);
118117
}
119118

120119
static void
@@ -230,7 +229,7 @@ tilesource_render_notify_idle(void *user_data)
230229
* pipeline.
231230
*/
232231
if (update->image == tilesource->display)
233-
tilesource_area_changed(tilesource, &update->rect, update->z);
232+
tilesource_collect(tilesource, &update->rect, update->z);
234233

235234
/* The update that's just for this one event needs freeing.
236235
*/
@@ -253,9 +252,13 @@ tilesource_render_notify(VipsImage *image, VipsRect *rect, void *client)
253252
*/
254253
TilesourceUpdate *new_update = g_new(TilesourceUpdate, 1);
255254

255+
/* From image cods to level0 cods.
256+
*/
256257
*new_update = *update;
257-
new_update->rect = *rect;
258-
new_update->z = update->z;
258+
new_update->rect.left = rect->left << update->z;
259+
new_update->rect.top = rect->top << update->z;
260+
new_update->rect.width = rect->width << update->z;
261+
new_update->rect.height = rect->height << update->z;
259262

260263
g_idle_add(tilesource_render_notify_idle, new_update);
261264
}
@@ -1237,10 +1240,10 @@ tilesource_class_init(TilesourceClass *class)
12371240
g_cclosure_marshal_VOID__VOID,
12381241
G_TYPE_NONE, 0);
12391242

1240-
tilesource_signals[SIG_AREA_CHANGED] = g_signal_new("area-changed",
1243+
tilesource_signals[SIG_COLLECT] = g_signal_new("collect",
12411244
G_TYPE_FROM_CLASS(class),
12421245
G_SIGNAL_RUN_LAST,
1243-
G_STRUCT_OFFSET(TilesourceClass, area_changed),
1246+
G_STRUCT_OFFSET(TilesourceClass, collect),
12441247
NULL, NULL,
12451248
nip4_VOID__POINTER_INT,
12461249
G_TYPE_NONE, 2,
@@ -1821,11 +1824,15 @@ tilesource_background_load(Tilesource *tilesource)
18211824
tilesource, NULL);
18221825
}
18231826

1827+
/* Request a tile from the pipeline. The tile might be already there (in
1828+
* cache), and we are all done, or it might need to be computed and collected
1829+
* later.
1830+
*/
18241831
int
1825-
tilesource_fill_tile(Tilesource *tilesource, Tile *tile)
1832+
tilesource_request_tile(Tilesource *tilesource, Tile *tile)
18261833
{
18271834
#ifdef DEBUG_VERBOSE
1828-
printf("tilesource_fill_tile: %d x %d\n",
1835+
printf("tilesource_request_tile: %d x %d\n",
18291836
tile->region->valid.left, tile->region->valid.top);
18301837
#endif /*DEBUG_VERBOSE*/
18311838

@@ -1850,8 +1857,10 @@ tilesource_fill_tile(Tilesource *tilesource, Tile *tile)
18501857
printf(" valid = %d\n", tile->valid);
18511858
#endif /*DEBUG_VERBOSE*/
18521859

1853-
/* We must always prepare the region, even if we know it's blank,
1854-
* since this will trigger the background render.
1860+
/* If the tile is not in cache, we must fetch to trigger a bg recomp.
1861+
*
1862+
* If it is in cache, we also fetch the pixels and set a texture ready
1863+
* for the cache.
18551864
*/
18561865
if (vips_region_prepare_to(tilesource->rgb_region, tile->region,
18571866
&tile->region->valid,
@@ -1870,6 +1879,46 @@ tilesource_fill_tile(Tilesource *tilesource, Tile *tile)
18701879
return 0;
18711880
}
18721881

1882+
/* Try to collect a computed tile.
1883+
*/
1884+
int
1885+
tilesource_collect_tile(Tilesource *tilesource, Tile *tile)
1886+
{
1887+
#ifdef DEBUG_VERBOSE
1888+
printf("tilesource_collect_tile: %d x %d\n",
1889+
tile->region->valid.left, tile->region->valid.top);
1890+
#endif /*DEBUG_VERBOSE*/
1891+
1892+
if (vips_region_prepare(tilesource->mask_region, &tile->region->valid))
1893+
return -1;
1894+
1895+
/* tile is within a single tile, so we only need to test the first byte
1896+
* of the mask.
1897+
*/
1898+
tile->valid = VIPS_REGION_ADDR(tilesource->mask_region,
1899+
tile->region->valid.left, tile->region->valid.top)[0];
1900+
1901+
#ifdef DEBUG_VERBOSE
1902+
printf(" valid = %d\n", tile->valid);
1903+
#endif /*DEBUG_VERBOSE*/
1904+
1905+
/* Only read out the tile if it's valid. We don't want to trigger another
1906+
* compute.
1907+
*/
1908+
if (tile->valid) {
1909+
if (vips_region_prepare_to(tilesource->rgb_region, tile->region,
1910+
&tile->region->valid,
1911+
tile->region->valid.left,
1912+
tile->region->valid.top))
1913+
return -1;
1914+
1915+
tile_free_texture(tile);
1916+
tile_get_texture(tile);
1917+
}
1918+
1919+
return 0;
1920+
}
1921+
18731922
const char *
18741923
tilesource_get_path(Tilesource *tilesource)
18751924
{

src/tilesource.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,10 @@ typedef struct _TilesourceClass {
258258
*/
259259
void (*tiles_changed)(Tilesource *tilesource);
260260

261-
/* A set of tiles on a certain level have new pixels now that a
262-
* background render has completed.
261+
/* A tile has been computed by a bg worker and must be collected from the
262+
* end of the pipeline.
263263
*/
264-
void (*area_changed)(Tilesource *tilesource, VipsRect *area, int z);
264+
void (*collect)(Tilesource *tilesource, VipsRect *area, int z);
265265

266266
/* The page has changed. Just for updating the page number display.
267267
*/
@@ -280,7 +280,8 @@ gboolean tilesource_has_imageinfo(Tilesource *tilesource, Imageinfo *ii);
280280

281281
void tilesource_background_load(Tilesource *tilesource);
282282

283-
int tilesource_fill_tile(Tilesource *tilesource, Tile *tile);
283+
int tilesource_request_tile(Tilesource *tilesource, Tile *tile);
284+
int tilesource_collect_tile(Tilesource *tilesource, Tile *tile);
284285

285286
const char *tilesource_get_path(Tilesource *tilesource);
286287
GFile *tilesource_get_file(Tilesource *tilesource);

0 commit comments

Comments
 (0)