summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2019-03-25 10:24:46 +0100
committerJonas Ådahl <jadahl@gmail.com>2019-04-02 13:49:59 +0000
commit3cc3b7526c31bd90cb9cb0b42a1096b1da76f48b (patch)
treeece5b5f280a0b7e15632d8a0d5fd33b4d3c8ce20
parent53b59d8bff05dee84fc8459794696776b971fa77 (diff)
downloadmutter-3cc3b7526c31bd90cb9cb0b42a1096b1da76f48b.tar.gz
renderer-native: Fake page flipping slower when power saving
We rely on the frame clock to compress input events, thus if the frame clock stops, input events are not dispatched. At the same time, there is no reason to redraw at a full frame rate, as nothing will be presented anyway, so slow down to 10Hz (compared to the most common 60Hz). Note that we'll only actually reach 10Hz if there is an active animation being displayed, which won't happen e.g. if there is a screen shield in the way. https://gitlab.gnome.org/GNOME/mutter/merge_requests/506
-rw-r--r--src/backends/meta-backend.c2
-rw-r--r--src/backends/meta-stage-private.h3
-rw-r--r--src/backends/meta-stage.c27
-rw-r--r--src/backends/native/meta-renderer-native.c99
4 files changed, 102 insertions, 29 deletions
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index c527114be..58eec8c94 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -475,7 +475,7 @@ meta_backend_real_post_init (MetaBackend *backend)
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
- priv->stage = meta_stage_new ();
+ priv->stage = meta_stage_new (backend);
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
diff --git a/src/backends/meta-stage-private.h b/src/backends/meta-stage-private.h
index 21feab3ac..639d2372c 100644
--- a/src/backends/meta-stage-private.h
+++ b/src/backends/meta-stage-private.h
@@ -23,12 +23,13 @@
#include "backends/meta-cursor.h"
#include "meta/boxes.h"
#include "meta/meta-stage.h"
+#include "meta/types.h"
G_BEGIN_DECLS
typedef struct _MetaOverlay MetaOverlay;
-ClutterActor *meta_stage_new (void);
+ClutterActor *meta_stage_new (MetaBackend *backend);
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
void meta_stage_remove_cursor_overlay (MetaStage *stage,
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index 1f0d9c050..47a00e51a 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -181,6 +181,15 @@ meta_stage_deactivate (ClutterStage *actor)
}
static void
+on_power_save_changed (MetaMonitorManager *monitor_manager,
+ MetaStage *stage)
+{
+ if (meta_monitor_manager_get_power_save_mode (monitor_manager) ==
+ META_POWER_SAVE_ON)
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+}
+
+static void
meta_stage_class_init (MetaStageClass *klass)
{
ClutterStageClass *stage_class = (ClutterStageClass *) klass;
@@ -209,11 +218,21 @@ meta_stage_init (MetaStage *stage)
}
ClutterActor *
-meta_stage_new (void)
+meta_stage_new (MetaBackend *backend)
{
- return g_object_new (META_TYPE_STAGE,
- "cursor-visible", FALSE,
- NULL);
+ MetaStage *stage;
+ MetaMonitorManager *monitor_manager;
+
+ stage = g_object_new (META_TYPE_STAGE,
+ "cursor-visible", FALSE,
+ NULL);
+
+ monitor_manager = meta_backend_get_monitor_manager (backend);
+ g_signal_connect (monitor_manager, "power-save-mode-changed",
+ G_CALLBACK (on_power_save_changed),
+ stage);
+
+ return CLUTTER_ACTOR (stage);
}
static void
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index e550a47e7..0f0992cbf 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -213,6 +213,9 @@ struct _MetaRendererNative
int64_t frame_counter;
gboolean pending_unset_disabled_crtcs;
+
+ GList *power_save_page_flip_closures;
+ guint power_save_page_flip_source_id;
};
static void
@@ -1526,6 +1529,38 @@ is_timestamp_earlier_than (uint64_t ts1,
return ts2 - ts1 < UINT64_MAX / 2;
}
+static gboolean
+dummy_power_save_page_flip_cb (gpointer user_data)
+{
+ MetaRendererNative *renderer_native = user_data;
+
+ g_list_free_full (renderer_native->power_save_page_flip_closures,
+ (GDestroyNotify) g_closure_unref);
+ renderer_native->power_save_page_flip_closures = NULL;
+ renderer_native->power_save_page_flip_source_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+queue_dummy_power_save_page_flip (MetaRendererNative *renderer_native,
+ GClosure *flip_closure)
+{
+ const unsigned int timeout_ms = 100;
+
+ if (!renderer_native->power_save_page_flip_source_id)
+ {
+ renderer_native->power_save_page_flip_source_id =
+ g_timeout_add (timeout_ms,
+ dummy_power_save_page_flip_cb,
+ renderer_native);
+ }
+
+ renderer_native->power_save_page_flip_closures =
+ g_list_prepend (renderer_native->power_save_page_flip_closures,
+ g_closure_ref (flip_closure));
+}
+
typedef struct _RetryPageFlipData
{
MetaCrtc *crtc;
@@ -1748,12 +1783,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
uint32_t fb_id;
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
- if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Tried to flip inactive CRTC");
- return FALSE;
- }
+
+ g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
@@ -1994,7 +2025,11 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaRendererView *view = onscreen_native->view;
+ MetaRendererNative *renderer_native = onscreen_native->renderer_native;
+ MetaMonitorManager *monitor_manager =
+ META_MONITOR_MANAGER (renderer_native->monitor_manager_kms);
GClosure *flip_closure;
+ MetaPowerSave power_save_mode;
MetaLogicalMonitor *logical_monitor;
/*
@@ -2012,23 +2047,28 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
(GClosureNotify) flip_closure_destroyed);
g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
- /* Either flip the CRTC's of the monitor info, if we are drawing just part
- * of the stage, or all of the CRTC's if we are drawing the whole stage.
- */
- FlipCrtcData data = {
- .onscreen = onscreen,
- .flip_closure = flip_closure,
- };
- logical_monitor = meta_renderer_view_get_logical_monitor (view);
- meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
+ power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
+ if (power_save_mode == META_POWER_SAVE_ON)
+ {
+ FlipCrtcData data = {
+ .onscreen = onscreen,
+ .flip_closure = flip_closure,
+ };
+ logical_monitor = meta_renderer_view_get_logical_monitor (view);
+ meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
- /*
- * If we didn't queue a page flip, but instead directly changed the mode due
- * to the driver not supporting mode setting, wes must swap the buffers
- * directly as we won't get a page flip callback.
- */
- if (!data.did_flip && data.did_mode_set)
- meta_onscreen_native_swap_drm_fb (onscreen);
+ /*
+ * If we didn't queue a page flip, but instead directly changed the mode
+ * due to the driver not supporting mode setting, we must swap the
+ * buffers directly as we won't get a page flip callback.
+ */
+ if (!data.did_flip && data.did_mode_set)
+ meta_onscreen_native_swap_drm_fb (onscreen);
+ }
+ else
+ {
+ queue_dummy_power_save_page_flip (renderer_native, flip_closure);
+ }
onscreen_native->pending_queue_swap_notify = TRUE;
@@ -2401,11 +2441,14 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
+ MetaMonitorManager *monitor_manager =
+ META_MONITOR_MANAGER (renderer_native->monitor_manager_kms);
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
CoglFrameInfo *frame_info;
gboolean egl_context_changed = FALSE;
+ MetaPowerSave power_save_mode;
/*
* Wait for the flip callback before continuing, as we might have started the
@@ -2447,7 +2490,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
/* If this is the first framebuffer to be presented then we now setup the
* crtc modes, else we flip from the previous buffer */
- if (onscreen_native->pending_set_crtc)
+
+ power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
+ if (onscreen_native->pending_set_crtc &&
+ power_save_mode == META_POWER_SAVE_ON)
{
meta_onscreen_native_set_crtc_modes (onscreen);
onscreen_native->pending_set_crtc = FALSE;
@@ -4157,6 +4203,13 @@ meta_renderer_native_finalize (GObject *object)
{
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object);
+ if (renderer_native->power_save_page_flip_closures)
+ {
+ g_list_free_full (renderer_native->power_save_page_flip_closures,
+ (GDestroyNotify) g_closure_unref);
+ g_source_remove (renderer_native->power_save_page_flip_source_id);
+ }
+
g_hash_table_destroy (renderer_native->gpu_datas);
g_clear_object (&renderer_native->gles3);