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
This commit is contained in:
parent
53b59d8bff
commit
3cc3b7526c
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -180,6 +180,15 @@ meta_stage_deactivate (ClutterStage *actor)
|
||||
stage->is_active = FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user