Update to 45.1

This commit is contained in:
Florian Müllner 2023-11-01 01:16:16 +01:00
parent cb6d6e8835
commit efea9ab023
11 changed files with 3 additions and 1661 deletions

1
.gitignore vendored
View File

@ -213,3 +213,4 @@ mutter-2.31.5.tar.bz2
/mutter-45.beta.1.tar.xz
/mutter-45.rc.tar.xz
/mutter-45.0.tar.xz
/mutter-45.1.tar.xz

View File

@ -1,149 +0,0 @@
From 01c01a221a7dabb2382a44b71dcf06649ee193d6 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Oct 2023 14:35:46 -0400
Subject: [PATCH 1/4] thread: For consistency, s/real_time/realtime/
Most of the code writes "real-time" as "realtime" not "real_time".
The only exception is one function `request_real_time_scheduling`.
This commit changes that function for consistency.
---
src/backends/native/meta-thread.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backends/native/meta-thread.c b/src/backends/native/meta-thread.c
index 08d01144d..93a84a8a5 100644
--- a/src/backends/native/meta-thread.c
+++ b/src/backends/native/meta-thread.c
@@ -175,62 +175,62 @@ get_rtkit_property (MetaDBusRealtimeKit1 *rtkit_proxy,
{
GDBusConnection *connection;
g_autoptr (GVariant) prop_value = NULL;
g_autoptr (GVariant) property_variant = NULL;
/* The following is a fall back path for a RTKit daemon that doesn't support
* org.freedesktop.DBus.Properties.GetAll. See
* <https://github.com/heftig/rtkit/pull/30>.
*/
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (rtkit_proxy));
prop_value =
g_dbus_connection_call_sync (connection,
"org.freedesktop.RealtimeKit1",
"/org/freedesktop/RealtimeKit1",
"org.freedesktop.DBus.Properties",
"Get",
g_variant_new ("(ss)",
"org.freedesktop.RealtimeKit1",
property_name),
G_VARIANT_TYPE ("(v)"),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1, NULL, error);
if (!prop_value)
return NULL;
g_variant_get (prop_value, "(v)", &property_variant);
return g_steal_pointer (&property_variant);
}
static gboolean
-request_real_time_scheduling (MetaThread *thread,
- GError **error)
+request_realtime_scheduling (MetaThread *thread,
+ GError **error)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
g_autoptr (MetaDBusRealtimeKit1) rtkit_proxy = NULL;
g_autoptr (GError) local_error = NULL;
int64_t rttime;
struct rlimit rl;
uint32_t priority;
rtkit_proxy =
meta_dbus_realtime_kit1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.RealtimeKit1",
"/org/freedesktop/RealtimeKit1",
NULL,
&local_error);
if (!rtkit_proxy)
{
g_dbus_error_strip_remote_error (local_error);
g_propagate_prefixed_error (error, g_steal_pointer (&local_error),
"Failed to acquire RTKit D-Bus proxy: ");
return FALSE;
}
priority = meta_dbus_realtime_kit1_get_max_realtime_priority (rtkit_proxy);
if (priority == 0)
{
g_autoptr (GVariant) priority_variant = NULL;
priority_variant = get_rtkit_property (rtkit_proxy,
@@ -286,61 +286,61 @@ request_real_time_scheduling (MetaThread *thread,
return TRUE;
}
static gpointer
thread_impl_func (gpointer user_data)
{
MetaThread *thread = META_THREAD (user_data);
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
MetaThreadImpl *impl = priv->impl;
MetaThreadImplRunFlags run_flags = META_THREAD_IMPL_RUN_FLAG_NONE;
GMainContext *thread_context = meta_thread_impl_get_main_context (impl);
#ifdef HAVE_PROFILER
MetaContext *context = meta_backend_get_context (priv->backend);
MetaProfiler *profiler = meta_context_get_profiler (context);
#endif
g_mutex_lock (&priv->kernel.init_mutex);
g_mutex_unlock (&priv->kernel.init_mutex);
g_main_context_push_thread_default (thread_context);
#ifdef HAVE_PROFILER
meta_profiler_register_thread (profiler, thread_context, priv->name);
#endif
if (priv->wants_realtime)
{
g_autoptr (GError) error = NULL;
- if (!request_real_time_scheduling (thread, &error))
+ if (!request_realtime_scheduling (thread, &error))
{
g_warning ("Failed to make thread '%s' realtime scheduled: %s",
priv->name, error->message);
}
else
{
g_message ("Made thread '%s' realtime scheduled", priv->name);
run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME;
}
}
meta_thread_impl_run (impl, run_flags);
#ifdef HAVE_PROFILER
meta_profiler_unregister_thread (profiler, thread_context);
#endif
g_main_context_pop_thread_default (thread_context);
return GINT_TO_POINTER (TRUE);
}
typedef struct _WrapperSource
{
GSource base;
GMainContext *thread_main_context;
GPollFD fds[256];
gpointer fd_tags[256];
--
2.41.0

View File

@ -1,65 +0,0 @@
From 742316746d50084dda4ebda5ad081e59451e3256 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 11 Oct 2023 09:37:54 -0400
Subject: [PATCH 2/4] tests/dbusmock-templates/rtkit: Add
MakeThreadHighPriority
mutter will soon need to call an additional method in RTKit,
MakeThreadHighPriority.
In preparation for that, this commit stubs it out in the
dbusmock template.
---
src/tests/dbusmock-templates/rtkit.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/tests/dbusmock-templates/rtkit.py b/src/tests/dbusmock-templates/rtkit.py
index 168582de8..766bd681e 100644
--- a/src/tests/dbusmock-templates/rtkit.py
+++ b/src/tests/dbusmock-templates/rtkit.py
@@ -1,38 +1,42 @@
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option) any
# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text
# of the license.
__author__ = 'Jonas Ådahl'
__copyright__ = '(c) 2022 Red Hat Inc.'
import dbus
from dbusmock import MOCK_IFACE, mockobject
BUS_NAME = 'org.freedesktop.RealtimeKit1'
MAIN_OBJ = '/org/freedesktop/RealtimeKit1'
MAIN_IFACE = 'org.freedesktop.RealtimeKit1'
SYSTEM_BUS = True
def load(mock, parameters):
mock.AddProperty(MAIN_IFACE, 'RTTimeUSecMax', dbus.Int64(200000))
mock.AddProperty(MAIN_IFACE, 'MaxRealtimePriority', dbus.Int32(20))
mock.AddProperty(MAIN_IFACE, 'MinNiceLevel', dbus.Int32(-15))
mock.priorities = dict()
@dbus.service.method(MAIN_IFACE, in_signature='tu')
def MakeThreadRealtime(self, thread, priority):
self.priorities[thread] = priority
+@dbus.service.method(MAIN_IFACE, in_signature='tu')
+def MakeThreadHighPriority(self, thread, priority):
+ self.priorities[thread] = priority
+
@dbus.service.method(MOCK_IFACE)
def Reset(self):
self.priorities = dict()
@dbus.service.method(MOCK_IFACE, in_signature='t', out_signature='u')
def GetThreadPriority(self, thread):
if thread in self.priorities:
return self.priorities[thread]
else:
return 0
--
2.41.0

View File

@ -1,580 +0,0 @@
From a7c0f106b30137e1fc6159eaecee8e61b8dc48a9 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Oct 2023 14:39:13 -0400
Subject: [PATCH 3/4] thread: Allow turning off rt scheduling for running
thread
At the moment if a thread is made real-time there's no going back,
it stays real-time for the duration of its life.
That's suboptimal because real-time threads are expected by RTKit to
have an rlimit on their CPU time and certain GPU drivers in the kernel
can exceed that CPU time during certain operations like DPMS off.
This commit adds two new ref counted functions:
meta_thread_{un,}inhibit_realtime_in_impl
that allow turning a thread real-time or normally scheduled. At the same
time, this commit stores the RTKit proxy as private data on the thread
so that it can be reused by the above apis.
A subsequent commit will use the new APIs.
---
src/backends/native/meta-thread.c | 189 ++++++++++++++++++++++++++----
src/backends/native/meta-thread.h | 3 +
2 files changed, 168 insertions(+), 24 deletions(-)
diff --git a/src/backends/native/meta-thread.c b/src/backends/native/meta-thread.c
index 93a84a8a5..1ed30441d 100644
--- a/src/backends/native/meta-thread.c
+++ b/src/backends/native/meta-thread.c
@@ -56,62 +56,66 @@ typedef struct _MetaThreadCallbackSource
GMutex mutex;
GCond cond;
MetaThread *thread;
GMainContext *main_context;
GList *callbacks;
gboolean needs_flush;
} MetaThreadCallbackSource;
typedef struct _MetaThreadPrivate
{
MetaBackend *backend;
char *name;
GMainContext *main_context;
MetaThreadImpl *impl;
gboolean wants_realtime;
gboolean waiting_for_impl_task;
GSource *wrapper_source;
GMutex callbacks_mutex;
GHashTable *callback_sources;
MetaThreadType thread_type;
GThread *main_thread;
struct {
+ MetaDBusRealtimeKit1 *rtkit_proxy;
GThread *thread;
+ pid_t thread_id;
GMutex init_mutex;
+ int realtime_inhibit_count;
+ gboolean is_realtime;
} kernel;
} MetaThreadPrivate;
typedef struct _MetaThreadClassPrivate
{
GType impl_type;
} MetaThreadClassPrivate;
static void initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_TYPE_WITH_CODE (MetaThread, meta_thread, G_TYPE_OBJECT,
G_ADD_PRIVATE (MetaThread)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init)
g_type_add_class_private (g_define_type_id,
sizeof (MetaThreadClassPrivate)))
static void
meta_thread_callback_data_free (MetaThreadCallbackData *callback_data)
{
if (callback_data->user_data_destroy)
callback_data->user_data_destroy (callback_data->user_data);
g_free (callback_data);
}
static void
meta_thread_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
@@ -175,181 +179,278 @@ get_rtkit_property (MetaDBusRealtimeKit1 *rtkit_proxy,
{
GDBusConnection *connection;
g_autoptr (GVariant) prop_value = NULL;
g_autoptr (GVariant) property_variant = NULL;
/* The following is a fall back path for a RTKit daemon that doesn't support
* org.freedesktop.DBus.Properties.GetAll. See
* <https://github.com/heftig/rtkit/pull/30>.
*/
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (rtkit_proxy));
prop_value =
g_dbus_connection_call_sync (connection,
"org.freedesktop.RealtimeKit1",
"/org/freedesktop/RealtimeKit1",
"org.freedesktop.DBus.Properties",
"Get",
g_variant_new ("(ss)",
"org.freedesktop.RealtimeKit1",
property_name),
G_VARIANT_TYPE ("(v)"),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1, NULL, error);
if (!prop_value)
return NULL;
g_variant_get (prop_value, "(v)", &property_variant);
return g_steal_pointer (&property_variant);
}
static gboolean
-request_realtime_scheduling (MetaThread *thread,
- GError **error)
+ensure_realtime_kit_proxy (MetaThread *thread,
+ GError **error)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
g_autoptr (MetaDBusRealtimeKit1) rtkit_proxy = NULL;
g_autoptr (GError) local_error = NULL;
- int64_t rttime;
- struct rlimit rl;
- uint32_t priority;
+
+ if (priv->kernel.rtkit_proxy)
+ return TRUE;
rtkit_proxy =
meta_dbus_realtime_kit1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.RealtimeKit1",
"/org/freedesktop/RealtimeKit1",
NULL,
&local_error);
if (!rtkit_proxy)
{
g_dbus_error_strip_remote_error (local_error);
g_propagate_prefixed_error (error, g_steal_pointer (&local_error),
"Failed to acquire RTKit D-Bus proxy: ");
return FALSE;
}
- priority = meta_dbus_realtime_kit1_get_max_realtime_priority (rtkit_proxy);
+ priv->kernel.rtkit_proxy = g_steal_pointer (&rtkit_proxy);
+ return TRUE;
+}
+
+static gboolean
+request_realtime_scheduling (MetaThread *thread,
+ GError **error)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+ g_autoptr (GError) local_error = NULL;
+ int64_t rttime;
+ struct rlimit rl;
+ uint32_t priority;
+
+ if (!ensure_realtime_kit_proxy (thread, error))
+ return FALSE;
+
+ priority = meta_dbus_realtime_kit1_get_max_realtime_priority (priv->kernel.rtkit_proxy);
if (priority == 0)
{
g_autoptr (GVariant) priority_variant = NULL;
- priority_variant = get_rtkit_property (rtkit_proxy,
+ priority_variant = get_rtkit_property (priv->kernel.rtkit_proxy,
"MaxRealtimePriority",
error);
if (!priority_variant)
return FALSE;
priority = g_variant_get_int32 (priority_variant);
}
if (priority == 0)
g_warning ("Maximum real time scheduling priority is 0");
- rttime = meta_dbus_realtime_kit1_get_rttime_usec_max (rtkit_proxy);
+ rttime = meta_dbus_realtime_kit1_get_rttime_usec_max (priv->kernel.rtkit_proxy);
if (rttime == 0)
{
g_autoptr (GVariant) rttime_variant = NULL;
- rttime_variant = get_rtkit_property (rtkit_proxy,
+ rttime_variant = get_rtkit_property (priv->kernel.rtkit_proxy,
"RTTimeUSecMax",
error);
if (!rttime_variant)
return FALSE;
rttime = g_variant_get_int64 (rttime_variant);
}
meta_topic (META_DEBUG_BACKEND,
"Setting soft and hard RLIMIT_RTTIME limit to %lu", rttime);
rl.rlim_cur = rttime;
rl.rlim_max = rttime;
if (setrlimit (RLIMIT_RTTIME, &rl) != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to set RLIMIT_RTTIME: %s", g_strerror (errno));
return FALSE;
}
meta_topic (META_DEBUG_BACKEND, "Setting '%s' thread real time priority to %d",
priv->name, priority);
- if (!meta_dbus_realtime_kit1_call_make_thread_realtime_sync (rtkit_proxy,
- gettid (),
+ if (!meta_dbus_realtime_kit1_call_make_thread_realtime_sync (priv->kernel.rtkit_proxy,
+ priv->kernel.thread_id,
priority,
NULL,
&local_error))
{
g_dbus_error_strip_remote_error (local_error);
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
return TRUE;
}
+static gboolean
+request_normal_scheduling (MetaThread *thread,
+ GError **error)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+ g_autoptr (GError) local_error = NULL;
+
+ if (!ensure_realtime_kit_proxy (thread, error))
+ return FALSE;
+
+ meta_topic (META_DEBUG_BACKEND, "Setting '%s' thread to normal priority", priv->name);
+ if (!meta_dbus_realtime_kit1_call_make_thread_high_priority_sync (priv->kernel.rtkit_proxy,
+ priv->kernel.thread_id,
+ 0 /* "normal" nice value */,
+ NULL,
+ &local_error))
+ {
+ g_dbus_error_strip_remote_error (local_error);
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+should_use_realtime_scheduling_in_impl (MetaThread *thread)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+ gboolean should_use_realtime_scheduling = FALSE;
+
+ switch (priv->thread_type)
+ {
+ case META_THREAD_TYPE_USER:
+ break;
+ case META_THREAD_TYPE_KERNEL:
+ if (priv->wants_realtime && priv->kernel.realtime_inhibit_count == 0)
+ should_use_realtime_scheduling = TRUE;
+ break;
+ }
+
+ return should_use_realtime_scheduling;
+}
+
+static void
+sync_realtime_scheduling_in_impl (MetaThread *thread)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+ g_autoptr (GError) error = NULL;
+ gboolean should_be_realtime;
+
+ should_be_realtime = should_use_realtime_scheduling_in_impl (thread);
+
+ if (should_be_realtime == priv->kernel.is_realtime)
+ return;
+
+ if (should_be_realtime)
+ {
+ if (!request_realtime_scheduling (thread, &error))
+ {
+ g_warning ("Failed to make thread '%s' realtime scheduled: %s",
+ priv->name, error->message);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_BACKEND, "Made thread '%s' real-time scheduled", priv->name);
+ priv->kernel.is_realtime = TRUE;
+ }
+ }
+ else
+ {
+ if (!request_normal_scheduling (thread, &error))
+ {
+ g_warning ("Failed to make thread '%s' normally scheduled: %s",
+ priv->name, error->message);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_BACKEND, "Made thread '%s' normally scheduled", priv->name);
+ priv->kernel.is_realtime = FALSE;
+ }
+ }
+}
+
static gpointer
thread_impl_func (gpointer user_data)
{
MetaThread *thread = META_THREAD (user_data);
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
MetaThreadImpl *impl = priv->impl;
MetaThreadImplRunFlags run_flags = META_THREAD_IMPL_RUN_FLAG_NONE;
GMainContext *thread_context = meta_thread_impl_get_main_context (impl);
#ifdef HAVE_PROFILER
MetaContext *context = meta_backend_get_context (priv->backend);
MetaProfiler *profiler = meta_context_get_profiler (context);
#endif
g_mutex_lock (&priv->kernel.init_mutex);
g_mutex_unlock (&priv->kernel.init_mutex);
g_main_context_push_thread_default (thread_context);
#ifdef HAVE_PROFILER
meta_profiler_register_thread (profiler, thread_context, priv->name);
#endif
- if (priv->wants_realtime)
- {
- g_autoptr (GError) error = NULL;
+ priv->kernel.thread_id = gettid ();
+ priv->kernel.realtime_inhibit_count = 0;
+ priv->kernel.is_realtime = FALSE;
- if (!request_realtime_scheduling (thread, &error))
- {
- g_warning ("Failed to make thread '%s' realtime scheduled: %s",
- priv->name, error->message);
- }
- else
- {
- g_message ("Made thread '%s' realtime scheduled", priv->name);
- run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME;
- }
+ sync_realtime_scheduling_in_impl (thread);
+
+ if (priv->kernel.is_realtime)
+ {
+ g_message ("Made thread '%s' realtime scheduled", priv->name);
+ run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME;
}
meta_thread_impl_run (impl, run_flags);
#ifdef HAVE_PROFILER
meta_profiler_unregister_thread (profiler, thread_context);
#endif
g_main_context_pop_thread_default (thread_context);
return GINT_TO_POINTER (TRUE);
}
typedef struct _WrapperSource
{
GSource base;
GMainContext *thread_main_context;
GPollFD fds[256];
gpointer fd_tags[256];
int n_fds;
int priority;
} WrapperSource;
static gboolean
wrapper_source_prepare (GSource *source,
int *timeout)
{
WrapperSource *wrapper_source = (WrapperSource *) source;
@@ -522,60 +623,64 @@ meta_thread_initable_init (GInitable *initable,
start_thread (thread);
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
initable_iface->init = meta_thread_initable_init;
}
static void
finalize_thread_user (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
meta_thread_impl_terminate (priv->impl);
while (meta_thread_impl_dispatch (priv->impl) > 0);
unwrap_main_context (thread, meta_thread_impl_get_main_context (priv->impl));
}
static void
finalize_thread_kernel (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
meta_thread_impl_terminate (priv->impl);
g_thread_join (priv->kernel.thread);
priv->kernel.thread = NULL;
+ priv->kernel.thread_id = 0;
+
+ g_clear_object (&priv->kernel.rtkit_proxy);
+
g_mutex_clear (&priv->kernel.init_mutex);
}
static void
tear_down_thread (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
switch (priv->thread_type)
{
case META_THREAD_TYPE_USER:
finalize_thread_user (thread);
break;
case META_THREAD_TYPE_KERNEL:
finalize_thread_kernel (thread);
break;
}
meta_thread_flush_callbacks (thread);
}
static void
meta_thread_finalize (GObject *object)
{
MetaThread *thread = META_THREAD (object);
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
tear_down_thread (thread);
meta_thread_unregister_callback_context (thread, priv->main_context);
@@ -1134,30 +1239,66 @@ meta_thread_get_thread_type (MetaThread *thread)
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
return priv->thread_type;
}
GThread *
meta_thread_get_thread (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
g_assert (priv->thread_type == META_THREAD_TYPE_KERNEL);
return priv->kernel.thread;
}
gboolean
meta_thread_is_in_impl_task (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
return meta_thread_impl_is_in_impl (priv->impl);
}
gboolean
meta_thread_is_waiting_for_impl_task (MetaThread *thread)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
return priv->waiting_for_impl_task;
}
+
+void
+meta_thread_inhibit_realtime_in_impl (MetaThread *thread)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+
+ switch (priv->thread_type)
+ {
+ case META_THREAD_TYPE_KERNEL:
+ priv->kernel.realtime_inhibit_count++;
+
+ if (priv->kernel.realtime_inhibit_count == 1)
+ sync_realtime_scheduling_in_impl (thread);
+ break;
+ case META_THREAD_TYPE_USER:
+ break;
+ }
+}
+
+void
+meta_thread_uninhibit_realtime_in_impl (MetaThread *thread)
+{
+ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
+
+ switch (priv->thread_type)
+ {
+ case META_THREAD_TYPE_KERNEL:
+ priv->kernel.realtime_inhibit_count--;
+
+ if (priv->kernel.realtime_inhibit_count == 0)
+ sync_realtime_scheduling_in_impl (thread);
+ break;
+ case META_THREAD_TYPE_USER:
+ break;
+ }
+}
diff --git a/src/backends/native/meta-thread.h b/src/backends/native/meta-thread.h
index f6c5c94f5..4765719ec 100644
--- a/src/backends/native/meta-thread.h
+++ b/src/backends/native/meta-thread.h
@@ -71,36 +71,39 @@ void meta_thread_queue_callback (MetaThread *thread,
GDestroyNotify user_data_destroy);
META_EXPORT_TEST
void meta_thread_flush_callbacks (MetaThread *thread);
META_EXPORT_TEST
gpointer meta_thread_run_impl_task_sync (MetaThread *thread,
MetaThreadTaskFunc func,
gpointer user_data,
GError **error);
META_EXPORT_TEST
void meta_thread_post_impl_task (MetaThread *thread,
MetaThreadTaskFunc func,
gpointer user_data,
GDestroyNotify user_data_destroy,
MetaThreadTaskFeedbackFunc feedback_func,
gpointer feedback_user_data);
META_EXPORT_TEST
MetaBackend * meta_thread_get_backend (MetaThread *thread);
META_EXPORT_TEST
const char * meta_thread_get_name (MetaThread *thread);
META_EXPORT_TEST
gboolean meta_thread_is_in_impl_task (MetaThread *thread);
gboolean meta_thread_is_waiting_for_impl_task (MetaThread *thread);
+void meta_thread_inhibit_realtime_in_impl (MetaThread *thread);
+void meta_thread_uninhibit_realtime_in_impl (MetaThread *thread);
+
#define meta_assert_in_thread_impl(thread) \
g_assert (meta_thread_is_in_impl_task (thread))
#define meta_assert_not_in_thread_impl(thread) \
g_assert (!meta_thread_is_in_impl_task (thread))
#define meta_assert_is_waiting_for_thread_impl_task(thread) \
g_assert (meta_thread_is_waiting_for_impl_task (thread))
--
2.41.0

View File

@ -1,183 +0,0 @@
From 105a3d60df5df74fd7ea78cacc0d9ca30607b45a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Oct 2023 14:48:55 -0400
Subject: [PATCH 4/4] kms/impl-device: Inhibit real-time scheduling when mode
setting
Certain kernel drivers can take an unreasonably long time to
complete mode setting operations. That excessive CPU time is charged
to the process's rlimits which can lead to the process getting killed
if the thread is a real-time thread.
This commit inhibits real-time scheduling around mode setting
commits, since those commits are the ones currently presenting as
excessively slow.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3037
---
src/backends/native/meta-kms-impl-device.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index da372383d..d53552704 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -1554,141 +1554,154 @@ meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device,
if (crtc_frame->await_flush)
return;
if (!is_using_deadline_timer (impl_device))
goto needs_flush;
if (crtc_frame->pending_page_flip)
return;
if (ensure_deadline_timer_armed (impl_device, crtc_frame, &error))
return;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
g_warning ("Failed to determine deadline: %s", error->message);
priv = meta_kms_impl_device_get_instance_private (impl_device);
priv->deadline_timer_inhibited = TRUE;
needs_flush:
meta_kms_device_set_needs_flush (meta_kms_crtc_get_device (crtc), crtc);
}
static MetaKmsFeedback *
process_mode_set_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsUpdateFlag flags)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
+ MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device);
+ MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl);
+ MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
+ MetaKmsFeedback *feedback;
CrtcFrame *crtc_frame;
GList *l;
GHashTableIter iter;
for (l = meta_kms_update_get_mode_sets (update); l; l = l->next)
{
MetaKmsModeSet *mode_set = l->data;
MetaKmsCrtc *crtc = mode_set->crtc;
crtc_frame = get_crtc_frame (impl_device, crtc);
if (!crtc_frame)
continue;
if (!crtc_frame->pending_update)
continue;
meta_kms_update_merge_from (update, crtc_frame->pending_update);
g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free);
}
g_hash_table_iter_init (&iter, priv->crtc_frames);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &crtc_frame))
{
crtc_frame->deadline.is_deadline_page_flip = FALSE;
crtc_frame->await_flush = FALSE;
crtc_frame->pending_page_flip = FALSE;
g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free);
disarm_crtc_frame_deadline_timer (crtc_frame);
}
- return do_process (impl_device, NULL, update, flags);
+ meta_thread_inhibit_realtime_in_impl (thread);
+ feedback = do_process (impl_device, NULL, update, flags);
+ meta_thread_uninhibit_realtime_in_impl (thread);
+
+ return feedback;
}
MetaKmsFeedback *
meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsUpdateFlag flags)
{
g_autoptr (GError) error = NULL;
if (!ensure_device_file (impl_device, &error))
{
MetaKmsFeedback *feedback = NULL;
feedback = meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error));
queue_result_feedback (impl_device, update, feedback);
meta_kms_update_free (update);
return feedback;
}
meta_kms_update_realize (update, impl_device);
if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY)
{
return do_process (impl_device,
meta_kms_update_get_latch_crtc (update),
update, flags);
}
else if (flags & META_KMS_UPDATE_FLAG_MODE_SET)
{
return process_mode_set_update (impl_device, update, flags);
}
else
{
g_assert_not_reached ();
}
}
void
meta_kms_impl_device_disable (MetaKmsImplDevice *impl_device)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
+ MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device);
+ MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl);
+ MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
if (!priv->device_file)
return;
meta_kms_impl_device_hold_fd (impl_device);
+ meta_thread_inhibit_realtime_in_impl (thread);
klass->disable (impl_device);
+ meta_thread_uninhibit_realtime_in_impl (thread);
g_list_foreach (priv->crtcs,
(GFunc) meta_kms_crtc_disable_in_impl, NULL);
g_list_foreach (priv->connectors,
(GFunc) meta_kms_connector_disable_in_impl, NULL);
meta_kms_impl_device_unhold_fd (impl_device);
}
void
meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data)
{
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
klass->handle_page_flip_callback (impl_device, page_flip_data);
}
void
meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device)
{
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
klass->discard_pending_page_flips (impl_device);
}
void
meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaKms *kms = meta_kms_device_get_kms (priv->device);
--
2.41.0

View File

@ -1,58 +0,0 @@
From 4008ed2f55d4621a4ed2230799c1ab2d012b3545 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Sep 2023 22:59:13 +0800
Subject: [PATCH] monitor-config-store: Discard config with fractional scale
when unusable
When a configuration has a fractional scale, but we're using a physical
monitor layout, we can't use the scale, but if we do, we end up with
wierd issues down the line. Just discard the config if we run into this.
Eventually we probably want to store the layout mode in the
configuration so we can handle more seamless switching between physical
and logical layout mode, but first do this.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3057
---
src/backends/meta-monitor-config-store.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
index fe9406fd3f7..53a32cd2aaf 100644
--- a/src/backends/meta-monitor-config-store.c
+++ b/src/backends/meta-monitor-config-store.c
@@ -653,6 +653,7 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf
MetaMonitorConfig *monitor_config;
int mode_width, mode_height;
int width = 0, height = 0;
+ float scale;
GList *l;
monitor_config = logical_monitor_config->monitor_configs->data;
@@ -683,13 +684,21 @@ derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_conf
height = mode_height;
}
+ scale = logical_monitor_config->scale;
+
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
- width = roundf (width / logical_monitor_config->scale);
- height = roundf (height / logical_monitor_config->scale);
+ width = roundf (width / scale);
+ height = roundf (height / scale);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
+ if (!G_APPROX_VALUE (scale, roundf (scale), FLT_EPSILON))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "A fractional scale with physical layout mode not allowed");
+ return FALSE;
+ }
break;
}
--
GitLab

View File

@ -1,65 +0,0 @@
From 6fe1b3145f840d39240046c0812b1406d23fe569 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Fri, 29 Sep 2023 13:14:14 +0200
Subject: [PATCH] backends/native: Translate keycodes with
xkb_key_state_get_one_sym()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There's two aspects from its documentation
(https://xkbcommon.org/doc/current/group__state.html#gae56031a8c1d48e7802da32f5f39f5738)
affecting us here:
1. "This function is similar to xkb_state_key_get_syms(), but intended for
users which cannot or do not want to handle the case where multiple
keysyms are returned (in which case this function is preferred)."
We are indeed in that field, and have been for a long time.
2. "This function performs Capitalization Keysym Transformations."
This is unlike the xkb_key_get_syms() function that we use, and
convenient here for parity with X11 since it behaves exactly that
way.
Fixes cases where the keysym for some keys is not properly capitalized
when caps lock is toggled, due to the output of capslock+key being
different from shift+key. An example of this is 'é' in french(azerty)
layout (bound to the '2' key). Even though shift+2 outputs '2',
capslock+é should output 'É'.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3058
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3306>
---
src/backends/native/meta-xkb-utils.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/src/backends/native/meta-xkb-utils.c b/src/backends/native/meta-xkb-utils.c
index 1ec12a37bea..7f80cca2e2a 100644
--- a/src/backends/native/meta-xkb-utils.c
+++ b/src/backends/native/meta-xkb-utils.c
@@ -50,7 +50,6 @@ meta_key_event_new_from_evdev (ClutterInputDevice *device,
{
ClutterEvent *event;
xkb_keysym_t sym;
- const xkb_keysym_t *syms;
char buffer[8];
gunichar unicode_value;
ClutterModifierType modifiers;
@@ -62,11 +61,7 @@ meta_key_event_new_from_evdev (ClutterInputDevice *device,
* upwards by 8. */
key = meta_xkb_evdev_to_keycode (key);
- n = xkb_key_get_syms (xkb_state, key, &syms);
- if (n == 1)
- sym = syms[0];
- else
- sym = XKB_KEY_NoSymbol;
+ sym = xkb_state_key_get_one_sym (xkb_state, key);
modifiers = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE) |
button_state;
--
GitLab

View File

@ -1,460 +0,0 @@
From b258e1f7eefa67006da72172d2a61389a58b7630 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Mon, 9 Oct 2023 22:47:38 +0200
Subject: [PATCH 1/2] screen-cast/stream-src: Various code cleanups
No functional changes.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3311>
---
src/backends/meta-screen-cast-stream-src.c | 117 ++++++++++-----------
1 file changed, 57 insertions(+), 60 deletions(-)
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index 8d4e32ef60e..acb5e9a1da1 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -555,17 +555,16 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
}
static gboolean
-do_record_frame (MetaScreenCastStreamSrc *src,
- MetaScreenCastRecordFlag flags,
- struct spa_buffer *spa_buffer,
- uint8_t *data,
- GError **error)
+do_record_frame (MetaScreenCastStreamSrc *src,
+ MetaScreenCastRecordFlag flags,
+ struct spa_buffer *spa_buffer,
+ GError **error)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
+ struct spa_data *spa_data = &spa_buffer->datas[0];
- if (spa_buffer->datas[0].data ||
- spa_buffer->datas[0].type == SPA_DATA_MemFd)
+ if (spa_data->data || spa_data->type == SPA_DATA_MemFd)
{
int width = priv->video_format.size.width;
int height = priv->video_format.size.height;
@@ -575,14 +574,14 @@ do_record_frame (MetaScreenCastStreamSrc *src,
width,
height,
stride,
- data,
+ spa_data->data,
error);
}
- else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
+ else if (spa_data->type == SPA_DATA_DmaBuf)
{
CoglDmaBufHandle *dmabuf_handle =
g_hash_table_lookup (priv->dmabuf_handles,
- GINT_TO_POINTER (spa_buffer->datas[0].fd));
+ GINT_TO_POINTER (spa_data->fd));
CoglFramebuffer *dmabuf_fbo =
cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
@@ -592,7 +591,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Unknown SPA buffer type %u", spa_buffer->datas[0].type);
+ "Unknown SPA buffer type %u", spa_data->type);
return FALSE;
}
@@ -745,12 +744,12 @@ meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStr
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
MetaScreenCastRecordResult record_result =
- META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING;
+ META_SCREEN_CAST_RECORD_RESULT_RECORDED_NOTHING;
MtkRectangle crop_rect;
struct pw_buffer *buffer;
struct spa_buffer *spa_buffer;
struct spa_meta_header *header;
- uint8_t *data = NULL;
+ struct spa_data *spa_data;
/* Accumulate the damaged region since we might not schedule a frame capture
* eventually but once we do, we should report all the previous damaged areas.
@@ -817,13 +816,13 @@ meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStr
}
spa_buffer = buffer->buffer;
- data = spa_buffer->datas[0].data;
+ spa_data = &spa_buffer->datas[0];
header = spa_buffer_find_meta_data (spa_buffer,
SPA_META_Header,
sizeof (*header));
- if (spa_buffer->datas[0].type != SPA_DATA_DmaBuf && !data)
+ if (spa_data->type != SPA_DATA_DmaBuf && !spa_data->data)
{
g_critical ("Invalid buffer data");
if (header)
@@ -838,10 +837,9 @@ meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStr
g_autoptr (GError) error = NULL;
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
- if (do_record_frame (src, flags, spa_buffer, data, &error))
+ if (do_record_frame (src, flags, spa_buffer, &error))
{
maybe_add_damaged_regions_metadata (src, spa_buffer);
- struct spa_data *spa_data = &spa_buffer->datas[0];
struct spa_meta_region *spa_meta_video_crop;
spa_data->chunk->size = spa_data->maxsize;
@@ -879,14 +877,14 @@ meta_screen_cast_stream_src_maybe_record_frame_with_timestamp (MetaScreenCastStr
{
if (error)
g_warning ("Failed to record screen cast frame: %s", error->message);
- spa_buffer->datas[0].chunk->size = 0;
- spa_buffer->datas[0].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
+ spa_data->chunk->size = 0;
+ spa_data->chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
}
}
else
{
- spa_buffer->datas[0].chunk->size = 0;
- spa_buffer->datas[0].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
+ spa_data->chunk->size = 0;
+ spa_data->chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
}
record_result |= maybe_record_cursor (src, spa_buffer);
@@ -1091,7 +1089,7 @@ on_stream_add_buffer (void *data,
meta_screen_cast_session_get_screen_cast (session);
CoglDmaBufHandle *dmabuf_handle;
struct spa_buffer *spa_buffer = buffer->buffer;
- struct spa_data *spa_data = spa_buffer->datas;
+ struct spa_data *spa_data = &spa_buffer->datas[0];
const int bpp = 4;
int stride;
@@ -1099,11 +1097,11 @@ on_stream_add_buffer (void *data,
stride = SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4);
- spa_data[0].mapoffset = 0;
- spa_data[0].maxsize = stride * priv->video_format.size.height;
- spa_data[0].data = NULL;
+ spa_data->mapoffset = 0;
+ spa_data->maxsize = stride * priv->video_format.size.height;
+ spa_data->data = NULL;
- if (spa_data[0].type & (1 << SPA_DATA_DmaBuf))
+ if (spa_data->type & (1 << SPA_DATA_DmaBuf))
{
CoglPixelFormat cogl_format;
@@ -1141,19 +1139,19 @@ on_stream_add_buffer (void *data,
"Allocating DMA buffer for pw_stream %u",
pw_stream_get_node_id (priv->pipewire_stream));
- spa_data[0].type = SPA_DATA_DmaBuf;
- spa_data[0].flags = SPA_DATA_FLAG_READWRITE;
- spa_data[0].fd = cogl_dma_buf_handle_get_fd (dmabuf_handle);
+ spa_data->type = SPA_DATA_DmaBuf;
+ spa_data->flags = SPA_DATA_FLAG_READWRITE;
+ spa_data->fd = cogl_dma_buf_handle_get_fd (dmabuf_handle);
g_hash_table_insert (priv->dmabuf_handles,
- GINT_TO_POINTER (spa_data[0].fd),
+ GINT_TO_POINTER (spa_data->fd),
dmabuf_handle);
}
else
{
unsigned int seals;
- if (!(spa_data[0].type & (1 << SPA_DATA_MemFd)))
+ if (!(spa_data->type & (1 << SPA_DATA_MemFd)))
{
g_critical ("No supported PipeWire stream buffer data type could "
"be negotiated");
@@ -1165,40 +1163,39 @@ on_stream_add_buffer (void *data,
pw_stream_get_node_id (priv->pipewire_stream));
/* Fallback to a memfd buffer */
- spa_data[0].type = SPA_DATA_MemFd;
- spa_data[0].flags = SPA_DATA_FLAG_READWRITE;
- spa_data[0].fd = memfd_create ("mutter-screen-cast-memfd",
- MFD_CLOEXEC | MFD_ALLOW_SEALING);
- if (spa_data[0].fd == -1)
+ spa_data->type = SPA_DATA_MemFd;
+ spa_data->flags = SPA_DATA_FLAG_READWRITE;
+ spa_data->fd = memfd_create ("mutter-screen-cast-memfd",
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (spa_data->fd == -1)
{
g_critical ("Can't create memfd: %m");
return;
}
- spa_data[0].mapoffset = 0;
- spa_data[0].maxsize = stride * priv->video_format.size.height;
+ spa_data->maxsize = stride * priv->video_format.size.height;
- if (ftruncate (spa_data[0].fd, spa_data[0].maxsize) < 0)
+ if (ftruncate (spa_data->fd, spa_data->maxsize) < 0)
{
- close (spa_data[0].fd);
- spa_data[0].fd = -1;
- g_critical ("Can't truncate to %d: %m", spa_data[0].maxsize);
+ close (spa_data->fd);
+ spa_data->fd = -1;
+ g_critical ("Can't truncate to %d: %m", spa_data->maxsize);
return;
}
seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
- if (fcntl (spa_data[0].fd, F_ADD_SEALS, seals) == -1)
+ if (fcntl (spa_data->fd, F_ADD_SEALS, seals) == -1)
g_warning ("Failed to add seals: %m");
- spa_data[0].data = mmap (NULL,
- spa_data[0].maxsize,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- spa_data[0].fd,
- spa_data[0].mapoffset);
- if (spa_data[0].data == MAP_FAILED)
+ spa_data->data = mmap (NULL,
+ spa_data->maxsize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ spa_data->fd,
+ spa_data->mapoffset);
+ if (spa_data->data == MAP_FAILED)
{
- close (spa_data[0].fd);
- spa_data[0].fd = -1;
+ close (spa_data->fd);
+ spa_data->fd = -1;
g_critical ("Failed to mmap memory: %m");
return;
}
@@ -1219,23 +1216,23 @@ on_stream_remove_buffer (void *data,
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
struct spa_buffer *spa_buffer = buffer->buffer;
- struct spa_data *spa_data = spa_buffer->datas;
+ struct spa_data *spa_data = &spa_buffer->datas[0];
priv->buffer_count--;
- if (spa_data[0].type == SPA_DATA_DmaBuf)
+ if (spa_data->type == SPA_DATA_DmaBuf)
{
- if (!g_hash_table_remove (priv->dmabuf_handles, GINT_TO_POINTER (spa_data[0].fd)))
+ if (!g_hash_table_remove (priv->dmabuf_handles, GINT_TO_POINTER (spa_data->fd)))
g_critical ("Failed to remove non-exported DMA buffer");
}
- else if (spa_data[0].type == SPA_DATA_MemFd)
+ else if (spa_data->type == SPA_DATA_MemFd)
{
- g_warn_if_fail (spa_data[0].fd > 0 || !spa_data[0].data);
+ g_warn_if_fail (spa_data->fd > 0 || !spa_data->data);
- if (spa_data[0].fd > 0)
+ if (spa_data->fd > 0)
{
- munmap (spa_data[0].data, spa_data[0].maxsize);
- close (spa_data[0].fd);
+ munmap (spa_data->data, spa_data->maxsize);
+ close (spa_data->fd);
}
}
}
--
GitLab
From 9b663f44e6044ece52c38b3ee23bbc2b55328b47 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Thu, 5 Oct 2023 08:36:31 +0200
Subject: [PATCH 2/2] screen-cast/strieam-src: Fix stride and max buffer size
calculation
1. Centralize stride calculation in one function.
2. For dmabufs query the stride instead of assuming a certain value.
3. For system memory buffers use the pixel format to calculate the
stride.
4. Stop negotiating `SPA_PARAM_BUFFERS_size` and
`SPA_PARAM_BUFFERS_stride`.
2. fixes an actual bug where we reported wrong max buffer sizes,
resulting in crashes in Gstreamer when doing area screencasts on AMD
GPUs.
The reasoning for 4. is that the values were possibly wrong for
dmabufs as the negotiation happens before we create any buffers.
Further more neither Mutter nor the common consumers required it.
The later either ignore the values (OBS), always accept (gstpipewiresrc)
them or calculate the exact same possibly wrong values (libwebrtc).
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6747
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3311>
---
src/backends/meta-screen-cast-stream-src.c | 70 ++++++++++------------
1 file changed, 33 insertions(+), 37 deletions(-)
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index acb5e9a1da1..cf198cf6472 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -102,7 +102,6 @@ typedef struct _MetaScreenCastStreamSrcPrivate
uint32_t node_id;
struct spa_video_info_raw video_format;
- int video_stride;
int64_t last_frame_timestamp_us;
guint follow_up_frame_source_id;
@@ -554,6 +553,33 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
g_assert_not_reached ();
}
+static int32_t
+meta_screen_cast_stream_src_calculate_stride (MetaScreenCastStreamSrc *src,
+ struct spa_data *spa_data)
+{
+ MetaScreenCastStreamSrcPrivate *priv =
+ meta_screen_cast_stream_src_get_instance_private (src);
+ CoglPixelFormat cogl_format;
+ int bpp;
+
+ if (spa_data->type == SPA_DATA_DmaBuf)
+ {
+ CoglDmaBufHandle *dmabuf_handle = NULL;
+
+ dmabuf_handle = g_hash_table_lookup (priv->dmabuf_handles,
+ GINT_TO_POINTER (spa_data->fd));
+ if (dmabuf_handle)
+ return cogl_dma_buf_handle_get_stride (dmabuf_handle);
+ }
+
+ if (!cogl_pixel_format_from_spa_video_format (priv->video_format.format,
+ &cogl_format))
+ g_assert_not_reached ();
+
+ bpp = cogl_pixel_format_get_bytes_per_pixel (cogl_format, 0);
+ return SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4);
+}
+
static gboolean
do_record_frame (MetaScreenCastStreamSrc *src,
MetaScreenCastRecordFlag flags,
@@ -568,7 +594,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
{
int width = priv->video_format.size.width;
int height = priv->video_format.size.height;
- int stride = priv->video_stride;
+ int stride = meta_screen_cast_stream_src_calculate_stride (src, spa_data);
return meta_screen_cast_stream_src_record_to_buffer (src,
width,
@@ -632,26 +658,6 @@ maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src,
src);
}
-static int32_t
-meta_screen_cast_stream_src_calculate_stride (MetaScreenCastStreamSrc *src,
- struct spa_data *spa_data)
-{
- MetaScreenCastStreamSrcPrivate *priv =
- meta_screen_cast_stream_src_get_instance_private (src);
- CoglDmaBufHandle *dmabuf_handle = NULL;
-
- if (spa_data->type == SPA_DATA_DmaBuf)
- {
- dmabuf_handle = g_hash_table_lookup (priv->dmabuf_handles,
- GINT_TO_POINTER (spa_data->fd));
- }
-
- if (dmabuf_handle)
- return cogl_dma_buf_handle_get_stride (dmabuf_handle);
- else
- return priv->video_stride;
-}
-
static void
maybe_add_damaged_regions_metadata (MetaScreenCastStreamSrc *src,
struct spa_buffer *spa_buffer)
@@ -1014,11 +1020,9 @@ on_stream_param_changed (void *data,
MetaScreenCastStreamSrcClass *klass =
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
uint8_t params_buffer[1024];
- int32_t width, height, stride, size;
struct spa_pod_builder pod_builder;
const struct spa_pod *params[5];
int n_params = 0;
- const int bpp = 4;
int buffer_types;
if (!format || id != SPA_PARAM_Format)
@@ -1027,13 +1031,6 @@ on_stream_param_changed (void *data,
spa_format_video_raw_parse (format,
&priv->video_format);
- width = priv->video_format.size.width;
- height = priv->video_format.size.height;
- stride = SPA_ROUND_UP_N (width * bpp, 4);
- size = height * stride;
-
- priv->video_stride = stride;
-
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
buffer_types = 1 << SPA_DATA_MemFd;
@@ -1045,8 +1042,6 @@ on_stream_param_changed (void *data,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (16, 2, 16),
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int (1),
- SPA_PARAM_BUFFERS_size, SPA_POD_Int (size),
- SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride),
SPA_PARAM_BUFFERS_align, SPA_POD_Int (16),
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int (buffer_types));
@@ -1090,15 +1085,11 @@ on_stream_add_buffer (void *data,
CoglDmaBufHandle *dmabuf_handle;
struct spa_buffer *spa_buffer = buffer->buffer;
struct spa_data *spa_data = &spa_buffer->datas[0];
- const int bpp = 4;
int stride;
priv->buffer_count++;
- stride = SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4);
-
spa_data->mapoffset = 0;
- spa_data->maxsize = stride * priv->video_format.size.height;
spa_data->data = NULL;
if (spa_data->type & (1 << SPA_DATA_DmaBuf))
@@ -1143,6 +1134,9 @@ on_stream_add_buffer (void *data,
spa_data->flags = SPA_DATA_FLAG_READWRITE;
spa_data->fd = cogl_dma_buf_handle_get_fd (dmabuf_handle);
+ stride = meta_screen_cast_stream_src_calculate_stride (src, spa_data);
+ spa_data->maxsize = stride * priv->video_format.size.height;
+
g_hash_table_insert (priv->dmabuf_handles,
GINT_TO_POINTER (spa_data->fd),
dmabuf_handle);
@@ -1172,6 +1166,8 @@ on_stream_add_buffer (void *data,
g_critical ("Can't create memfd: %m");
return;
}
+
+ stride = meta_screen_cast_stream_src_calculate_stride (src, spa_data);
spa_data->maxsize = stride * priv->video_format.size.height;
if (ftruncate (spa_data->fd, spa_data->maxsize) < 0)
--
GitLab

View File

@ -1,78 +0,0 @@
From 5809ef62f5e8b12a9cbaf8ec8efac814563bf13e Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Fri, 13 Oct 2023 15:37:27 +0200
Subject: [PATCH 1/2] screen-cast/stream-src: Calculate stride after adding
handle to hash table
`calculate_stride()` looks up the dmabuf handle from the hash table so
we need to add it first.
Fixes 9b663f44e6044ece52c38b3ee23bbc2b55328b47
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3326>
---
src/backends/meta-screen-cast-stream-src.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index cf198cf6472..fd49c533930 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -1134,12 +1134,12 @@ on_stream_add_buffer (void *data,
spa_data->flags = SPA_DATA_FLAG_READWRITE;
spa_data->fd = cogl_dma_buf_handle_get_fd (dmabuf_handle);
- stride = meta_screen_cast_stream_src_calculate_stride (src, spa_data);
- spa_data->maxsize = stride * priv->video_format.size.height;
-
g_hash_table_insert (priv->dmabuf_handles,
GINT_TO_POINTER (spa_data->fd),
dmabuf_handle);
+
+ stride = meta_screen_cast_stream_src_calculate_stride (src, spa_data);
+ spa_data->maxsize = stride * priv->video_format.size.height;
}
else
{
--
GitLab
From 8d3d8b86e517c97accf11eb243078faf31dd72bb Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Fri, 13 Oct 2023 18:29:19 +0200
Subject: [PATCH 2/2] screen-cast/stream-src: Assert that dmabuf handle lookup
succeeds
To prevent issues like the one fixed in the previous commit.
Also remove a redundant variable assignment.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3326>
---
src/backends/meta-screen-cast-stream-src.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index fd49c533930..273c085d5b8 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -564,12 +564,12 @@ meta_screen_cast_stream_src_calculate_stride (MetaScreenCastStreamSrc *src,
if (spa_data->type == SPA_DATA_DmaBuf)
{
- CoglDmaBufHandle *dmabuf_handle = NULL;
+ CoglDmaBufHandle *dmabuf_handle;
dmabuf_handle = g_hash_table_lookup (priv->dmabuf_handles,
GINT_TO_POINTER (spa_data->fd));
- if (dmabuf_handle)
- return cogl_dma_buf_handle_get_stride (dmabuf_handle);
+ g_assert (dmabuf_handle != NULL);
+ return cogl_dma_buf_handle_get_stride (dmabuf_handle);
}
if (!cogl_pixel_format_from_spa_video_format (priv->video_format.format,
--
GitLab

View File

@ -13,7 +13,7 @@
%global tarball_version %%(echo %{version} | tr '~' '.')
Name: mutter
Version: 45.0
Version: 45.1
Release: %autorelease
Summary: Window and compositing manager based on Clutter
@ -32,39 +32,18 @@ Patch: 0001-place-Always-center-initial-setup-fedora-welcome.patch
Patch: 0001-gschema-Enable-scale-monitor-framebuffer-experimenta.patch
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3299
Patch: 3299.patch
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3306
Patch: 3306.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2239128
# https://gitlab.gnome.org/GNOME/mutter/-/issues/3068
# not upstreamed because for upstream we'd really want to find a way
# to fix *both* problems
Patch: 0001-Revert-x11-Use-input-region-from-frame-window-for-de.patch
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3324
Patch: 0001-thread-For-consistency-s-real_time-realtime.patch
Patch: 0002-tests-dbusmock-templates-rtkit-Add-MakeThreadHighPri.patch
Patch: 0003-thread-Allow-turning-off-rt-scheduling-for-running-t.patch
Patch: 0004-kms-impl-device-Inhibit-real-time-scheduling-when-mo.patch
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329
# Modified to add the change from
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3329#note_1874837
# which solves the problems reported with #3329 alone
Patch: 0001-modified-3329.patch
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7148
# https://bugzilla.redhat.com/show_bug.cgi?id=2247033
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3311
# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3326
# Fix problems with screen captures being corrupted or not working on
# certain hardware
Patch: 3311.patch
Patch: 3326.patch
BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0
BuildRequires: pkgconfig(sm)
BuildRequires: pkgconfig(libwacom)

View File

@ -1 +1 @@
SHA512 (mutter-45.0.tar.xz) = bbf813a720a3d8545969d089790f6e4c19cd5c8eb3079ba028945e4728446c78aa7540061ea87e43151c2ef359ea986b0e7a45f56f0eb6a33ca2c3979955bb43
SHA512 (mutter-45.1.tar.xz) = 87a629e941eb231d05fc24dbb905acb12236c971a02dd000fdd6cc6e7686544b5796ce57d10b34e096dc956578a373d5a73e89760bcc6beb292e9a25ce2faaf4