1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

app: optimize the detection of filters with aux input.

As reported by Liam, apparently for someone with a lot of filters, these
node creations just to check the aux input may add up noticeable time on
boot (it may also depend on the OS too? I didn't have any noticeable
delay personally).

Unfortunately we cannot know the presence of an aux input just with
class introspection because they can be registered by the op at runtime.

This optimization is therefore twofold:

* Since we know which filters have an aux input among all the ones with
  hardcoded actions, we also hardcode this data. It means we only do the
  actual check on non-hardcoded operations (third-party filters but also
  GEGL operations which are not specifically listed in our code).
* I only do these checks once, stored by name in a hash table, because
  filters_actions_setup() is actually run several times (for different
  menus).

This should improve startup time a lot for people who experienced this
delay.
This commit is contained in:
Jehan
2025-09-03 18:17:57 +02:00
parent e4cb1e485e
commit 05e90b1cde
3 changed files with 59 additions and 36 deletions

View File

@@ -104,6 +104,7 @@
/* global variables */
GimpActionFactory *global_action_factory = NULL;
GHashTable *aux_filter_hash_table = NULL;
/* private variables */
@@ -270,6 +271,8 @@ actions_init (Gimp *gimp)
action_groups[i].icon_name,
action_groups[i].setup_func,
action_groups[i].update_func);
aux_filter_hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
void
@@ -280,6 +283,23 @@ actions_exit (Gimp *gimp)
g_return_if_fail (global_action_factory->gimp == gimp);
g_clear_object (&global_action_factory);
g_hash_table_unref (aux_filter_hash_table);
}
/* XXX Temporary code to store the list of filter operations with an
* "aux" input. This won't be necessary anymore once these filters can
* be applied non-destructively too in the future.
*/
void
actions_filter_set_aux (const gchar *action_name)
{
g_hash_table_add (aux_filter_hash_table, (gpointer) g_strdup (action_name));
}
gboolean
actions_filter_get_aux (const gchar *action_name)
{
return g_hash_table_lookup (aux_filter_hash_table, action_name) != NULL;
}
Gimp *

View File

@@ -24,6 +24,9 @@ extern GimpActionFactory *global_action_factory;
void actions_init (Gimp *gimp);
void actions_exit (Gimp *gimp);
void actions_filter_set_aux (const gchar *action_name);
gboolean actions_filter_get_aux (const gchar *action_name);
Gimp * action_data_get_gimp (gpointer data);
GimpContext * action_data_get_context (gpointer data);
GimpImage * action_data_get_image (gpointer data);

View File

@@ -754,10 +754,10 @@ static const GimpEnumActionEntry filters_repeat_actions[] =
void
filters_actions_setup (GimpActionGroup *group)
{
static gboolean first_setup = TRUE;
GimpProcedureActionEntry *entries;
gint n_entries;
gint i;
GList *actions;
GList *op_classes;
GList *iter;
GStrvBuilder *gegl_actions;
@@ -783,6 +783,21 @@ filters_actions_setup (GimpActionGroup *group)
filters_actions_set_tooltips (group, filters_interactive_actions,
G_N_ELEMENTS (filters_interactive_actions));
/* XXX Hardcoded list to prevent expensive node/graph creation of a
* well-known list of operations.
* This whole code will disappear when we'll support filters with aux
* input non-destructively anyway.
*/
if (first_setup)
{
actions_filter_set_aux ("filters-variable-blur");
actions_filter_set_aux ("filters-oilify");
actions_filter_set_aux ("filters-lens-blur");
actions_filter_set_aux ("filters-gaussian-blur-selective");
actions_filter_set_aux ("filters-displace");
actions_filter_set_aux ("filters-bump-map");
}
gegl_actions = g_strv_builder_new ();
op_classes = gimp_gegl_get_op_classes (TRUE);
@@ -868,6 +883,23 @@ filters_actions_setup (GimpActionGroup *group)
g_free (short_label);
}
/* Identify third-party filters based on operations with an
* auxiliary pad in first setup because of slowness on Windows.
* See #14781.
*/
if (first_setup)
{
GeglNode *node = gegl_node_new ();
gegl_node_set (node,
"operation", op_class->name,
NULL);
if (gegl_node_has_pad (node, "aux"))
actions_filter_set_aux (action_name);
g_clear_object (&node);
}
g_strv_builder_add (gegl_actions, action_name);
g_free (label);
@@ -882,40 +914,6 @@ filters_actions_setup (GimpActionGroup *group)
g_strv_builder_unref (gegl_actions);
g_list_free (op_classes);
/* Identify all filters based on operations with an auxiliary pad in
* setup because of slowness on Windows. See #14781.
*/
actions = gimp_action_group_list_actions (group);
for (iter = actions; iter; iter = iter->next)
{
GimpAction *action = iter->data;
const gchar *action_name;
action_name = gimp_action_get_name (action);
if (! filters_is_non_interactive (action_name) && GIMP_IS_STRING_ACTION (action))
{
const gchar *opname;
opname = GIMP_STRING_ACTION (action)->value;
if (opname != NULL && g_strcmp0 (opname, "gegl:gegl") != 0 && gegl_has_operation (opname))
{
GeglNode *node = gegl_node_new ();
gegl_node_set (node,
"operation", opname,
NULL);
if (gegl_node_has_pad (node, "aux"))
g_object_set_data (G_OBJECT (action), "filters-action-has-pad", GINT_TO_POINTER (TRUE));
g_clear_object (&node);
}
}
}
g_list_free (actions);
gimp_action_group_add_enum_actions (group, "filters-action",
filters_repeat_actions,
G_N_ELEMENTS (filters_repeat_actions),
@@ -951,6 +949,8 @@ filters_actions_setup (GimpActionGroup *group)
group, 0);
filters_actions_history_changed (group->gimp, group);
first_setup = FALSE;
}
void
@@ -1054,7 +1054,7 @@ filters_actions_update (GimpActionGroup *group,
* types of layers where filters can only be applied
* non-destructively.
*/
sensitive = ! GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "filters-action-has-pad"));
sensitive = ! actions_filter_get_aux (action_name);
SET_SENSITIVE (gimp_action_get_name (action), sensitive);
}