Skip to content

Commit 7ad41ca

Browse files
committed
another imagewindow repaint improvement
1 parent 6f0a862 commit 7ad41ca

File tree

7 files changed

+60
-193
lines changed

7 files changed

+60
-193
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
## master
22

3+
## 9.0.3 2025/03/13
4+
35
- fix save-as
6+
- revise image repaint (again)
47

58
## 9.0.2 2025/03/10
69

TODO

Lines changed: 0 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,3 @@
1-
- try
2-
3-
nip4 ~/test.ws
4-
5-
open imagewindow, often does not paint correctlyo
6-
7-
seems to be a race
8-
9-
trace of failed repaint
10-
11-
looks like an unexpected thumbnail repaint is coming in half-way
12-
though the main window repaint, causing the pipeline to rebuild, and
13-
making the rest of the level0 tiles to be discarded
14-
15-
why does the thumbnail repaint cause a request? you'd think that would
16-
just be served from cache
17-
18-
19-
20-
row_deselect: FIXME ... call matrix_deselect()
21-
tilecache_init:
22-
tilecache_build_pyramid:
23-
2 pyr levels
24-
0) 512 x 512
25-
1) 256 x 256
26-
tilecache_source_tiles_changed:
27-
tilesource_background_load_worker: starting ...
28-
tilesource_set_property: ACTIVE = FALSE
29-
tilesource_set_property: VISIBLE = TRUE
30-
tilesource_background_load_worker: ... done
31-
tilesource_set_property: FALSECOLOUR = FALSE
32-
tilesource_set_property: LOG = FALSE
33-
tilesource_set_property: ICC = FALSE
34-
tilesource_set_property: MODE = ((TilesourceMode) TILESOURCE_MODE_MULTIPAGE)
35-
tilesource_background_load_worker: starting ...
36-
tilesource_background_load_worker: ... done
37-
38-
tilecache_snapshot: scale = 1, x = 0, y = 0
39-
paint_rect left = 550, top = 461, width = 0, height = 0
40-
tilecache_request: fetching left = 0, top = 0, width = 256, height = 256, z = 0
41-
tilesource_request_tile: 0 x 0
42-
valid = 255
43-
tilecache_compute_visibility: z = 0
44-
viewport in level0 coordinates: left = 0, top = 0, width = 256, height = 256
45-
level 0, 1 tiles, 1 visible, 0 free
46-
level 1, 0 tiles, 0 visible, 0 free
47-
level 0 tiles:
48-
@ 0 x 0, 256 x 256, valid = 255, visible = 1, texture = 0x5d34010b1210
49-
level 1 tiles:
50-
tilecache_snapshot: 3.573 ms
51-
52-
tilesource_background_load_done_cb: ... unreffing
53-
tilesource_set_property: LOADED = TRUE
54-
tilesource_set_property: VISIBLE = TRUE
55-
tilesource_update_display:
56-
tilesource_update_rgb:
57-
tilecache_source_changed:
58-
tilecache_build_pyramid:
59-
no geometry change, skipping pyr rebuild
60-
tilecache_source_tiles_changed:
61-
tilecache_source_changed:
62-
tilecache_build_pyramid:
63-
no geometry change, skipping pyr rebuild
64-
tilecache_source_tiles_changed:
65-
tilesource_set_property: FALSECOLOUR = FALSE
66-
tilesource_set_property: LOG = FALSE
67-
tilesource_set_property: ICC = FALSE
68-
tilesource_set_property: MODE = ((TilesourceMode) TILESOURCE_MODE_MULTIPAGE)
69-
tilesource_background_load_done_cb: ... unreffing
70-
tilesource_set_property: LOADED = TRUE
71-
tilesource_set_property: VISIBLE = TRUE
72-
tilesource_update_display:
73-
tilesource_update_rgb:
74-
tilecache_source_changed:
75-
tilecache_build_pyramid:
76-
no geometry change, skipping pyr rebuild
77-
tilecache_source_tiles_changed:
78-
tilecache_source_changed:
79-
tilecache_build_pyramid:
80-
no geometry change, skipping pyr rebuild
81-
tilecache_source_tiles_changed:
82-
tilesource_set_property: FALSECOLOUR = FALSE
83-
tilesource_set_property: LOG = FALSE
84-
tilesource_set_property: ICC = FALSE
85-
tilesource_set_property: MODE = ((TilesourceMode) TILESOURCE_MODE_MULTIPAGE)
86-
87-
tilecache_snapshot: scale = 1.80273, x = 0, y = 0
88-
paint_rect left = 88, top = 0, width = 923, height = 923
89-
tilecache_request: fetching left = 0, top = 0, width = 256, height = 256, z = 0
90-
tilesource_request_tile: 0 x 0
91-
valid = 0
92-
tilecache_request: fetching left = 256, top = 0, width = 256, height = 256, z = 0
93-
tilesource_request_tile: 256 x 0
94-
valid = 0
95-
tilecache_request: fetching left = 0, top = 256, width = 256, height = 256, z = 0
96-
tilesource_request_tile: 0 x 256
97-
valid = 0
98-
tilecache_request: fetching left = 256, top = 256, width = 256, height = 256, z = 0
99-
tilesource_request_tile: 256 x 256
100-
valid = 0
101-
tilecache_compute_visibility: z = 0
102-
viewport in level0 coordinates: left = 0, top = 0, width = 512, height = 512
103-
level 0, 4 tiles, 1 visible, 3 free
104-
level 1, 0 tiles, 0 visible, 0 free
105-
level 0 tiles:
106-
@ 256 x 256, 256 x 256, valid = 0, visible = 0, texture = (nil)
107-
@ 0 x 256, 256 x 256, valid = 0, visible = 0, texture = (nil)
108-
@ 256 x 0, 256 x 256, valid = 0, visible = 0, texture = (nil)
109-
@ 0 x 0, 256 x 256, valid = 0, visible = 1, texture = 0x5d34010b1210
110-
level 1 tiles:
111-
tilecache_snapshot: 13.936 ms
112-
113-
tilecache_snapshot: scale = 0.125, x = 0, y = 0
114-
paint_rect left = 143, top = 0, width = 64, height = 64
115-
tilecache_request: fetching left = 0, top = 0, width = 512, height = 512, z = 1
116-
tilesource_request_tile: 0 x 0
117-
tilesource_update_display:
118-
tilesource_update_rgb:
119-
valid = 0
120-
tilecache_compute_visibility: z = 1
121-
viewport in level0 coordinates: left = 0, top = 0, width = 512, height = 512
122-
level 0, 0 tiles, 0 visible, 0 free
123-
level 1, 1 tiles, 1 visible, 0 free
124-
level 0 tiles:
125-
level 1 tiles:
126-
@ 0 x 0, 512 x 512, valid = 0, visible = 1, texture = 0x5d33ffc65320
127-
tilecache_snapshot: 4.511 ms
128-
129-
tilecache_source_collect: left = 0, top = 0, width = 512, height = 512, z = 1
130-
tilesource_collect_tile: 0 x 0
131-
valid = 255
132-
tilecache_source_collect: left = 0, top = 0, width = 512, height = 512, z = 1
133-
134-
tilecache_snapshot: scale = 0.125, x = 0, y = 0
135-
paint_rect left = 143, top = 0, width = 64, height = 64
136-
tilecache_compute_visibility: z = 1
137-
viewport in level0 coordinates: left = 0, top = 0, width = 512, height = 512
138-
level 0, 0 tiles, 0 visible, 0 free
139-
level 1, 1 tiles, 1 visible, 0 free
140-
level 0 tiles:
141-
level 1 tiles:
142-
@ 0 x 0, 512 x 512, valid = 255, visible = 1, texture = 0x5d33fe3ec960
143-
tilecache_snapshot: 0.027 ms
144-
145-
tilecache_snapshot: scale = 1.80273, x = 0, y = 0
146-
paint_rect left = 88, top = 0, width = 923, height = 923
147-
tilecache_request: fetching left = 0, top = 0, width = 256, height = 256, z = 0
148-
tilesource_request_tile: 0 x 0
149-
tilesource_update_display:
150-
tilesource_update_rgb:
151-
valid = 0
152-
tilecache_request: fetching left = 256, top = 0, width = 256, height = 256, z = 0
153-
tilesource_request_tile: 256 x 0
154-
valid = 0
155-
tilecache_request: fetching left = 0, top = 256, width = 256, height = 256, z = 0
156-
tilesource_request_tile: 0 x 256
157-
valid = 0
158-
tilecache_request: fetching left = 256, top = 256, width = 256, height = 256, z = 0
159-
tilesource_request_tile: 256 x 256
160-
valid = 0
161-
tilecache_compute_visibility: z = 0
162-
viewport in level0 coordinates: left = 0, top = 0, width = 512, height = 512
163-
level 0, 4 tiles, 1 visible, 3 free
164-
level 1, 0 tiles, 0 visible, 0 free
165-
level 0 tiles:
166-
@ 256 x 256, 256 x 256, valid = 0, visible = 0, texture = (nil)
167-
@ 0 x 256, 256 x 256, valid = 0, visible = 0, texture = (nil)
168-
@ 256 x 0, 256 x 256, valid = 0, visible = 0, texture = (nil)
169-
@ 0 x 0, 256 x 256, valid = 0, visible = 1, texture = 0x5d34010b1210
170-
level 1 tiles:
171-
tilecache_snapshot: 14.875 ms
172-
173-
174-
175-
176-
177-
178-
1791
# menu redesign
1802

1813
- remove unused widgets

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project('nip4', 'c',
22
# ie. a major after nip2 8.9 for workspace save file versioning
3-
version: '9.0.2-2',
3+
version: '9.0.3',
44
license: 'GPL',
55
meson_version: '>=0.64',
66
default_options: [

src/tilecache.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ tilecache_dispose(GObject *object)
9393
#endif /*DEBUG*/
9494

9595
FREESID(tilecache->tilesource_changed_sid, tilecache->tilesource);
96+
FREESID(tilecache->tilesource_loaded_sid, tilecache->tilesource);
9697
FREESID(tilecache->tilesource_tiles_changed_sid, tilecache->tilesource);
9798
FREESID(tilecache->tilesource_collect_sid, tilecache->tilesource);
9899
VIPS_UNREF(tilecache->tilesource);
@@ -278,7 +279,7 @@ tilecache_source_tiles_changed(Tilesource *tilesource,
278279
int i;
279280

280281
#ifdef DEBUG
281-
printf("tilecache_source_tiles_changed:\n");
282+
printf("tilecache_source_tiles_changed: %p\n", tilecache);
282283
#endif /*DEBUG*/
283284

284285
for (i = 0; i < tilecache->n_levels; i++) {
@@ -318,6 +319,21 @@ tilecache_source_changed(Tilesource *tilesource, Tilecache *tilecache)
318319
tilecache_changed(tilecache);
319320
}
320321

322+
/* background load is done ... no pixels have changed, but we should repaint
323+
* in casewe have any missing tiles.
324+
*/
325+
static void
326+
tilecache_source_loaded(Tilesource *tilesource, Tilecache *tilecache)
327+
{
328+
#ifdef DEBUG
329+
printf("tilecache_source_loaded:\n");
330+
#endif /*DEBUG*/
331+
332+
/* Repaint to trigger a request (if necessary).
333+
*/
334+
tilecache_changed(tilecache);
335+
}
336+
321337
static Tile *
322338
tilecache_find(Tilecache *tilecache, VipsRect *tile_rect, int z)
323339
{
@@ -489,6 +505,7 @@ static void
489505
tilecache_set_tilesource(Tilecache *tilecache, Tilesource *tilesource)
490506
{
491507
FREESID(tilecache->tilesource_changed_sid, tilecache->tilesource);
508+
FREESID(tilecache->tilesource_loaded_sid, tilecache->tilesource);
492509
FREESID(tilecache->tilesource_tiles_changed_sid, tilecache->tilesource);
493510
FREESID(tilecache->tilesource_collect_sid, tilecache->tilesource);
494511
VIPS_UNREF(tilecache->tilesource);
@@ -503,6 +520,9 @@ tilecache_set_tilesource(Tilecache *tilecache, Tilesource *tilesource)
503520
tilecache->tilesource_changed_sid =
504521
g_signal_connect(tilesource, "changed",
505522
G_CALLBACK(tilecache_source_changed), tilecache);
523+
tilecache->tilesource_loaded_sid =
524+
g_signal_connect(tilesource, "loaded",
525+
G_CALLBACK(tilecache_source_loaded), tilecache);
506526
tilecache->tilesource_tiles_changed_sid =
507527
g_signal_connect(tilesource, "tiles-changed",
508528
G_CALLBACK(tilecache_source_tiles_changed), tilecache);
@@ -917,8 +937,8 @@ tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot,
917937
}
918938

919939
#ifdef DEBUG
920-
printf("tilecache_snapshot: scale = %g, x = %g, y = %g\n",
921-
scale, x, y);
940+
printf("tilecache_snapshot: %p scale = %g, x = %g, y = %g\n",
941+
tilecache, scale, x, y);
922942
#endif /*DEBUG*/
923943

924944
#ifdef DEBUG_VERBOSE
@@ -928,16 +948,19 @@ tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot,
928948
paint_rect->width, paint_rect->height);
929949
#endif /*DEBUG_VERBOSE*/
930950

951+
#ifdef DEBUG_VERBOSE
952+
printf("tilecache_snapshot: %p tiles are:\n", tilecache);
953+
tilecache_print(tilecache);
954+
#endif /*DEBUG_VERBOSE*/
955+
931956
/* Pick a pyramid layer. For enlarging, we leave the z at 0
932957
* (the highest res layer).
933958
*/
934959
if (scale > 1.0 ||
935960
scale == 0)
936961
z = 0;
937962
else
938-
z = VIPS_CLIP(0,
939-
log(1.0 / scale) / log(2.0),
940-
tilecache->n_levels - 1);
963+
z = VIPS_CLIP(0, log(1.0 / scale) / log(2.0), tilecache->n_levels - 1);
941964

942965
/* paint_rect in level0 coordinates.
943966
*/

src/tilecache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ typedef struct _Tilecache {
9090
/* The signals we watch tilesource with.
9191
*/
9292
guint tilesource_changed_sid;
93+
guint tilesource_loaded_sid;
9394
guint tilesource_tiles_changed_sid;
9495
guint tilesource_collect_sid;
9596

src/tilesource.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
*/
2929

3030
/*
31-
*/
3231
#define DEBUG_VERBOSE
3332
#define DEBUG
3433
#define DEBUG_MAKE
34+
*/
3535

3636
#include "nip4.h"
3737

@@ -64,6 +64,7 @@ enum {
6464
SIG_TILES_CHANGED,
6565
SIG_COLLECT,
6666
SIG_PAGE_CHANGED,
67+
SIG_LOADED,
6768

6869
SIG_LAST
6970
};
@@ -122,6 +123,12 @@ tilesource_page_changed(Tilesource *tilesource)
122123
g_signal_emit(tilesource, tilesource_signals[SIG_PAGE_CHANGED], 0);
123124
}
124125

126+
static void
127+
tilesource_loaded(Tilesource *tilesource)
128+
{
129+
g_signal_emit(tilesource, tilesource_signals[SIG_LOADED], 0);
130+
}
131+
125132
typedef struct _TilesourceUpdate {
126133
Tilesource *tilesource;
127134
VipsImage *image;
@@ -279,8 +286,7 @@ tilesource_display_image(Tilesource *tilesource, VipsImage **mask_out)
279286
/* There's a pyramid ... compute the size of image we need,
280287
* then find the layer which is one larger.
281288
*/
282-
int required_width =
283-
tilesource->display_width >> tilesource->current_z;
289+
int required_width = tilesource->width >> tilesource->current_z;
284290

285291
int i;
286292
int level;
@@ -417,10 +423,8 @@ tilesource_display_image(Tilesource *tilesource, VipsImage **mask_out)
417423
* some layer other than the base one. Calculate the
418424
* subsample as (current_width / required_width).
419425
*/
420-
int width =
421-
VIPS_MAX(1, tilesource->display_width >> tilesource->current_z);
422-
int height =
423-
VIPS_MAX(1, tilesource->display_height >> tilesource->current_z);
426+
int width = VIPS_MAX(1, tilesource->width >> tilesource->current_z);
427+
int height = VIPS_MAX(1, tilesource->height >> tilesource->current_z);
424428
int xfac = image->Xsize / width;
425429
int yfac = image->Ysize / height;
426430

@@ -1082,7 +1086,7 @@ tilesource_background_load_done_idle(void *user_data)
10821086
"visible", TRUE,
10831087
NULL);
10841088
tilesource_update_display(tilesource);
1085-
tilesource_changed(tilesource);
1089+
tilesource_loaded(tilesource);
10861090

10871091
/* Drop the ref that kept this tilesource alive during load, see
10881092
* tilesource_background_load().
@@ -1258,6 +1262,14 @@ tilesource_class_init(TilesourceClass *class)
12581262
g_cclosure_marshal_VOID__VOID,
12591263
G_TYPE_NONE, 0);
12601264

1265+
tilesource_signals[SIG_LOADED] = g_signal_new("loaded",
1266+
G_TYPE_FROM_CLASS(class),
1267+
G_SIGNAL_RUN_LAST,
1268+
G_STRUCT_OFFSET(TilesourceClass, loaded),
1269+
NULL, NULL,
1270+
g_cclosure_marshal_VOID__VOID,
1271+
G_TYPE_NONE, 0);
1272+
12611273
g_assert(!tilesource_background_load_pool);
12621274
tilesource_background_load_pool = g_thread_pool_new(
12631275
tilesource_background_load_worker,

src/tilesource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ typedef struct _TilesourceClass {
267267
*/
268268
void (*page_changed)(Tilesource *tilesource);
269269

270+
/* The image has loaded and you can fetch pixels (ie. you should repaint,
271+
* but don't invalidate any cache, since the pixels will not have changed
272+
* since last time).
273+
*/
274+
void (*loaded)(Tilesource *tilesource);
275+
270276
} TilesourceClass;
271277

272278
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Tilesource, g_object_unref)

0 commit comments

Comments
 (0)