mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 05:12:15 +00:00
kms: Use a kernel thread by default
Also add an API to inhibit the kernel thread from being used, and make MetaRenderDeviceEglStream inhibit the kernel thread from being used if it's active. The reason for this is that the MetaRenderDeviceEGlStream is used when using EGLStreams instead of KMS for page flipping. This means the actual page flipping happens as a side effect of using EGL/OpenGL, which can't easily be done off thread. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
parent
788ad43e17
commit
276ebbf5ee
@ -152,6 +152,8 @@ struct _MetaKms
|
||||
|
||||
GList *pending_callbacks;
|
||||
guint callback_source_id;
|
||||
|
||||
int kernel_thread_inhibit_count;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaKms, meta_kms, META_TYPE_THREAD)
|
||||
@ -441,7 +443,7 @@ meta_kms_new (MetaBackend *backend,
|
||||
MetaUdev *udev = meta_backend_native_get_udev (backend_native);
|
||||
MetaKms *kms;
|
||||
const char *thread_type_string;
|
||||
MetaThreadType thread_type = META_THREAD_TYPE_USER;
|
||||
MetaThreadType thread_type = META_THREAD_TYPE_KERNEL;
|
||||
|
||||
thread_type_string = g_getenv ("MUTTER_DEBUG_KMS_THREAD_TYPE");
|
||||
if (thread_type_string)
|
||||
@ -532,3 +534,23 @@ meta_kms_emit_resources_changed (MetaKms *kms,
|
||||
{
|
||||
g_signal_emit (kms, signals[RESOURCES_CHANGED], 0, changes);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_inhibit_kernel_thread (MetaKms *kms)
|
||||
{
|
||||
kms->kernel_thread_inhibit_count++;
|
||||
|
||||
if (kms->kernel_thread_inhibit_count == 1)
|
||||
meta_thread_reset_thread_type (META_THREAD (kms), META_THREAD_TYPE_USER);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_uninhibit_kernel_thread (MetaKms *kms)
|
||||
{
|
||||
g_return_if_fail (kms->kernel_thread_inhibit_count > 0);
|
||||
|
||||
kms->kernel_thread_inhibit_count--;
|
||||
|
||||
if (kms->kernel_thread_inhibit_count == 0)
|
||||
meta_thread_reset_thread_type (META_THREAD (kms), META_THREAD_TYPE_KERNEL);
|
||||
}
|
||||
|
@ -56,4 +56,10 @@ MetaKms * meta_kms_new (MetaBackend *backend,
|
||||
MetaKmsFlags flags,
|
||||
GError **error);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_inhibit_kernel_thread (MetaKms *kms);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_uninhibit_kernel_thread (MetaKms *kms);
|
||||
|
||||
#endif /* META_KMS_H */
|
||||
|
@ -23,11 +23,15 @@
|
||||
#include "backends/native/meta-render-device-egl-stream.h"
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-kms.h"
|
||||
|
||||
struct _MetaRenderDeviceEglStream
|
||||
{
|
||||
MetaRenderDevice parent;
|
||||
|
||||
gboolean inhibited_kms_kernel_thread;
|
||||
|
||||
EGLDeviceEXT egl_device;
|
||||
};
|
||||
|
||||
@ -169,6 +173,7 @@ meta_render_device_egl_stream_initable_init (GInitable *initable,
|
||||
MetaRenderDeviceEglStream *render_device_egl_stream =
|
||||
META_RENDER_DEVICE_EGL_STREAM (initable);
|
||||
MetaBackend *backend = meta_render_device_get_backend (render_device);
|
||||
MetaKms *kms;
|
||||
EGLDeviceEXT egl_device;
|
||||
EGLDisplay egl_display;
|
||||
g_autofree const char **missing_extensions = NULL;
|
||||
@ -198,6 +203,10 @@ meta_render_device_egl_stream_initable_init (GInitable *initable,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend));
|
||||
meta_kms_inhibit_kernel_thread (kms);
|
||||
render_device_egl_stream->inhibited_kms_kernel_thread = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -259,11 +268,32 @@ meta_render_device_egl_stream_create_egl_display (MetaRenderDevice *render_devi
|
||||
return egl_display;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_render_device_egl_stream_finalize (GObject *object)
|
||||
{
|
||||
MetaRenderDevice *render_device = META_RENDER_DEVICE (object);
|
||||
MetaRenderDeviceEglStream *render_device_egl_stream =
|
||||
META_RENDER_DEVICE_EGL_STREAM (render_device);
|
||||
|
||||
if (render_device_egl_stream->inhibited_kms_kernel_thread)
|
||||
{
|
||||
MetaBackend *backend = meta_render_device_get_backend (render_device);
|
||||
MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend));
|
||||
|
||||
meta_kms_uninhibit_kernel_thread (kms);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_render_device_egl_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_render_device_egl_stream_class_init (MetaRenderDeviceEglStreamClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaRenderDeviceClass *render_device_class = META_RENDER_DEVICE_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_render_device_egl_stream_finalize;
|
||||
|
||||
render_device_class->create_egl_display =
|
||||
meta_render_device_egl_stream_create_egl_display;
|
||||
}
|
||||
|
@ -448,6 +448,16 @@ if have_native_tests
|
||||
],
|
||||
'variants': [['', test_env_variables + kms_thread_user_variables]],
|
||||
},
|
||||
{
|
||||
'name': 'kms',
|
||||
'suite': 'backends/native/kms',
|
||||
'sources': [
|
||||
#'meta-kms-test-utils.c',
|
||||
#'meta-kms-test-utils.h',
|
||||
'native-kms.c',
|
||||
],
|
||||
'variants': [['', test_env_variables ]],
|
||||
},
|
||||
{
|
||||
'name': 'kms-render',
|
||||
'suite': 'backends/native/kms',
|
||||
|
110
src/tests/native-kms.c
Normal file
110
src/tests/native-kms.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Red Hat Inc.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-kms.h"
|
||||
#include "meta-test/meta-context-test.h"
|
||||
//#include "tests/meta-kms-test-utils.h"
|
||||
|
||||
static MetaContext *test_context;
|
||||
|
||||
static gpointer
|
||||
assert_not_thread (MetaThreadImpl *thread_impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
GThread **thread_to_check = user_data;
|
||||
|
||||
g_assert (g_steal_pointer (thread_to_check) != g_thread_self ());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
assert_thread (MetaThreadImpl *thread_impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
GThread **thread_to_check = user_data;
|
||||
|
||||
g_assert (g_steal_pointer (thread_to_check) == g_thread_self ());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_kms_inhibit_kernel_thread (void)
|
||||
{
|
||||
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||
MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend));
|
||||
MetaThread *thread = META_THREAD (kms);
|
||||
GThread *main_thread;
|
||||
GThread *test_thread;
|
||||
|
||||
main_thread = g_thread_self ();
|
||||
|
||||
test_thread = main_thread;
|
||||
meta_thread_post_impl_task (thread, assert_not_thread, &test_thread, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
meta_kms_inhibit_kernel_thread (kms);
|
||||
g_assert_null (test_thread);
|
||||
|
||||
test_thread = main_thread;
|
||||
meta_thread_post_impl_task (thread, assert_thread, &test_thread, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
meta_kms_uninhibit_kernel_thread (kms);
|
||||
g_assert_null (test_thread);
|
||||
|
||||
test_thread = main_thread;
|
||||
meta_thread_post_impl_task (thread, assert_not_thread, &test_thread, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
while (test_thread)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
init_tests (void)
|
||||
{
|
||||
g_test_add_func ("/backends/native/kms/inhibit-kernel-thread",
|
||||
meta_test_kms_inhibit_kernel_thread);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
g_autoptr (MetaContext) context = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
context = test_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 ();
|
||||
|
||||
return meta_context_test_run_tests (META_CONTEXT_TEST (context),
|
||||
META_TEST_RUN_FLAG_CAN_SKIP);
|
||||
}
|
Loading…
Reference in New Issue
Block a user