Skip to content

Commit cdf6e03

Browse files
masterpigaTurboGit
authored andcommitted
Re-introduce previously reverted raster mask release fix
1 parent 49de409 commit cdf6e03

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

‎src/develop/pixelpipe_hb.c‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,81 @@ static void _dev_pixelpipe_synch(dt_dev_pixelpipe_t *pipe,
640640
}
641641
}
642642

643+
/** remove stale entries (deleted, disabled or de-synced consumers) from a
644+
raster mask source's users table, so it doesn't keep
645+
publishing/invalidating forever */
646+
static void _iop_prune_stale_raster_users(dt_dev_pixelpipe_t *pipe, dt_iop_module_t *module)
647+
{
648+
GHashTable *users = module->raster_mask.source.users;
649+
if(!module->dev || !users || g_hash_table_size(users) == 0)
650+
return;
651+
652+
/* Phantom users (deleted or de-synced consumers) keep the source republishing
653+
-- and invalidating downstream -- every run. Judge each consumer from its
654+
node in THIS pipe, never from module->enabled/blend_params: those track the
655+
darkroom UI and are stale in the export pipe, where the piece is authoritative
656+
(dropped a live export consumer's mask, regression 0167-raster-mask). We only
657+
compare the consumer pointer, so a freed module is never dereferenced. */
658+
GHashTableIter iter;
659+
gpointer key, value;
660+
g_hash_table_iter_init(&iter, users);
661+
while(g_hash_table_iter_next(&iter, &key, &value))
662+
{
663+
dt_iop_module_t *sink = key;
664+
665+
// locate the consumer's node in this pipe (pointer-only match)
666+
dt_dev_pixelpipe_iop_t *sink_piece = NULL;
667+
for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
668+
{
669+
dt_dev_pixelpipe_iop_t *p = nodes->data;
670+
if(p->module == sink)
671+
{
672+
sink_piece = p;
673+
break;
674+
}
675+
}
676+
if(!sink_piece)
677+
{
678+
g_hash_table_iter_remove(&iter);
679+
dt_print_pipe(DT_DEBUG_PIPE | DT_DEBUG_MASKS,
680+
"prune stale raster user",
681+
pipe,
682+
module,
683+
DT_DEVICE_NONE,
684+
NULL,
685+
NULL,
686+
"dropped deleted consumer");
687+
continue;
688+
}
689+
690+
// a real consumer must still point back at us, have its node enabled in
691+
// this pipe, and actually have its blending in raster-mask mode. A module
692+
// that named us as raster source but is then disabled (or switched its mask
693+
// to drawn/parametric) leaves a phantom entry that would otherwise keep us
694+
// publishing -- and invalidating every downstream cacheline -- on every run.
695+
const dt_develop_blend_params_t *bp = sink_piece->blendop_data;
696+
const gboolean consumes = sink->raster_mask.sink.source == module && sink_piece->enabled &&
697+
bp && (bp->mask_mode & DEVELOP_MASK_RASTER);
698+
if(!consumes)
699+
{
700+
g_hash_table_iter_remove(&iter);
701+
dt_print_pipe(DT_DEBUG_PIPE | DT_DEBUG_MASKS,
702+
"prune stale raster user",
703+
pipe,
704+
module,
705+
DT_DEVICE_NONE,
706+
NULL,
707+
NULL,
708+
"dropped '%s%s' (%s)",
709+
sink->op,
710+
dt_iop_get_instance_id(sink),
711+
sink->raster_mask.sink.source != module ? "de-synced"
712+
: !sink_piece->enabled ? "disabled"
713+
: "not in raster mode");
714+
}
715+
}
716+
}
717+
643718
void dt_dev_pixelpipe_synch_all(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
644719
{
645720
dt_pthread_mutex_lock(&pipe->busy_mutex);
@@ -675,6 +750,12 @@ void dt_dev_pixelpipe_synch_all(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
675750
_dev_pixelpipe_synch(pipe, dev, history);
676751
history = g_list_next(history);
677752
}
753+
754+
// history has been (re)applied, so real raster consumers have re-registered;
755+
// drop any phantom users left behind by deleted or de-synced consumers
756+
for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
757+
_iop_prune_stale_raster_users(pipe, ((dt_dev_pixelpipe_iop_t *)nodes->data)->module);
758+
678759
dt_print_pipe(DT_DEBUG_PARAMS,
679760
"synch all modules done",
680761
pipe, NULL, DT_DEVICE_NONE, NULL, NULL,
@@ -699,6 +780,12 @@ void dt_dev_pixelpipe_synch_top(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
699780
dt_print_pipe(DT_DEBUG_PARAMS, "synch top history module missing!",
700781
pipe, NULL, DT_DEVICE_NONE, NULL, NULL);
701782
}
783+
784+
// clear any phantom raster users (deleted/de-synced consumers) so a source
785+
// doesn't keep republishing its mask and invalidating downstream every run
786+
for(GList *nodes = pipe->nodes; nodes; nodes = g_list_next(nodes))
787+
_iop_prune_stale_raster_users(pipe, ((dt_dev_pixelpipe_iop_t *)nodes->data)->module);
788+
702789
dt_pthread_mutex_unlock(&pipe->busy_mutex);
703790
}
704791

0 commit comments

Comments
 (0)