onscreen/native: Hold output and CRTC refs until dispose
We relied on them being valid longer to keep track of used GPUs. If we
don't have the CRTC (or output) we don't have a way to fetch the pointer
to the MetaGpu that drives the associated monitor.
This avoids a crash when trying to fetch said pointer from what would be
the NULL MetaCrtc pointer.
Fixes: 08593ea872
("onscreen/native: Hold ref to the output and CRTC until detached")
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2667
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2887>
This commit is contained in:
parent
3d28e03a29
commit
995f9f9db8
3 changed files with 129 additions and 2 deletions
|
@ -2334,6 +2334,9 @@ meta_onscreen_native_dispose (GObject *object)
|
|||
g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy);
|
||||
g_clear_pointer (&onscreen_native->secondary_gpu_state,
|
||||
secondary_gpu_state_free);
|
||||
|
||||
g_clear_object (&onscreen_native->output);
|
||||
g_clear_object (&onscreen_native->crtc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2369,6 +2372,4 @@ void
|
|||
meta_onscreen_native_detach (MetaOnscreenNative *onscreen_native)
|
||||
{
|
||||
clear_invalidation_handlers (onscreen_native);
|
||||
g_clear_object (&onscreen_native->output);
|
||||
g_clear_object (&onscreen_native->crtc);
|
||||
}
|
||||
|
|
|
@ -398,6 +398,16 @@ if have_native_tests
|
|||
'suite': 'backend/native/kms',
|
||||
'sources': [ 'native-kms-headless-start.c', ],
|
||||
},
|
||||
{
|
||||
'name': 'kms-hotplug',
|
||||
'suite': 'backends/native/kms',
|
||||
'sources': [
|
||||
'meta-kms-test-utils.c',
|
||||
'meta-kms-test-utils.h',
|
||||
'native-kms-hotplug.c',
|
||||
],
|
||||
'variants': kms_test_variants,
|
||||
},
|
||||
]
|
||||
|
||||
privileged_test_cases += kms_test_cases
|
||||
|
|
116
src/tests/native-kms-hotplug.c
Normal file
116
src/tests/native-kms-hotplug.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "backends/meta-monitor-manager-private.h"
|
||||
#include "meta-test/meta-context-test.h"
|
||||
|
||||
typedef enum _State
|
||||
{
|
||||
INIT,
|
||||
PAINTED,
|
||||
PRESENTED,
|
||||
} State;
|
||||
|
||||
static MetaContext *test_context;
|
||||
|
||||
static void
|
||||
on_after_paint (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
ClutterFrame *frame,
|
||||
State *state)
|
||||
{
|
||||
*state = PAINTED;
|
||||
}
|
||||
|
||||
static void
|
||||
on_presented (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
ClutterFrameInfo *frame_info,
|
||||
State *state)
|
||||
{
|
||||
if (*state == PAINTED)
|
||||
*state = PRESENTED;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_reload (void)
|
||||
{
|
||||
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
GList *logical_monitors;
|
||||
gulong after_paint_handler_id;
|
||||
gulong presented_handler_id;
|
||||
g_autoptr (GError) error = NULL;
|
||||
State state;
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
g_assert_cmpuint (g_list_length (logical_monitors), ==, 1);
|
||||
|
||||
after_paint_handler_id = g_signal_connect (stage, "after-paint",
|
||||
G_CALLBACK (on_after_paint),
|
||||
&state);
|
||||
presented_handler_id = g_signal_connect (stage, "presented",
|
||||
G_CALLBACK (on_presented),
|
||||
&state);
|
||||
|
||||
state = INIT;
|
||||
clutter_actor_queue_redraw (stage);
|
||||
while (state < PAINTED)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
meta_monitor_manager_reload (monitor_manager);
|
||||
|
||||
while (state < PRESENTED)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
state = INIT;
|
||||
clutter_actor_queue_redraw (stage);
|
||||
while (state < PRESENTED)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
g_signal_handler_disconnect (stage, after_paint_handler_id);
|
||||
g_signal_handler_disconnect (stage, presented_handler_id);
|
||||
}
|
||||
|
||||
static void
|
||||
init_tests (void)
|
||||
{
|
||||
g_test_add_func ("/hotplug/reload",
|
||||
meta_test_reload);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_autoptr (MetaContext) context = NULL;
|
||||
|
||||
context = meta_create_test_context (META_CONTEXT_TEST_TYPE_VKMS,
|
||||
META_CONTEXT_TEST_FLAG_NO_X11);
|
||||
g_assert (meta_context_configure (context, &argc, &argv, NULL));
|
||||
|
||||
init_tests ();
|
||||
|
||||
test_context = context;
|
||||
|
||||
return meta_context_test_run_tests (META_CONTEXT_TEST (context),
|
||||
META_TEST_RUN_FLAG_NONE);
|
||||
}
|
Loading…
Reference in a new issue