Compare commits

...

6 Commits

Author SHA1 Message Date
Carlos Garnacho
6dda417773 backends/input-mapper: Add some g_debug() traces to MetaInputMapper
Add some debug statements to mapping_helper_apply(), enough to work out
the heuristic decisions that were taken.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1202
2020-04-16 16:31:45 +02:00
Carlos Garnacho
d4bc355ee9 backends/input-mapper: Implement score mechanism to assign the most relevant output
We used to pick the "best" output for each builtin/size/edid categories,
and then pick the "best" (in that order) of those for each input device.
This is most often enough, but is prone to wrong results in some corner
cases (eg. 2 outputs with the exact same dimensions).

Change this to a score mechanism that doesn't leave outputs out. The
weights are the same, but the score is accumulated if an output matches
multiple categories. All outputs are evaluated and sorted by score, and
input devices with the best matches are applied first (as they already
did).

This should break the tie if eg. there's 2 outputs with similar dimensions,
but one of them has some EDID match in addition. The output with multiple
matches will score higher up, while it might have been entirely discarded
with the previous implementation.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1175

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1202
2020-04-16 16:31:14 +02:00
Thomas Hindoe Paaboel Andersen
d0ef660ff6 clutter: fix memleak in test error path
If clutter_init fails then we will not free state.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1195
2020-04-12 21:40:20 +00:00
Marco Trevisan (Treviño)
506e06589b test-utils: Only initialize client when we're returning it
test_client_new might return early if conditions are not met, leaving some
allocated data around without freeing it.

Since we're not using the client before, there's no need to initialize it early
and just initialize it when it's going to be returned.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1195
2020-04-12 21:40:20 +00:00
Marco Trevisan (Treviño)
1d75d5aa2f group: Free group if returning early
If we get an error when fetching the window attributes, the group isn't ever
free'd, so use an autopointer instead, releasing the stolen one.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1195
2020-04-12 21:40:20 +00:00
Marco Trevisan (Treviño)
645d596f9d cogl: Use autopointers to free structs on return
This is a potential leak discovered by static analysis, in fact if
_COGL_GET_CONTEXT returns, the newly allocated struct isn't released.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1195
2020-04-12 21:40:20 +00:00
7 changed files with 85 additions and 72 deletions

View File

@@ -74,7 +74,7 @@ PangoFontMap *
cogl_pango_font_map_new (void)
{
PangoFontMap *fm = pango_cairo_font_map_new ();
CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
g_autofree CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
_COGL_GET_CONTEXT (context, NULL);
@@ -85,7 +85,7 @@ cogl_pango_font_map_new (void)
* for now. */
g_object_set_qdata_full (G_OBJECT (fm),
cogl_pango_font_map_get_priv_key (),
priv,
g_steal_pointer (&priv),
free_priv);
return fm;

View File

@@ -93,10 +93,12 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
CoglOnscreen *
_cogl_onscreen_new (void)
{
CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
g_autofree CoglOnscreen *onscreen_ptr = g_new0 (CoglOnscreen, 1);
CoglOnscreen *onscreen;
_COGL_GET_CONTEXT (ctx, NULL);
onscreen = g_steal_pointer (&onscreen_ptr);
_cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
ctx,
COGL_FRAMEBUFFER_TYPE_ONSCREEN,

View File

@@ -50,7 +50,7 @@ struct _CoglPipelineCache
CoglPipelineCache *
_cogl_pipeline_cache_new (void)
{
CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
g_autofree CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
unsigned long vertex_state;
unsigned long layer_vertex_state;
unsigned int fragment_state;
@@ -80,7 +80,7 @@ _cogl_pipeline_cache_new (void)
layer_vertex_state | layer_fragment_state,
"programs");
return cache;
return g_steal_pointer (&cache);
}
void

View File

@@ -35,6 +35,7 @@ typedef struct _MetaMapperInputInfo MetaMapperInputInfo;
typedef struct _MetaMapperOutputInfo MetaMapperOutputInfo;
typedef struct _MappingHelper MappingHelper;
typedef struct _DeviceCandidates DeviceCandidates;
typedef struct _DeviceMatch DeviceMatch;
struct _MetaInputMapper
{
@@ -59,11 +60,11 @@ typedef enum
typedef enum
{
META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */
META_MATCH_SIZE, /* Size from input device and output match */
META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */
META_MATCH_EDID_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
META_MATCH_EDID_VENDOR, /* EDID vendor match, eg. "WAC" for Wacom */
META_MATCH_EDID_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */
META_MATCH_SIZE, /* Size from input device and output match */
META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */
N_OUTPUT_MATCHES
} MetaOutputMatchType;
@@ -87,13 +88,19 @@ struct _MappingHelper
GArray *device_maps;
};
struct _DeviceMatch
{
MetaMonitor *monitor;
uint32_t score;
};
struct _DeviceCandidates
{
MetaMapperInputInfo *input;
MetaMonitor *candidates[N_OUTPUT_MATCHES];
GArray *matches; /* Array of DeviceMatch */;
MetaOutputMatchType best;
int best;
};
enum
@@ -305,52 +312,37 @@ input_device_get_physical_size (MetaInputMapper *mapper,
}
static gboolean
find_size_match (MetaMapperInputInfo *input,
GList *monitors,
MetaMonitor **matched_monitor)
match_size (MetaMapperInputInfo *input,
MetaMonitor *monitor)
{
double min_w_diff, min_h_diff;
double w_diff, h_diff;
int o_width, o_height;
double i_width, i_height;
gboolean found = FALSE;
GList *l;
min_w_diff = min_h_diff = MAX_SIZE_MATCH_DIFF;
if (!input_device_get_physical_size (input->mapper, input->device,
&i_width, &i_height))
return FALSE;
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
double w_diff, h_diff;
int o_width, o_height;
meta_monitor_get_physical_dimensions (monitor, &o_width, &o_height);
w_diff = ABS (1 - ((double) o_width / i_width));
h_diff = ABS (1 - ((double) o_height / i_height));
meta_monitor_get_physical_dimensions (monitor, &o_width, &o_height);
w_diff = ABS (1 - ((double) o_width / i_width));
h_diff = ABS (1 - ((double) o_height / i_height));
if (w_diff >= min_w_diff || h_diff >= min_h_diff)
continue;
*matched_monitor = monitor;
min_w_diff = w_diff;
min_h_diff = h_diff;
found = TRUE;
}
return found;
return w_diff < MAX_SIZE_MATCH_DIFF && h_diff < MAX_SIZE_MATCH_DIFF;
}
static gboolean
find_builtin_output (MetaInputMapper *mapper,
MetaMonitor **matched_monitor)
match_builtin (MetaInputMapper *mapper,
MetaMonitor *monitor)
{
MetaMonitor *panel;
return monitor == meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
}
panel = meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
*matched_monitor = panel;
return panel != NULL;
static int
sort_by_score (DeviceMatch *match1,
DeviceMatch *match2)
{
return (int) match1->score - match2->score;
}
static void
@@ -358,36 +350,45 @@ guess_candidates (MetaInputMapper *mapper,
MetaMapperInputInfo *input,
DeviceCandidates *info)
{
MetaOutputMatchType best = N_OUTPUT_MATCHES;
GList *monitors, *l;
MetaMonitor *matched_monitor = NULL;
monitors = meta_monitor_manager_get_monitors (mapper->monitor_manager);
for (l = monitors; l; l = l->next)
{
MetaOutputMatchType edid_match;
DeviceMatch match = { l->data, 0 };
if (match_edid (input, l->data, &edid_match))
{
best = MIN (best, edid_match);
info->candidates[edid_match] = l->data;
}
match.score |= 1 << edid_match;
if (match_size (input, l->data))
match.score |= 1 << META_MATCH_SIZE;
if (input->builtin && match_builtin (mapper, l->data))
match.score |= 1 << META_MATCH_IS_BUILTIN;
if (match.score > 0)
g_array_append_val (info->matches, match);
}
if (find_size_match (input, monitors, &matched_monitor))
if (info->matches->len == 0)
{
best = MIN (best, META_MATCH_SIZE);
info->candidates[META_MATCH_SIZE] = matched_monitor;
}
DeviceMatch match = { 0 };
if (input->builtin || best == N_OUTPUT_MATCHES)
match.monitor =
meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
g_array_append_val (info->matches, match);
info->best = 0;
}
else
{
best = MIN (best, META_MATCH_IS_BUILTIN);
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
}
DeviceMatch *best;
info->best = best;
g_array_sort (info->matches, (GCompareFunc) sort_by_score);
best = &g_array_index (info->matches, DeviceMatch, 0);
info->best = best->score;
}
}
static void
@@ -399,6 +400,7 @@ mapping_helper_add (MappingHelper *helper,
guint i, pos = 0;
info.input = input;
info.matches = g_array_new (FALSE, TRUE, sizeof (DeviceMatch));
guess_candidates (mapper, input, &info);
@@ -408,7 +410,7 @@ mapping_helper_add (MappingHelper *helper,
elem = &g_array_index (helper->device_maps, DeviceCandidates, i);
if (elem->best < info.best)
if (elem->best > info.best)
pos = i;
}
@@ -422,26 +424,32 @@ static void
mapping_helper_apply (MappingHelper *helper,
MetaInputMapper *mapper)
{
guint i;
guint i, j;
/* Now, decide which input claims which output */
for (i = 0; i < helper->device_maps->len; i++)
{
MetaMapperOutputInfo *output;
DeviceCandidates *info;
MetaOutputMatchType j;
MetaMonitor *monitor;
info = &g_array_index (helper->device_maps, DeviceCandidates, i);
g_debug ("Applying mapping %d to input device '%s', capabilities %x", i,
clutter_input_device_get_device_name (info->input->device),
mapper_input_info_get_caps (info->input));
for (j = 0; j < N_OUTPUT_MATCHES; j++)
for (j = 0; j < info->matches->len; j++)
{
MetaLogicalMonitor *logical_monitor;
DeviceMatch *match;
if (!info->candidates[j])
continue;
match = &g_array_index (info->matches, DeviceMatch, j);
g_debug ("Output candidate '%s', score %x",
meta_monitor_get_display_name (match->monitor),
match->score);
logical_monitor =
meta_monitor_get_logical_monitor (info->candidates[j]);
monitor = match->monitor;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
output = g_hash_table_lookup (mapper->output_devices,
logical_monitor);
@@ -451,8 +459,10 @@ mapping_helper_apply (MappingHelper *helper,
if (output->attached_caps & mapper_input_info_get_caps (info->input))
continue;
mapper_output_info_add_input (output, info->input,
info->candidates[j]);
g_debug ("Matched input '%s' with output '%s'",
clutter_input_device_get_device_name (info->input->device),
meta_monitor_get_display_name (match->monitor));
mapper_output_info_add_input (output, info->input, monitor);
break;
}
}

View File

@@ -112,7 +112,7 @@ test_cogl_multitexture_main (int argc, char *argv[])
GError *error = NULL;
ClutterActor *stage;
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
g_autofree TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
gfloat stage_w, stage_h;
gchar **files;
gfloat tex_coords[] =

View File

@@ -427,7 +427,7 @@ test_client_new (const char *id,
MetaWindowClientType type,
GError **error)
{
TestClient *client = g_new0 (TestClient, 1);
TestClient *client;
GSubprocessLauncher *launcher;
GSubprocess *subprocess;
MetaWaylandCompositor *compositor;
@@ -462,6 +462,7 @@ test_client_new (const char *id,
if (!subprocess)
return NULL;
client = g_new0 (TestClient, 1);
client->type = type;
client->id = g_strdup (id);
client->cancellable = g_cancellable_new ();

View File

@@ -41,7 +41,7 @@ static MetaGroup*
meta_group_new (MetaX11Display *x11_display,
Window group_leader)
{
MetaGroup *group;
g_autofree MetaGroup *group = NULL;
#define N_INITIAL_PROPS 3
Atom initial_props[N_INITIAL_PROPS];
int i;
@@ -91,7 +91,7 @@ meta_group_new (MetaX11Display *x11_display,
"Created new group with leader 0x%lx\n",
group->group_leader);
return group;
return g_steal_pointer (&group);
}
static void