Created
April 19, 2023 16:03
-
-
Save kode54/b6d137df7f06b07eedb62c7491923142 to your computer and use it in GitHub Desktop.
Mutter VRR patch, rebased against mutter 43.4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 596f396f62ab834845fe1253ebb677866f9a6b23 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sun, 16 Aug 2020 17:14:03 +0300 | |
Subject: [PATCH 02/25] surface-actor: Add "frozen" signal | |
This signal is emitted when the surface actor is frozen and will not | |
update until it is thawed. | |
--- | |
src/compositor/meta-surface-actor.c | 11 +++++++++++ | |
1 file changed, 11 insertions(+) | |
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c | |
index c2bf6696a20..978ccf9e61b 100644 | |
--- a/src/compositor/meta-surface-actor.c | |
+++ b/src/compositor/meta-surface-actor.c | |
@@ -51,6 +51,7 @@ enum | |
{ | |
REPAINT_SCHEDULED, | |
SIZE_CHANGED, | |
+ FROZEN, | |
LAST_SIGNAL, | |
}; | |
@@ -269,6 +270,13 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass) | |
0, | |
NULL, NULL, NULL, | |
G_TYPE_NONE, 0); | |
+ | |
+ signals[FROZEN] = g_signal_new ("frozen", | |
+ G_TYPE_FROM_CLASS (object_class), | |
+ G_SIGNAL_RUN_LAST, | |
+ 0, | |
+ NULL, NULL, NULL, | |
+ G_TYPE_NONE, 0); | |
} | |
gboolean | |
@@ -594,6 +602,9 @@ meta_surface_actor_set_frozen (MetaSurfaceActor *self, | |
priv->frozen = frozen; | |
+ if (frozen) | |
+ g_signal_emit (self, signals[FROZEN], 0); | |
+ | |
if (!frozen && priv->pending_damage) | |
{ | |
int i, n_rects = cairo_region_num_rectangles (priv->pending_damage); | |
-- | |
GitLab | |
From ad05a9f906fcc291aa5b2d450b12166b74321460 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sun, 16 Aug 2020 19:50:45 +0300 | |
Subject: [PATCH 03/25] clutter/stage: Allow scheduling stage updates in the | |
context of an actor | |
This is implemented using a new ClutterStageView virtual function so | |
each child class can implement unique functionality around it. When not | |
implemented by a child class, the virtual function keeps the existing | |
behavior of a stage view update. | |
In later commits, the virtual function would be implemented by the | |
native backend to synchronize the frame clock to the update rate of | |
specific actors. | |
--- | |
clutter/clutter/clutter-stage-view-private.h | 4 +++ | |
clutter/clutter/clutter-stage-view.c | 18 ++++++++++++ | |
clutter/clutter/clutter-stage-view.h | 3 ++ | |
clutter/clutter/clutter-stage.c | 30 ++++++++++++++++++++ | |
clutter/clutter/clutter-stage.h | 4 +++ | |
5 files changed, 59 insertions(+) | |
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h | |
index 39d8601ea57..5c1ce964525 100644 | |
--- a/clutter/clutter/clutter-stage-view-private.h | |
+++ b/clutter/clutter/clutter-stage-view-private.h | |
@@ -72,6 +72,10 @@ void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView | |
CLUTTER_EXPORT | |
void clutter_stage_view_schedule_update (ClutterStageView *view); | |
+CLUTTER_EXPORT | |
+void clutter_stage_view_schedule_actor_update (ClutterStageView *view, | |
+ ClutterActor *actor); | |
+ | |
CLUTTER_EXPORT | |
void clutter_stage_view_notify_presented (ClutterStageView *view, | |
ClutterFrameInfo *frame_info); | |
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c | |
index 2e47237f0ad..55d4368bc50 100644 | |
--- a/clutter/clutter/clutter-stage-view.c | |
+++ b/clutter/clutter/clutter-stage-view.c | |
@@ -1047,6 +1047,22 @@ clutter_stage_view_schedule_update (ClutterStageView *view) | |
clutter_frame_clock_schedule_update (priv->frame_clock); | |
} | |
+void | |
+clutter_stage_view_schedule_actor_update (ClutterStageView *view, | |
+ ClutterActor *actor) | |
+{ | |
+ ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view); | |
+ | |
+ view_class->schedule_actor_update (view, actor); | |
+} | |
+ | |
+static void | |
+clutter_stage_view_real_schedule_actor_update (ClutterStageView *view, | |
+ ClutterActor *actor) | |
+{ | |
+ clutter_stage_view_schedule_update (view); | |
+} | |
+ | |
float | |
clutter_stage_view_get_refresh_rate (ClutterStageView *view) | |
{ | |
@@ -1443,6 +1459,8 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) | |
object_class->dispose = clutter_stage_view_dispose; | |
object_class->finalize = clutter_stage_view_finalize; | |
+ klass->schedule_actor_update = clutter_stage_view_real_schedule_actor_update; | |
+ | |
obj_props[PROP_NAME] = | |
g_param_spec_string ("name", | |
"Name", | |
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h | |
index c2cf76abf6a..0f34cf5b8aa 100644 | |
--- a/clutter/clutter/clutter-stage-view.h | |
+++ b/clutter/clutter/clutter-stage-view.h | |
@@ -50,6 +50,9 @@ struct _ClutterStageViewClass | |
int dst_width, | |
int dst_height, | |
cairo_rectangle_int_t *dst_rect); | |
+ | |
+ void (* schedule_actor_update) (ClutterStageView *view, | |
+ ClutterActor *actor); | |
}; | |
CLUTTER_EXPORT | |
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c | |
index e97cd54a3f9..3e81655e01e 100644 | |
--- a/clutter/clutter/clutter-stage.c | |
+++ b/clutter/clutter/clutter-stage.c | |
@@ -2467,6 +2467,36 @@ clutter_stage_schedule_update (ClutterStage *stage) | |
} | |
} | |
+/** | |
+ * clutter_stage_schedule_actor_update: | |
+ * @stage: a #ClutterStage actor | |
+ * @actor: a #ClutterActor which requires an update | |
+ * | |
+ * Schedules a redraw of the #ClutterStage at the next optimal timestamp | |
+ * for the specified actor. | |
+ */ | |
+void | |
+clutter_stage_schedule_actor_update (ClutterStage *stage, | |
+ ClutterActor *actor) | |
+{ | |
+ ClutterStageWindow *stage_window; | |
+ GList *l; | |
+ | |
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) | |
+ return; | |
+ | |
+ stage_window = _clutter_stage_get_window (stage); | |
+ if (stage_window == NULL) | |
+ return; | |
+ | |
+ for (l = clutter_stage_peek_stage_views (stage); l; l = l->next) | |
+ { | |
+ ClutterStageView *view = l->data; | |
+ | |
+ clutter_stage_view_schedule_actor_update (view, actor); | |
+ } | |
+} | |
+ | |
ClutterPaintVolume * | |
_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage) | |
{ | |
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h | |
index 5412c4d7297..a579820a44d 100644 | |
--- a/clutter/clutter/clutter-stage.h | |
+++ b/clutter/clutter/clutter-stage.h | |
@@ -210,6 +210,10 @@ gboolean clutter_stage_is_redraw_queued_on_view (ClutterStage | |
CLUTTER_EXPORT | |
void clutter_stage_schedule_update (ClutterStage *stage); | |
+CLUTTER_EXPORT | |
+void clutter_stage_schedule_actor_update (ClutterStage *stage, | |
+ ClutterActor *actor); | |
+ | |
CLUTTER_EXPORT | |
gboolean clutter_stage_get_capture_final_size (ClutterStage *stage, | |
cairo_rectangle_int_t *rect, | |
-- | |
GitLab | |
From 95e0f89ab6a34966ba132b512d01900c0d1e894a Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 4 Aug 2020 00:28:12 +0300 | |
Subject: [PATCH 05/25] clutter/frame-clock: Add a mode for variable scheduling | |
A new variable mode is introduced which allows: | |
* Immediate update scheduling, even when an update is already | |
scheduled. | |
* A timeout-based frame scheduling for every other update. | |
This mode will be used by following commits to implement | |
synchronization of page flips to actor frames. | |
--- | |
clutter/clutter/clutter-frame-clock.c | 106 ++++++++++++++++++++++++-- | |
clutter/clutter/clutter-frame-clock.h | 10 +++ | |
2 files changed, 109 insertions(+), 7 deletions(-) | |
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c | |
index de5223dec5c..e45107d8dc0 100644 | |
--- a/clutter/clutter/clutter-frame-clock.c | |
+++ b/clutter/clutter/clutter-frame-clock.c | |
@@ -47,6 +47,8 @@ typedef struct _EstimateQueue | |
#define SYNC_DELAY_FALLBACK_FRACTION 0.875 | |
+#define MINIMUM_REFRESH_RATE 30 | |
+ | |
typedef struct _ClutterFrameListener | |
{ | |
const ClutterFrameListenerIface *iface; | |
@@ -64,6 +66,7 @@ typedef enum _ClutterFrameClockState | |
{ | |
CLUTTER_FRAME_CLOCK_STATE_INIT, | |
CLUTTER_FRAME_CLOCK_STATE_IDLE, | |
+ CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT, | |
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, | |
CLUTTER_FRAME_CLOCK_STATE_DISPATCHING, | |
CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED, | |
@@ -75,6 +78,8 @@ struct _ClutterFrameClock | |
float refresh_rate; | |
int64_t refresh_interval_us; | |
+ int64_t minimum_refresh_interval_us; | |
+ | |
ClutterFrameListener listener; | |
GSource *source; | |
@@ -82,6 +87,8 @@ struct _ClutterFrameClock | |
int64_t frame_count; | |
ClutterFrameClockState state; | |
+ ClutterFrameClockMode mode; | |
+ | |
int64_t last_dispatch_time_us; | |
int64_t last_dispatch_lateness_us; | |
int64_t last_presentation_time_us; | |
@@ -315,6 +322,7 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, | |
{ | |
case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
g_warn_if_reached (); | |
break; | |
@@ -335,6 +343,7 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) | |
{ | |
case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
g_warn_if_reached (); | |
break; | |
@@ -543,6 +552,39 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, | |
*out_next_presentation_time_us = next_presentation_time_us; | |
} | |
+static void | |
+calculate_next_idle_timeout_us (ClutterFrameClock *frame_clock, | |
+ int64_t *out_next_update_time_us) | |
+{ | |
+ int64_t now_us; | |
+ int64_t last_presentation_time_us; | |
+ int64_t next_presentation_time_us; | |
+ int64_t timeout_interval_us; | |
+ | |
+ now_us = g_get_monotonic_time (); | |
+ | |
+ last_presentation_time_us = frame_clock->last_presentation_time_us; | |
+ | |
+ timeout_interval_us = frame_clock->minimum_refresh_interval_us; | |
+ | |
+ if (last_presentation_time_us == 0) | |
+ { | |
+ *out_next_update_time_us = | |
+ frame_clock->last_dispatch_time_us ? | |
+ ((frame_clock->last_dispatch_time_us - | |
+ frame_clock->last_dispatch_lateness_us) + timeout_interval_us) : | |
+ now_us; | |
+ return; | |
+ } | |
+ | |
+ next_presentation_time_us = last_presentation_time_us + timeout_interval_us; | |
+ | |
+ while (next_presentation_time_us < now_us) | |
+ next_presentation_time_us += timeout_interval_us; | |
+ | |
+ *out_next_update_time_us = next_presentation_time_us; | |
+} | |
+ | |
void | |
clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) | |
{ | |
@@ -555,6 +597,7 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) | |
case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
break; | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
frame_clock->pending_reschedule = TRUE; | |
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; | |
@@ -595,6 +638,7 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) | |
{ | |
case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
next_update_time_us = g_get_monotonic_time (); | |
break; | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
@@ -628,14 +672,12 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) | |
{ | |
case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
next_update_time_us = g_get_monotonic_time (); | |
- break; | |
+ g_source_set_ready_time (frame_clock->source, next_update_time_us); | |
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; | |
+ return; | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
- calculate_next_update_time_us (frame_clock, | |
- &next_update_time_us, | |
- &frame_clock->next_presentation_time_us); | |
- frame_clock->is_next_presentation_time_valid = | |
- (frame_clock->next_presentation_time_us != 0); | |
break; | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
return; | |
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | |
@@ -644,10 +686,54 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) | |
return; | |
} | |
+ switch (frame_clock->mode) | |
+ { | |
+ case CLUTTER_FRAME_CLOCK_MODE_FIXED: | |
+ calculate_next_update_time_us (frame_clock, | |
+ &next_update_time_us, | |
+ &frame_clock->next_presentation_time_us); | |
+ frame_clock->is_next_presentation_time_valid = | |
+ (frame_clock->next_presentation_time_us != 0); | |
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; | |
+ break; | |
+ case CLUTTER_FRAME_CLOCK_MODE_VARIABLE: | |
+ calculate_next_idle_timeout_us (frame_clock, | |
+ &next_update_time_us); | |
+ frame_clock->is_next_presentation_time_valid = FALSE; | |
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT; | |
+ break; | |
+ } | |
+ | |
g_warn_if_fail (next_update_time_us != -1); | |
g_source_set_ready_time (frame_clock->source, next_update_time_us); | |
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; | |
+} | |
+ | |
+void | |
+clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, | |
+ ClutterFrameClockMode mode) | |
+{ | |
+ if (frame_clock->mode == mode) | |
+ return; | |
+ | |
+ frame_clock->mode = mode; | |
+ | |
+ switch (frame_clock->state) | |
+ { | |
+ case CLUTTER_FRAME_CLOCK_STATE_INIT: | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
+ break; | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; | |
+ frame_clock->pending_reschedule = TRUE; | |
+ break; | |
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | |
+ case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | |
+ break; | |
+ } | |
+ | |
+ maybe_reschedule_update (frame_clock); | |
} | |
static void | |
@@ -711,6 +797,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, | |
g_warn_if_reached (); | |
break; | |
case CLUTTER_FRAME_CLOCK_STATE_IDLE: | |
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE_TIMEOUT: | |
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | |
break; | |
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | |
@@ -851,6 +938,10 @@ clutter_frame_clock_new (float refresh_rate, | |
init_frame_clock_source (frame_clock); | |
clutter_frame_clock_set_refresh_rate (frame_clock, refresh_rate); | |
+ | |
+ frame_clock->minimum_refresh_interval_us = | |
+ (int64_t) (0.5 + G_USEC_PER_SEC / MINIMUM_REFRESH_RATE); | |
+ | |
frame_clock->vblank_duration_us = vblank_duration_us; | |
return frame_clock; | |
@@ -882,6 +973,7 @@ static void | |
clutter_frame_clock_init (ClutterFrameClock *frame_clock) | |
{ | |
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_INIT; | |
+ frame_clock->mode = CLUTTER_FRAME_CLOCK_MODE_FIXED; | |
} | |
static void | |
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h | |
index 91e6b3a1303..380f56c6b6d 100644 | |
--- a/clutter/clutter/clutter-frame-clock.h | |
+++ b/clutter/clutter/clutter-frame-clock.h | |
@@ -53,6 +53,12 @@ typedef struct _ClutterFrameListenerIface | |
gpointer user_data); | |
} ClutterFrameListenerIface; | |
+typedef enum _ClutterFrameClockMode | |
+{ | |
+ CLUTTER_FRAME_CLOCK_MODE_FIXED, | |
+ CLUTTER_FRAME_CLOCK_MODE_VARIABLE, | |
+} ClutterFrameClockMode; | |
+ | |
CLUTTER_EXPORT | |
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate, | |
int64_t vblank_duration_us, | |
@@ -62,6 +68,10 @@ ClutterFrameClock * clutter_frame_clock_new (float re | |
CLUTTER_EXPORT | |
void clutter_frame_clock_destroy (ClutterFrameClock *frame_clock); | |
+CLUTTER_EXPORT | |
+void clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock, | |
+ ClutterFrameClockMode mode); | |
+ | |
CLUTTER_EXPORT | |
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, | |
ClutterFrameInfo *frame_info); | |
-- | |
GitLab | |
From e329df1e840f74614c3d41bdbc22642dc74f72f7 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Fri, 10 Jul 2020 18:40:07 +0300 | |
Subject: [PATCH 06/25] backends/native: Introduce MetaRendererViewNative | |
MetaRendererViewNative is a MetaRendererView which contains logic | |
specific to views of the native backend. It will be used by following | |
commits. | |
In the future, per-view logic from MetaRendererNative can be moved to | |
MetaRendererViewNative where it makes more sense to have it. | |
--- | |
src/backends/meta-renderer-view.c | 45 ++++++++++++------- | |
src/backends/meta-renderer-view.h | 11 +++-- | |
src/backends/native/meta-renderer-native.c | 34 +++++++------- | |
.../native/meta-renderer-view-native.c | 43 ++++++++++++++++++ | |
.../native/meta-renderer-view-native.h | 34 ++++++++++++++ | |
src/meson.build | 2 + | |
6 files changed, 135 insertions(+), 34 deletions(-) | |
create mode 100644 src/backends/native/meta-renderer-view-native.c | |
create mode 100644 src/backends/native/meta-renderer-view-native.h | |
diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c | |
index 55617fc682c..c16ba351c91 100644 | |
--- a/src/backends/meta-renderer-view.c | |
+++ b/src/backends/meta-renderer-view.c | |
@@ -49,28 +49,32 @@ enum | |
static GParamSpec *obj_props[PROP_LAST]; | |
-struct _MetaRendererView | |
+typedef struct _MetaRendererViewPrivate | |
{ | |
- MetaStageView parent; | |
- | |
MetaMonitorTransform transform; | |
MetaCrtc *crtc; | |
-}; | |
+} MetaRendererViewPrivate; | |
-G_DEFINE_TYPE (MetaRendererView, meta_renderer_view, | |
- META_TYPE_STAGE_VIEW) | |
+G_DEFINE_TYPE_WITH_PRIVATE (MetaRendererView, meta_renderer_view, | |
+ META_TYPE_STAGE_VIEW) | |
MetaMonitorTransform | |
meta_renderer_view_get_transform (MetaRendererView *view) | |
{ | |
- return view->transform; | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
+ | |
+ return priv->transform; | |
} | |
MetaCrtc * | |
meta_renderer_view_get_crtc (MetaRendererView *view) | |
{ | |
- return view->crtc; | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
+ | |
+ return priv->crtc; | |
} | |
static void | |
@@ -78,10 +82,12 @@ meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view, | |
graphene_matrix_t *matrix) | |
{ | |
MetaRendererView *renderer_view = META_RENDERER_VIEW (view); | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (renderer_view); | |
graphene_matrix_init_identity (matrix); | |
meta_monitor_transform_transform_matrix ( | |
- meta_monitor_transform_invert (renderer_view->transform), matrix); | |
+ meta_monitor_transform_invert (priv->transform), matrix); | |
} | |
static void | |
@@ -136,9 +142,11 @@ meta_renderer_view_transform_rect_to_onscreen (ClutterStageView *view | |
cairo_rectangle_int_t *dst_rect) | |
{ | |
MetaRendererView *renderer_view = META_RENDERER_VIEW (view); | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (renderer_view); | |
return meta_rectangle_transform (src_rect, | |
- renderer_view->transform, | |
+ priv->transform, | |
dst_width, | |
dst_height, | |
dst_rect); | |
@@ -151,10 +159,13 @@ static void | |
meta_renderer_view_set_transform (MetaRendererView *view, | |
MetaMonitorTransform transform) | |
{ | |
- if (view->transform == transform) | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
+ | |
+ if (priv->transform == transform) | |
return; | |
- view->transform = transform; | |
+ priv->transform = transform; | |
clutter_stage_view_invalidate_offscreen_blit_pipeline (CLUTTER_STAGE_VIEW (view)); | |
} | |
@@ -165,14 +176,16 @@ meta_renderer_view_get_property (GObject *object, | |
GParamSpec *pspec) | |
{ | |
MetaRendererView *view = META_RENDERER_VIEW (object); | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
switch (prop_id) | |
{ | |
case PROP_TRANSFORM: | |
- g_value_set_uint (value, view->transform); | |
+ g_value_set_uint (value, priv->transform); | |
break; | |
case PROP_CRTC: | |
- g_value_set_object (value, view->crtc); | |
+ g_value_set_object (value, priv->crtc); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
@@ -187,6 +200,8 @@ meta_renderer_view_set_property (GObject *object, | |
GParamSpec *pspec) | |
{ | |
MetaRendererView *view = META_RENDERER_VIEW (object); | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
switch (prop_id) | |
{ | |
@@ -194,7 +209,7 @@ meta_renderer_view_set_property (GObject *object, | |
meta_renderer_view_set_transform (view, g_value_get_uint (value)); | |
break; | |
case PROP_CRTC: | |
- view->crtc = g_value_get_object (value); | |
+ priv->crtc = g_value_get_object (value); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
diff --git a/src/backends/meta-renderer-view.h b/src/backends/meta-renderer-view.h | |
index 3f21c7c48cc..b6247f38c1c 100644 | |
--- a/src/backends/meta-renderer-view.h | |
+++ b/src/backends/meta-renderer-view.h | |
@@ -22,10 +22,15 @@ | |
#include "backends/meta-stage-impl-private.h" | |
#include "backends/meta-stage-view-private.h" | |
+struct _MetaRendererViewClass | |
+{ | |
+ MetaStageViewClass parent_class; | |
+}; | |
+ | |
#define META_TYPE_RENDERER_VIEW (meta_renderer_view_get_type ()) | |
-G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view, | |
- META, RENDERER_VIEW, | |
- MetaStageView) | |
+G_DECLARE_DERIVABLE_TYPE (MetaRendererView, meta_renderer_view, | |
+ META, RENDERER_VIEW, | |
+ MetaStageView) | |
MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view); | |
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c | |
index d538cc25a4c..ea3513f0232 100644 | |
--- a/src/backends/native/meta-renderer-native.c | |
+++ b/src/backends/native/meta-renderer-native.c | |
@@ -62,6 +62,7 @@ | |
#include "backends/native/meta-render-device-gbm.h" | |
#include "backends/native/meta-render-device-surfaceless.h" | |
#include "backends/native/meta-renderer-native-private.h" | |
+#include "backends/native/meta-renderer-view-native.h" | |
#include "cogl/cogl.h" | |
#include "core/boxes-private.h" | |
@@ -1240,7 +1241,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, | |
int onscreen_width; | |
int onscreen_height; | |
MetaRectangle view_layout; | |
- MetaRendererView *view; | |
+ MetaRendererViewNative *view_native; | |
EGLSurface egl_surface; | |
GError *error = NULL; | |
@@ -1352,26 +1353,27 @@ meta_renderer_native_create_view (MetaRenderer *renderer, | |
meta_rectangle_from_graphene_rect (&crtc_config->layout, | |
META_ROUNDING_STRATEGY_ROUND, | |
&view_layout); | |
- view = g_object_new (META_TYPE_RENDERER_VIEW, | |
- "name", meta_output_get_name (output), | |
- "stage", meta_backend_get_stage (backend), | |
- "layout", &view_layout, | |
- "crtc", crtc, | |
- "scale", scale, | |
- "framebuffer", framebuffer, | |
- "offscreen", offscreen, | |
- "use-shadowfb", use_shadowfb, | |
- "transform", view_transform, | |
- "refresh-rate", crtc_mode_info->refresh_rate, | |
- "vblank-duration-us", crtc_mode_info->vblank_duration_us, | |
- NULL); | |
+ view_native = g_object_new (META_TYPE_RENDERER_VIEW_NATIVE, | |
+ "name", meta_output_get_name (output), | |
+ "stage", meta_backend_get_stage (backend), | |
+ "layout", &view_layout, | |
+ "crtc", crtc, | |
+ "scale", scale, | |
+ "framebuffer", framebuffer, | |
+ "offscreen", offscreen, | |
+ "use-shadowfb", use_shadowfb, | |
+ "transform", view_transform, | |
+ "refresh-rate", crtc_mode_info->refresh_rate, | |
+ "vblank-duration-us", crtc_mode_info->vblank_duration_us, | |
+ NULL); | |
if (META_IS_ONSCREEN_NATIVE (framebuffer)) | |
{ | |
CoglDisplayEGL *cogl_display_egl; | |
CoglOnscreenEgl *onscreen_egl; | |
- meta_onscreen_native_set_view (COGL_ONSCREEN (framebuffer), view); | |
+ meta_onscreen_native_set_view (COGL_ONSCREEN (framebuffer), | |
+ META_RENDERER_VIEW (view_native)); | |
/* Ensure we don't point to stale surfaces when creating the offscreen */ | |
cogl_display_egl = cogl_display->winsys; | |
@@ -1383,7 +1385,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, | |
cogl_display_egl->egl_context); | |
} | |
- return view; | |
+ return META_RENDERER_VIEW (view_native); | |
} | |
static void | |
diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c | |
new file mode 100644 | |
index 00000000000..e64a1476ad5 | |
--- /dev/null | |
+++ b/src/backends/native/meta-renderer-view-native.c | |
@@ -0,0 +1,43 @@ | |
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | |
+ | |
+/* | |
+ * Copyright (C) 2020-2022 Dor Askayo | |
+ * | |
+ * 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. | |
+ * | |
+ * Written by: | |
+ * Dor Askayo <dor.askayo@gmail.com> | |
+ */ | |
+ | |
+#include "backends/native/meta-renderer-view-native.h" | |
+ | |
+struct _MetaRendererViewNative | |
+{ | |
+ MetaRendererView parent; | |
+}; | |
+ | |
+G_DEFINE_TYPE (MetaRendererViewNative, meta_renderer_view_native, | |
+ META_TYPE_RENDERER_VIEW) | |
+ | |
+static void | |
+meta_renderer_view_native_class_init (MetaRendererViewNativeClass *klass) | |
+{ | |
+} | |
+ | |
+static void | |
+meta_renderer_view_native_init (MetaRendererViewNative *view_native) | |
+{ | |
+} | |
diff --git a/src/backends/native/meta-renderer-view-native.h b/src/backends/native/meta-renderer-view-native.h | |
new file mode 100644 | |
index 00000000000..34c37939c1f | |
--- /dev/null | |
+++ b/src/backends/native/meta-renderer-view-native.h | |
@@ -0,0 +1,34 @@ | |
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | |
+ | |
+/* | |
+ * Copyright (C) 2020-2022 Dor Askayo | |
+ * | |
+ * 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. | |
+ * | |
+ * Written by: | |
+ * Dor Askayo <dor.askayo@gmail.com> | |
+ */ | |
+ | |
+#ifndef META_RENDERER_VIEW_NATIVE_H | |
+#define META_RENDERER_VIEW_NATIVE_H | |
+ | |
+#include "backends/meta-renderer-view.h" | |
+ | |
+#define META_TYPE_RENDERER_VIEW_NATIVE (meta_renderer_view_native_get_type ()) | |
+G_DECLARE_FINAL_TYPE (MetaRendererViewNative, meta_renderer_view_native, | |
+ META, RENDERER_VIEW_NATIVE, MetaRendererView) | |
+ | |
+#endif /* META_RENDERER_VIEW_NATIVE_H */ | |
diff --git a/src/meson.build b/src/meson.build | |
index f752f03d96f..d3d1ae0f490 100644 | |
--- a/src/meson.build | |
+++ b/src/meson.build | |
@@ -775,6 +775,8 @@ if have_native_backend | |
'backends/native/meta-renderer-native-private.h', | |
'backends/native/meta-renderer-native.c', | |
'backends/native/meta-renderer-native.h', | |
+ 'backends/native/meta-renderer-view-native.c', | |
+ 'backends/native/meta-renderer-view-native.h', | |
'backends/native/meta-seat-impl.c', | |
'backends/native/meta-seat-impl.h', | |
'backends/native/meta-seat-native.c', | |
-- | |
GitLab | |
From 02ada676a007e1c95ff424f1f373c33ff1bd46c5 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sat, 4 Jul 2020 22:13:55 +0300 | |
Subject: [PATCH 07/25] renderer-view/native: Allow syncing frame clock updates | |
with actor updates | |
Allow per-view tracking of actors for the purpose of synchronizing | |
the frame clock to their updates. | |
This uses the variable mode of ClutterFrameClock to either perform an | |
immediate update or a delayed update depending on whether the update | |
is performed in the context of the tracked actor or a different one. | |
This approach achieves a minimal latency between updates of the actor | |
and updates of the view, and delays updates of the view when the | |
tracked actor has not updated. | |
Changes in the synchronization mode are applied asynchronously at the | |
preparation phase of the next frame. | |
If the tracked actor is frozen or destroyed, the synchornization is | |
stopped as no further updates from the actor are expected. | |
For now, the only applicable synchronization mode is | |
META_FRAME_SYNC_MODE_DISABLED, which doesn't synchronize to actor | |
updates and keeps the frame clock on the its default fixed mode. | |
When support for VRR is added in the commits to follow, | |
META_FRAME_SYNC_MODE_ENABLED will be set when appropriate. | |
--- | |
src/backends/native/meta-renderer-native.c | 1 + | |
.../native/meta-renderer-view-native.c | 152 ++++++++++++++++++ | |
.../native/meta-renderer-view-native.h | 5 + | |
3 files changed, 158 insertions(+) | |
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c | |
index ea3513f0232..a45b2080604 100644 | |
--- a/src/backends/native/meta-renderer-native.c | |
+++ b/src/backends/native/meta-renderer-native.c | |
@@ -1453,6 +1453,7 @@ meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native, | |
kms_device = meta_kms_crtc_get_device (kms_crtc); | |
meta_crtc_kms_maybe_set_gamma (crtc_kms, kms_device); | |
+ meta_renderer_view_native_maybe_set_frame_sync (META_RENDERER_VIEW_NATIVE (view)); | |
} | |
void | |
diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c | |
index e64a1476ad5..c2b38e980b8 100644 | |
--- a/src/backends/native/meta-renderer-view-native.c | |
+++ b/src/backends/native/meta-renderer-view-native.c | |
@@ -24,20 +24,172 @@ | |
#include "backends/native/meta-renderer-view-native.h" | |
+#include "clutter/clutter.h" | |
+ | |
+typedef enum _MetaFrameSyncMode | |
+{ | |
+ META_FRAME_SYNC_MODE_INIT, | |
+ META_FRAME_SYNC_MODE_ENABLED, | |
+ META_FRAME_SYNC_MODE_DISABLED, | |
+} MetaFrameSyncMode; | |
+ | |
struct _MetaRendererViewNative | |
{ | |
MetaRendererView parent; | |
+ | |
+ gboolean frame_sync_mode_update_queued; | |
+ | |
+ MetaFrameSyncMode frame_sync_mode; | |
+ ClutterActor *frame_sync_actor; | |
+ | |
+ gulong frame_sync_actor_frozen_id; | |
+ gulong frame_sync_actor_destroy_id; | |
}; | |
G_DEFINE_TYPE (MetaRendererViewNative, meta_renderer_view_native, | |
META_TYPE_RENDERER_VIEW) | |
+static void | |
+on_frame_sync_actor_frozen (ClutterActor *actor, | |
+ MetaRendererViewNative *view_native) | |
+{ | |
+ meta_renderer_view_native_set_frame_sync_actor (view_native, NULL); | |
+} | |
+ | |
+static void | |
+on_frame_sync_actor_destroyed (ClutterActor *actor, | |
+ MetaRendererViewNative *view_native) | |
+{ | |
+ meta_renderer_view_native_set_frame_sync_actor (view_native, NULL); | |
+} | |
+ | |
+static void | |
+meta_renderer_view_native_schedule_actor_update (ClutterStageView *stage_view, | |
+ ClutterActor *actor) | |
+{ | |
+ MetaRendererViewNative *view_native = META_RENDERER_VIEW_NATIVE (stage_view); | |
+ ClutterFrameClock *frame_clock; | |
+ | |
+ g_return_if_fail (actor != NULL); | |
+ | |
+ frame_clock = clutter_stage_view_get_frame_clock (stage_view); | |
+ | |
+ if (view_native->frame_sync_mode == META_FRAME_SYNC_MODE_ENABLED && | |
+ actor == view_native->frame_sync_actor) | |
+ clutter_frame_clock_schedule_update_now (frame_clock); | |
+ else | |
+ clutter_frame_clock_schedule_update (frame_clock); | |
+} | |
+ | |
+void | |
+meta_renderer_view_native_set_frame_sync_actor (MetaRendererViewNative *view_native, | |
+ ClutterActor *actor) | |
+{ | |
+ if (G_LIKELY (actor == view_native->frame_sync_actor)) | |
+ return; | |
+ | |
+ g_clear_signal_handler (&view_native->frame_sync_actor_frozen_id, | |
+ view_native->frame_sync_actor); | |
+ g_clear_signal_handler (&view_native->frame_sync_actor_destroy_id, | |
+ view_native->frame_sync_actor); | |
+ | |
+ if (actor) | |
+ { | |
+ view_native->frame_sync_actor_frozen_id = | |
+ g_signal_connect (actor, "frozen", | |
+ G_CALLBACK (on_frame_sync_actor_frozen), | |
+ view_native); | |
+ view_native->frame_sync_actor_destroy_id = | |
+ g_signal_connect (actor, "destroy", | |
+ G_CALLBACK (on_frame_sync_actor_destroyed), | |
+ view_native); | |
+ } | |
+ | |
+ view_native->frame_sync_actor = actor; | |
+ | |
+ view_native->frame_sync_mode_update_queued = TRUE; | |
+} | |
+ | |
+static void | |
+meta_renderer_view_native_set_frame_sync (MetaRendererViewNative *view_native, | |
+ MetaFrameSyncMode sync_mode) | |
+{ | |
+ ClutterFrameClock *frame_clock = | |
+ clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (view_native)); | |
+ | |
+ switch (sync_mode) | |
+ { | |
+ case META_FRAME_SYNC_MODE_ENABLED: | |
+ clutter_frame_clock_set_mode (frame_clock, | |
+ CLUTTER_FRAME_CLOCK_MODE_VARIABLE); | |
+ break; | |
+ case META_FRAME_SYNC_MODE_DISABLED: | |
+ clutter_frame_clock_set_mode (frame_clock, | |
+ CLUTTER_FRAME_CLOCK_MODE_FIXED); | |
+ break; | |
+ case META_FRAME_SYNC_MODE_INIT: | |
+ g_assert_not_reached (); | |
+ } | |
+ | |
+ view_native->frame_sync_mode = sync_mode; | |
+} | |
+ | |
+static MetaFrameSyncMode | |
+meta_renderer_view_native_get_applicable_sync_mode (MetaRendererViewNative *view_native) | |
+{ | |
+ return META_FRAME_SYNC_MODE_DISABLED; | |
+} | |
+ | |
+void | |
+meta_renderer_view_native_maybe_set_frame_sync (MetaRendererViewNative *view_native) | |
+{ | |
+ MetaFrameSyncMode applicable_sync_mode; | |
+ | |
+ if (G_LIKELY (!view_native->frame_sync_mode_update_queued)) | |
+ return; | |
+ | |
+ view_native->frame_sync_mode_update_queued = FALSE; | |
+ | |
+ applicable_sync_mode = | |
+ meta_renderer_view_native_get_applicable_sync_mode (view_native); | |
+ | |
+ if (applicable_sync_mode != view_native->frame_sync_mode) | |
+ { | |
+ meta_renderer_view_native_set_frame_sync (view_native, | |
+ applicable_sync_mode); | |
+ } | |
+} | |
+ | |
+static void | |
+meta_renderer_view_native_dispose (GObject *object) | |
+{ | |
+ MetaRendererViewNative *view_native = META_RENDERER_VIEW_NATIVE (object); | |
+ | |
+ if (view_native->frame_sync_actor) | |
+ { | |
+ g_clear_signal_handler (&view_native->frame_sync_actor_destroy_id, | |
+ view_native->frame_sync_actor); | |
+ g_clear_signal_handler (&view_native->frame_sync_actor_frozen_id, | |
+ view_native->frame_sync_actor); | |
+ } | |
+ | |
+ G_OBJECT_CLASS (meta_renderer_view_native_parent_class)->dispose (object); | |
+} | |
+ | |
static void | |
meta_renderer_view_native_class_init (MetaRendererViewNativeClass *klass) | |
{ | |
+ GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
+ ClutterStageViewClass *clutter_stage_view_class = CLUTTER_STAGE_VIEW_CLASS (klass); | |
+ | |
+ object_class->dispose = meta_renderer_view_native_dispose; | |
+ | |
+ clutter_stage_view_class->schedule_actor_update = meta_renderer_view_native_schedule_actor_update; | |
} | |
static void | |
meta_renderer_view_native_init (MetaRendererViewNative *view_native) | |
{ | |
+ view_native->frame_sync_mode_update_queued = TRUE; | |
+ view_native->frame_sync_mode = META_FRAME_SYNC_MODE_INIT; | |
} | |
diff --git a/src/backends/native/meta-renderer-view-native.h b/src/backends/native/meta-renderer-view-native.h | |
index 34c37939c1f..16e3a8d48bf 100644 | |
--- a/src/backends/native/meta-renderer-view-native.h | |
+++ b/src/backends/native/meta-renderer-view-native.h | |
@@ -31,4 +31,9 @@ | |
G_DECLARE_FINAL_TYPE (MetaRendererViewNative, meta_renderer_view_native, | |
META, RENDERER_VIEW_NATIVE, MetaRendererView) | |
+void meta_renderer_view_native_set_frame_sync_actor (MetaRendererViewNative *view_native, | |
+ ClutterActor *actor); | |
+ | |
+void meta_renderer_view_native_maybe_set_frame_sync (MetaRendererViewNative *view_native); | |
+ | |
#endif /* META_RENDERER_VIEW_NATIVE_H */ | |
-- | |
GitLab | |
From b5520550fe1c60625df401fdc44a4ba8d78d28cb Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sun, 16 Aug 2020 10:07:54 +0300 | |
Subject: [PATCH 09/25] clutter/stage: Always schedule actor updates on redraw | |
When updates are scheduled in the context of specific actors, | |
already-scheduled updates may need to be rescheduled based on the | |
actor requesting the update. | |
Allow scheduling updates for actors when the stage is already | |
pending a redraw. | |
--- | |
clutter/clutter/clutter-stage.c | 21 +-------------------- | |
1 file changed, 1 insertion(+), 20 deletions(-) | |
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c | |
index 3e81655e01e..f40df1017dc 100644 | |
--- a/clutter/clutter/clutter-stage.c | |
+++ b/clutter/clutter/clutter-stage.c | |
@@ -127,8 +127,6 @@ struct _ClutterStagePrivate | |
int update_freeze_count; | |
- gboolean pending_finish_queue_redraws; | |
- | |
GHashTable *pointer_devices; | |
GHashTable *touch_sequences; | |
@@ -2548,19 +2546,7 @@ clutter_stage_queue_actor_redraw (ClutterStage *stage, | |
CLUTTER_NOTE (CLIPPING, "stage_queue_actor_redraw (actor=%s, clip=%p): ", | |
_clutter_actor_get_debug_name (actor), clip); | |
- if (!priv->pending_finish_queue_redraws) | |
- { | |
- GList *l; | |
- | |
- for (l = clutter_stage_peek_stage_views (stage); l; l = l->next) | |
- { | |
- ClutterStageView *view = l->data; | |
- | |
- clutter_stage_view_schedule_update (view); | |
- } | |
- | |
- priv->pending_finish_queue_redraws = TRUE; | |
- } | |
+ clutter_stage_schedule_actor_update (stage, actor); | |
entry = g_hash_table_lookup (priv->pending_queue_redraws, actor); | |
@@ -2684,11 +2670,6 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage) | |
COGL_TRACE_BEGIN_SCOPED (ClutterStageFinishQueueRedraws, "FinishQueueRedraws"); | |
- if (!priv->pending_finish_queue_redraws) | |
- return; | |
- | |
- priv->pending_finish_queue_redraws = FALSE; | |
- | |
g_hash_table_iter_init (&iter, priv->pending_queue_redraws); | |
while (g_hash_table_iter_next (&iter, &key, &value)) | |
{ | |
-- | |
GitLab | |
From 9bd5eef4043c2ce25e5c228bec0edeef7f2826bd Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sat, 11 Jun 2022 12:50:02 +0300 | |
Subject: [PATCH 13/25] window: Allow checking if a window covers a rect | |
This is just a small function to improve the readability of the code. | |
--- | |
src/core/window-private.h | 3 +++ | |
src/core/window.c | 8 ++++++++ | |
2 files changed, 11 insertions(+) | |
diff --git a/src/core/window-private.h b/src/core/window-private.h | |
index 8d2d4a02032..9765aa5c86a 100644 | |
--- a/src/core/window-private.h | |
+++ b/src/core/window-private.h | |
@@ -716,6 +716,9 @@ void meta_window_get_session_geometry (MetaWindow *window, | |
int *width, | |
int *height); | |
+gboolean meta_window_frame_contains_rect (MetaWindow *window, | |
+ MetaRectangle *rect); | |
+ | |
void meta_window_update_unfocused_button_grabs (MetaWindow *window); | |
void meta_window_update_appears_focused (MetaWindow *window); | |
diff --git a/src/core/window.c b/src/core/window.c | |
index 95a8e33e048..af68011f164 100644 | |
--- a/src/core/window.c | |
+++ b/src/core/window.c | |
@@ -4250,6 +4250,14 @@ meta_window_get_session_geometry (MetaWindow *window, | |
window->size_hints.height_inc; | |
} | |
+gboolean | |
+meta_window_frame_contains_rect (MetaWindow *window, | |
+ MetaRectangle *rect) | |
+{ | |
+ return meta_rectangle_contains_rect (&window->rect, | |
+ rect); | |
+} | |
+ | |
/** | |
* meta_window_get_buffer_rect: | |
* @window: a #MetaWindow | |
-- | |
GitLab | |
From 631cafccb6ed5150cd45628148efd11e31206c53 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 14 Jun 2022 01:04:03 +0300 | |
Subject: [PATCH 14/25] surface-actor: Allow checking if a surface actor covers | |
a rect | |
--- | |
src/compositor/meta-surface-actor.c | 16 ++++++++++++++++ | |
src/compositor/meta-surface-actor.h | 3 +++ | |
2 files changed, 19 insertions(+) | |
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c | |
index 978ccf9e61b..d5a32085caa 100644 | |
--- a/src/compositor/meta-surface-actor.c | |
+++ b/src/compositor/meta-surface-actor.c | |
@@ -521,6 +521,22 @@ meta_surface_actor_is_obscured_on_stage_view (MetaSurfaceActor *self, | |
stage_view); | |
} | |
+gboolean | |
+meta_surface_actor_contains_rect (MetaSurfaceActor *surface_actor, | |
+ MetaRectangle *rect) | |
+{ | |
+ ClutterActor *actor = CLUTTER_ACTOR (surface_actor); | |
+ graphene_rect_t bounding_rect; | |
+ graphene_rect_t bound_rect; | |
+ | |
+ clutter_actor_get_transformed_extents (actor, &bounding_rect); | |
+ | |
+ _clutter_util_rect_from_rectangle (rect, &bound_rect); | |
+ | |
+ return graphene_rect_contains_rect (&bounding_rect, | |
+ &bound_rect); | |
+} | |
+ | |
void | |
meta_surface_actor_set_input_region (MetaSurfaceActor *self, | |
cairo_region_t *region) | |
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h | |
index f69cb15275e..3128f513cd1 100644 | |
--- a/src/compositor/meta-surface-actor.h | |
+++ b/src/compositor/meta-surface-actor.h | |
@@ -40,6 +40,9 @@ gboolean meta_surface_actor_is_obscured_on_stage_view (MetaSurfaceActor *self, | |
ClutterStageView *stage_view, | |
float *unobscurred_fraction); | |
+gboolean meta_surface_actor_contains_rect (MetaSurfaceActor *surface_actor, | |
+ MetaRectangle *rect); | |
+ | |
void meta_surface_actor_set_input_region (MetaSurfaceActor *self, | |
cairo_region_t *region); | |
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | |
-- | |
GitLab | |
From 3e5aab85d24252cba7ac9163bee621f976ba0594 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 17 Mar 2020 01:44:25 +0200 | |
Subject: [PATCH 16/25] compositor/native: Request frame sync for compatible | |
windows | |
--- | |
src/compositor/meta-compositor-native.c | 5 ++ | |
src/compositor/meta-compositor-view-native.c | 74 ++++++++++++++++++++ | |
src/compositor/meta-compositor-view-native.h | 4 ++ | |
3 files changed, 83 insertions(+) | |
diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c | |
index a156be7da24..63680b6d81c 100644 | |
--- a/src/compositor/meta-compositor-native.c | |
+++ b/src/compositor/meta-compositor-native.c | |
@@ -45,6 +45,9 @@ static void | |
compositor); | |
#endif | |
+ meta_compositor_view_native_maybe_set_frame_sync (compositor_view_native, | |
+ compositor); | |
+ | |
parent_class = META_COMPOSITOR_CLASS (meta_compositor_native_parent_class); | |
parent_class->before_paint (compositor, compositor_view); | |
} | |
diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c | |
index e46b615cf80..9a4558c67dc 100644 | |
--- a/src/compositor/meta-compositor-view-native.c | |
+++ b/src/compositor/meta-compositor-view-native.c | |
@@ -28,6 +28,7 @@ | |
#include "backends/meta-crtc.h" | |
#include "backends/native/meta-crtc-kms.h" | |
+#include "backends/native/meta-renderer-view-native.h" | |
#include "compositor/compositor-private.h" | |
#include "compositor/meta-window-actor-private.h" | |
@@ -32,6 +37,75 @@ struct _MetaCompositorViewNative | |
G_DEFINE_TYPE (MetaCompositorViewNative, meta_compositor_view_native, | |
META_TYPE_COMPOSITOR_VIEW) | |
+static ClutterActor * | |
+find_frame_sync_actor (MetaCompositorView *compositor_view, | |
+ MetaCompositor *compositor) | |
+{ | |
+ MetaWindowActor *window_actor; | |
+ MetaWindow *window; | |
+ ClutterStageView *stage_view; | |
+ MetaRectangle view_layout; | |
+ MetaSurfaceActor *surface_actor; | |
+ | |
+ if (meta_compositor_is_unredirect_inhibited (compositor)) | |
+ return NULL; | |
+ | |
+ window_actor = | |
+ meta_compositor_view_get_top_window_actor (compositor_view); | |
+ if (!window_actor) | |
+ return NULL; | |
+ | |
+ if (meta_window_actor_is_frozen (window_actor)) | |
+ return NULL; | |
+ | |
+ if (meta_window_actor_effect_in_progress (window_actor)) | |
+ return NULL; | |
+ | |
+ if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor))) | |
+ return NULL; | |
+ | |
+ window = meta_window_actor_get_meta_window (window_actor); | |
+ if (!window) | |
+ return NULL; | |
+ | |
+ stage_view = meta_compositor_view_get_stage_view (compositor_view); | |
+ | |
+ clutter_stage_view_get_layout (stage_view, &view_layout); | |
+ | |
+ if (!meta_window_frame_contains_rect (window, &view_layout)) | |
+ return NULL; | |
+ | |
+ surface_actor = meta_window_actor_get_scanout_candidate (window_actor); | |
+ if (!surface_actor) | |
+ return NULL; | |
+ | |
+ if (!meta_surface_actor_contains_rect (surface_actor, | |
+ &view_layout)) | |
+ return NULL; | |
+ | |
+ return CLUTTER_ACTOR (surface_actor); | |
+} | |
+ | |
+void | |
+meta_compositor_view_native_maybe_set_frame_sync (MetaCompositorViewNative *view_native, | |
+ MetaCompositor *compositor) | |
+{ | |
+ MetaCompositorView *compositor_view = | |
+ META_COMPOSITOR_VIEW (view_native); | |
+ ClutterActor *frame_sync_actor; | |
+ MetaRendererViewNative *renderer_view_native; | |
+ ClutterStageView *stage_view; | |
+ | |
+ frame_sync_actor = find_frame_sync_actor (compositor_view, | |
+ compositor); | |
+ | |
+ stage_view = meta_compositor_view_get_stage_view (compositor_view); | |
+ renderer_view_native = META_RENDERER_VIEW_NATIVE (stage_view); | |
+ | |
+ meta_renderer_view_native_set_frame_sync_actor (renderer_view_native, | |
+ frame_sync_actor); | |
+} | |
+ | |
#ifdef HAVE_WAYLAND | |
static void | |
update_scanout_candidate (MetaCompositorViewNative *view_native, | |
diff --git a/src/compositor/meta-compositor-view-native.h b/src/compositor/meta-compositor-view-native.h | |
index d0971cef34c..301e26f7d71 100644 | |
--- a/src/compositor/meta-compositor-view-native.h | |
+++ b/src/compositor/meta-compositor-view-native.h | |
@@ -34,6 +35,9 @@ G_DECLARE_FINAL_TYPE (MetaCompositorViewNative, meta_compositor_view_native, | |
MetaCompositorViewNative *meta_compositor_view_native_new (ClutterStageView *stage_view); | |
+void meta_compositor_view_native_maybe_set_frame_sync (MetaCompositorViewNative *view_native, | |
+ MetaCompositor *compositor); | |
+ | |
#ifdef HAVE_WAYLAND | |
void meta_compositor_view_native_maybe_assign_scanout (MetaCompositorViewNative *view_native, | |
MetaCompositor *compositor); | |
-- | |
GitLab | |
From dcbb4054171fd546ac217bd16a4e493684d902a4 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 17 Mar 2020 21:42:37 +0200 | |
Subject: [PATCH 17/25] connector/kms: Detect variable refresh rate capability | |
The "vrr_capable" property indicates whether variable refresh rate is | |
supported for a connector. | |
--- | |
src/backends/native/meta-kms-connector.c | 7 +++++++ | |
src/backends/native/meta-kms-connector.h | 2 ++ | |
2 files changed, 9 insertions(+) | |
diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h | |
index 66b2fa6fb..a5a909cd4 100644 | |
--- a/src/backends/native/meta-kms-connector-private.h | |
+++ b/src/backends/native/meta-kms-connector-private.h | |
@@ -40,6 +40,7 @@ typedef enum _MetaKmsConnectorProp | |
META_KMS_CONNECTOR_PROP_PANEL_ORIENTATION, | |
META_KMS_CONNECTOR_PROP_NON_DESKTOP, | |
META_KMS_CONNECTOR_PROP_MAX_BPC, | |
+ META_KMS_CONNECTOR_PROP_VRR_CAPABLE, | |
META_KMS_CONNECTOR_N_PROPS | |
} MetaKmsConnectorProp; | |
diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c | |
index b7550e12ee0..dc906035b58 100644 | |
--- a/src/backends/native/meta-kms-connector.c | |
+++ b/src/backends/native/meta-kms-connector.c | |
@@ -329,6 +329,10 @@ state_set_properties (MetaKmsConnectorState *state, | |
state->max_bpc.min_value = prop->range_min; | |
state->max_bpc.max_value = prop->range_max; | |
} | |
+ | |
+ prop = &props[META_KMS_CONNECTOR_PROP_VRR_CAPABLE]; | |
+ if (prop->prop_id) | |
+ state->vrr_capable = prop->value; | |
} | |
static CoglSubpixelOrder | |
@@ -541,6 +544,7 @@ meta_kms_connector_state_new (void) | |
state = g_new0 (MetaKmsConnectorState, 1); | |
state->suggested_x = -1; | |
state->suggested_y = -1; | |
+ state->vrr_capable = FALSE; | |
return state; | |
} | |
@@ -636,6 +640,9 @@ meta_kms_connector_state_changes (MetaKmsConnectorState *state, | |
if (!kms_modes_equal (state->modes, new_state->modes)) | |
return META_KMS_RESOURCE_CHANGE_FULL; | |
+ if (state->vrr_capable != new_state->vrr_capable) | |
+ return META_KMS_RESOURCE_CHANGE_FULL; | |
+ | |
if (state->max_bpc.value != new_state->max_bpc.value || | |
state->max_bpc.min_value != new_state->max_bpc.min_value || | |
state->max_bpc.max_value != new_state->max_bpc.max_value) | |
@@ -967,6 +971,11 @@ init_properties (MetaKmsConnector *connector, | |
.name = "max bpc", | |
.type = DRM_MODE_PROP_RANGE, | |
}, | |
+ [META_KMS_CONNECTOR_PROP_VRR_CAPABLE] = | |
+ { | |
+ .name = "vrr_capable", | |
+ .type = DRM_MODE_PROP_RANGE, | |
+ }, | |
}, | |
.dpms_enum = { | |
[META_KMS_CONNECTOR_DPMS_ON] = | |
diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h | |
index c2b763548e8..381edca973e 100644 | |
--- a/src/backends/native/meta-kms-connector.h | |
+++ b/src/backends/native/meta-kms-connector.h | |
@@ -59,6 +59,8 @@ typedef struct _MetaKmsConnectorState | |
MetaMonitorTransform panel_orientation_transform; | |
MetaKmsRange max_bpc; | |
+ | |
+ gboolean vrr_capable; | |
} MetaKmsConnectorState; | |
META_EXPORT_TEST | |
-- | |
GitLab | |
From d78c33dbf8ac2ad9a155335f1072138be3d10485 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sat, 2 Jul 2022 17:10:36 +0300 | |
Subject: [PATCH 19/25] kms: Allow setting the "VRR_ENABLED" property on a CRTC | |
Add the "VRR_ENABLED" propetry ID and a function to update its value | |
on a CRTC. | |
This requires the addition of an infrastrucure to create and process | |
CRTC property updates similarly to connector updates, in both the | |
atomic and the simple KMS backends. | |
--- | |
src/backends/native/meta-kms-crtc-private.h | 8 ++ | |
src/backends/native/meta-kms-crtc.c | 5 ++ | |
.../native/meta-kms-impl-device-atomic.c | 43 ++++++++++ | |
.../native/meta-kms-impl-device-simple.c | 78 +++++++++++++++++++ | |
src/backends/native/meta-kms-update-private.h | 13 ++++ | |
src/backends/native/meta-kms-update.c | 47 +++++++++++ | |
src/backends/native/meta-kms-update.h | 4 + | |
7 files changed, 198 insertions(+) | |
diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h | |
index 65bda3f10b3..9575b61e123 100644 | |
--- a/src/backends/native/meta-kms-crtc-private.h | |
+++ b/src/backends/native/meta-kms-crtc-private.h | |
@@ -30,9 +30,17 @@ typedef enum _MetaKmsCrtcProp | |
META_KMS_CRTC_PROP_MODE_ID = 0, | |
META_KMS_CRTC_PROP_ACTIVE, | |
META_KMS_CRTC_PROP_GAMMA_LUT, | |
+ META_KMS_CRTC_PROP_VRR_ENABLED, | |
META_KMS_CRTC_N_PROPS | |
} MetaKmsCrtcProp; | |
+typedef enum _MetaKmsCrtcVRRMode | |
+{ | |
+ META_KMS_CRTC_VRR_MODE_DISABLED = 0, | |
+ META_KMS_CRTC_VRR_MODE_ENABLED, | |
+ META_KMS_CRTC_VRR_MODE_N_PROPS, | |
+} MetaKmsCrtcVRRMode; | |
+ | |
MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, | |
drmModeCrtc *drm_crtc, | |
int idx, | |
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c | |
index e9bd9308b20..b00ccca7191 100644 | |
--- a/src/backends/native/meta-kms-crtc.c | |
+++ b/src/backends/native/meta-kms-crtc.c | |
@@ -390,6 +390,11 @@ init_properties (MetaKmsCrtc *crtc, | |
.name = "GAMMA_LUT", | |
.type = DRM_MODE_PROP_BLOB, | |
}, | |
+ [META_KMS_CRTC_PROP_VRR_ENABLED] = | |
+ { | |
+ .name = "VRR_ENABLED", | |
+ .type = DRM_MODE_PROP_RANGE, | |
+ }, | |
} | |
}; | |
} | |
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c | |
index f21740e298b..0a26d2780fb 100644 | |
--- a/src/backends/native/meta-kms-impl-device-atomic.c | |
+++ b/src/backends/native/meta-kms-impl-device-atomic.c | |
@@ -261,6 +261,39 @@ add_crtc_property (MetaKmsImplDevice *impl_device, | |
return TRUE; | |
} | |
+static gboolean | |
+process_crtc_update (MetaKmsImplDevice *impl_device, | |
+ MetaKmsUpdate *update, | |
+ drmModeAtomicReq *req, | |
+ GArray *blob_ids, | |
+ gpointer update_entry, | |
+ gpointer user_data, | |
+ GError **error) | |
+{ | |
+ MetaKmsCrtcUpdate *crtc_update = update_entry; | |
+ MetaKmsCrtc *crtc = crtc_update->crtc; | |
+ | |
+ if (crtc_update->vrr_mode.has_update) | |
+ { | |
+ meta_topic (META_DEBUG_KMS, | |
+ "[atomic] Setting VRR mode to %d on CRTC %u (%s)", | |
+ crtc_update->vrr_mode.is_enabled ? | |
+ META_KMS_CRTC_VRR_MODE_ENABLED : | |
+ META_KMS_CRTC_VRR_MODE_DISABLED, | |
+ meta_kms_crtc_get_id (crtc), | |
+ meta_kms_impl_device_get_path (impl_device)); | |
+ | |
+ if (!add_crtc_property (impl_device, | |
+ crtc, req, | |
+ META_KMS_CRTC_PROP_VRR_ENABLED, | |
+ crtc_update->vrr_mode.is_enabled, | |
+ error)) | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
static gboolean | |
process_mode_set (MetaKmsImplDevice *impl_device, | |
MetaKmsUpdate *update, | |
@@ -948,6 +981,16 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, | |
&error)) | |
goto err; | |
+ if (!process_entries (impl_device, | |
+ update, | |
+ req, | |
+ blob_ids, | |
+ meta_kms_update_get_crtc_updates (update), | |
+ NULL, | |
+ process_crtc_update, | |
+ &error)) | |
+ goto err; | |
+ | |
if (!process_entries (impl_device, | |
update, | |
req, | |
diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c | |
index ca4ffe24544..89310ce0f38 100644 | |
--- a/src/backends/native/meta-kms-impl-device-simple.c | |
+++ b/src/backends/native/meta-kms-impl-device-simple.c | |
@@ -180,6 +180,47 @@ set_connector_property (MetaKmsImplDevice *impl_device, | |
return TRUE; | |
} | |
+static gboolean | |
+set_crtc_property (MetaKmsImplDevice *impl_device, | |
+ MetaKmsCrtc *crtc, | |
+ MetaKmsCrtcProp prop, | |
+ uint64_t value, | |
+ GError **error) | |
+{ | |
+ uint32_t prop_id; | |
+ int fd; | |
+ int ret; | |
+ | |
+ prop_id = meta_kms_crtc_get_prop_id (crtc, prop); | |
+ if (!prop_id) | |
+ { | |
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, | |
+ "Property (%s) not found on CRTC %u", | |
+ meta_kms_crtc_get_prop_name (crtc, prop), | |
+ meta_kms_crtc_get_id (crtc)); | |
+ return FALSE; | |
+ } | |
+ | |
+ fd = meta_kms_impl_device_get_fd (impl_device); | |
+ | |
+ ret = drmModeObjectSetProperty (fd, | |
+ meta_kms_crtc_get_id (crtc), | |
+ DRM_MODE_OBJECT_CRTC, | |
+ prop_id, | |
+ value); | |
+ if (ret != 0) | |
+ { | |
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), | |
+ "Failed to set CRTC %u property %u: %s", | |
+ meta_kms_crtc_get_id (crtc), | |
+ prop_id, | |
+ g_strerror (-ret)); | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
static gboolean | |
process_connector_update (MetaKmsImplDevice *impl_device, | |
MetaKmsUpdate *update, | |
@@ -253,6 +294,36 @@ process_connector_update (MetaKmsImplDevice *impl_device, | |
return TRUE; | |
} | |
+static gboolean | |
+process_crtc_update (MetaKmsImplDevice *impl_device, | |
+ MetaKmsUpdate *update, | |
+ gpointer update_entry, | |
+ GError **error) | |
+{ | |
+ MetaKmsCrtcUpdate *crtc_update = update_entry; | |
+ MetaKmsCrtc *crtc = crtc_update->crtc; | |
+ | |
+ if (crtc_update->vrr_mode.has_update) | |
+ { | |
+ meta_topic (META_DEBUG_KMS, | |
+ "[simple] Setting VRR mode to %d on CRTC %u (%s)", | |
+ crtc_update->vrr_mode.is_enabled ? | |
+ META_KMS_CRTC_VRR_MODE_ENABLED : | |
+ META_KMS_CRTC_VRR_MODE_DISABLED, | |
+ meta_kms_crtc_get_id (crtc), | |
+ meta_kms_impl_device_get_path (impl_device)); | |
+ | |
+ if (!set_crtc_property (impl_device, | |
+ crtc, | |
+ META_KMS_CRTC_PROP_VRR_ENABLED, | |
+ crtc_update->vrr_mode.is_enabled, | |
+ error)) | |
+ return FALSE; | |
+ } | |
+ | |
+ return TRUE; | |
+} | |
+ | |
static CachedModeSet * | |
cached_mode_set_new (GList *connectors, | |
const drmModeModeInfo *drm_mode, | |
@@ -1492,6 +1563,13 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, | |
&error)) | |
goto err; | |
+ if (!process_entries (impl_device, | |
+ update, | |
+ meta_kms_update_get_crtc_updates (update), | |
+ process_crtc_update, | |
+ &error)) | |
+ goto err; | |
+ | |
if (!process_entries (impl_device, | |
update, | |
meta_kms_update_get_crtc_gammas (update), | |
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h | |
index d76c2d89f4f..442da6b4ca3 100644 | |
--- a/src/backends/native/meta-kms-update-private.h | |
+++ b/src/backends/native/meta-kms-update-private.h | |
@@ -84,6 +84,16 @@ typedef struct _MetaKmsConnectorUpdate | |
} max_bpc; | |
} MetaKmsConnectorUpdate; | |
+typedef struct _MetaKmsCrtcUpdate | |
+{ | |
+ MetaKmsCrtc *crtc; | |
+ | |
+ struct { | |
+ gboolean has_update; | |
+ gboolean is_enabled; | |
+ } vrr_mode; | |
+} MetaKmsCrtcUpdate; | |
+ | |
typedef struct _MetaKmsPageFlipListener | |
{ | |
MetaKmsCrtc *crtc; | |
@@ -157,6 +167,9 @@ void meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update); | |
META_EXPORT_TEST | |
GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update); | |
+META_EXPORT_TEST | |
+GList * meta_kms_update_get_crtc_updates (MetaKmsUpdate *update); | |
+ | |
META_EXPORT_TEST | |
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update); | |
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c | |
index ec4ff23ce88..dc3dc3fef1f 100644 | |
--- a/src/backends/native/meta-kms-update.c | |
+++ b/src/backends/native/meta-kms-update.c | |
@@ -38,6 +38,7 @@ struct _MetaKmsUpdate | |
GList *mode_sets; | |
GList *plane_assignments; | |
GList *connector_updates; | |
+ GList *crtc_updates; | |
GList *crtc_gammas; | |
MetaKmsCustomPageFlip *custom_page_flip; | |
@@ -408,6 +409,45 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, | |
update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma); | |
} | |
+static MetaKmsCrtcUpdate * | |
+ensure_crtc_update (MetaKmsUpdate *update, | |
+ MetaKmsCrtc *crtc) | |
+{ | |
+ GList *l; | |
+ MetaKmsCrtcUpdate *crtc_update; | |
+ | |
+ for (l = update->crtc_updates; l; l = l->next) | |
+ { | |
+ crtc_update = l->data; | |
+ | |
+ if (crtc_update->crtc == crtc) | |
+ return crtc_update; | |
+ } | |
+ | |
+ crtc_update = g_new0 (MetaKmsCrtcUpdate, 1); | |
+ crtc_update->crtc = crtc; | |
+ | |
+ update->crtc_updates = g_list_prepend (update->crtc_updates, | |
+ crtc_update); | |
+ | |
+ return crtc_update; | |
+} | |
+ | |
+void | |
+meta_kms_update_set_vrr_mode (MetaKmsUpdate *update, | |
+ MetaKmsCrtc *crtc, | |
+ gboolean enabled) | |
+{ | |
+ MetaKmsCrtcUpdate *crtc_update; | |
+ | |
+ g_assert (!meta_kms_update_is_locked (update)); | |
+ g_assert (meta_kms_crtc_get_device (crtc) == update->device); | |
+ | |
+ crtc_update = ensure_crtc_update (update, crtc); | |
+ crtc_update->vrr_mode.has_update = TRUE; | |
+ crtc_update->vrr_mode.is_enabled = enabled; | |
+} | |
+ | |
void | |
meta_kms_update_add_page_flip_listener (MetaKmsUpdate *update, | |
MetaKmsCrtc *crtc, | |
@@ -639,6 +679,12 @@ meta_kms_update_get_connector_updates (MetaKmsUpdate *update) | |
return update->connector_updates; | |
} | |
+GList * | |
+meta_kms_update_get_crtc_updates (MetaKmsUpdate *update) | |
+{ | |
+ return update->crtc_updates; | |
+} | |
+ | |
GList * | |
meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update) | |
{ | |
@@ -719,6 +765,7 @@ meta_kms_update_free (MetaKmsUpdate *update) | |
g_list_free_full (update->page_flip_listeners, | |
(GDestroyNotify) meta_kms_page_flip_listener_free); | |
g_list_free_full (update->connector_updates, g_free); | |
+ g_list_free_full (update->crtc_updates, g_free); | |
g_list_free_full (update->crtc_gammas, (GDestroyNotify) meta_kms_crtc_gamma_free); | |
g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free); | |
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h | |
index f31e36aad3e..4e963833ffb 100644 | |
--- a/src/backends/native/meta-kms-update.h | |
+++ b/src/backends/native/meta-kms-update.h | |
@@ -123,6 +123,10 @@ void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, | |
const uint16_t *green, | |
const uint16_t *blue); | |
+void meta_kms_update_set_vrr_mode (MetaKmsUpdate *update, | |
+ MetaKmsCrtc *crtc, | |
+ gboolean enabled); | |
+ | |
void meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment, | |
const int *rectangles, | |
int n_rectangles); | |
-- | |
GitLab | |
From 27879b7b36d4a269943a42d41c70cd8603fb855b Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sun, 31 Jul 2022 14:04:01 +0300 | |
Subject: [PATCH 20/25] backends/native: Disable VRR for i915 using a udev rule | |
The i915 DRM driver currently requires setting the | |
DRM_MODE_ATOMIC_ALLOW_MODESET flag on the atomic commit when updating | |
the "VRR_ENABLED" KMS property. | |
However, we prefer not to allow a modeset in the context of VRR to | |
avoid a potential blanking of the monitor and a bad user experience | |
around enabling and disabling VRR dynamically. As such, disable | |
support for VRR with i915 using a udev rule for now. | |
--- | |
data/61-mutter.rules | 2 +- | |
src/backends/native/meta-backend-native.c | 3 +++ | |
src/backends/native/meta-gpu-kms.c | 9 +++++++++ | |
src/backends/native/meta-gpu-kms.h | 1 + | |
src/backends/native/meta-kms-types.h | 5 +++-- | |
src/backends/native/meta-udev.c | 7 +++++++ | |
src/backends/native/meta-udev.h | 2 ++ | |
7 files changed, 26 insertions(+), 3 deletions(-) | |
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c | |
index 22453878766..cca0745045a 100644 | |
--- a/src/backends/native/meta-backend-native.c | |
+++ b/src/backends/native/meta-backend-native.c | |
@@ -448,6 +448,9 @@ create_gpu_from_udev_device (MetaBackendNative *native, | |
if (meta_is_udev_device_disable_client_modifiers (device)) | |
flags |= META_KMS_DEVICE_FLAG_DISABLE_CLIENT_MODIFIERS; | |
+ if (meta_is_udev_device_disable_vrr (device)) | |
+ flags |= META_KMS_DEVICE_FLAG_DISABLE_VRR; | |
+ | |
if (meta_is_udev_device_preferred_primary (device)) | |
flags |= META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY; | |
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c | |
index 97b47f9f9c8..f30363dc996 100644 | |
--- a/src/backends/native/meta-gpu-kms.c | |
+++ b/src/backends/native/meta-gpu-kms.c | |
@@ -143,6 +143,15 @@ meta_gpu_kms_disable_modifiers (MetaGpuKms *gpu_kms) | |
return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE); | |
} | |
+gboolean | |
+meta_gpu_kms_disable_vrr (MetaGpuKms *gpu_kms) | |
+{ | |
+ MetaKmsDeviceFlag flags; | |
+ | |
+ flags = meta_kms_device_get_flags (gpu_kms->kms_device); | |
+ return !!(flags & META_KMS_DEVICE_FLAG_DISABLE_VRR); | |
+} | |
+ | |
static int | |
compare_outputs (gconstpointer one, | |
gconstpointer two) | |
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h | |
index e6f8b3e879c..77daba2e20c 100644 | |
--- a/src/backends/native/meta-gpu-kms.h | |
+++ b/src/backends/native/meta-gpu-kms.h | |
@@ -48,6 +48,7 @@ gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, | |
gboolean meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms); | |
gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms); | |
+gboolean meta_gpu_kms_disable_vrr (MetaGpuKms *gpu_kms); | |
MetaKmsDevice * meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms); | |
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h | |
index 5762babc7..ed605046d 100644 | |
--- a/src/backends/native/meta-kms-types.h | |
+++ b/src/backends/native/meta-kms-types.h | |
@@ -60,11 +60,12 @@ typedef enum _MetaKmsDeviceFlag | |
META_KMS_DEVICE_FLAG_BOOT_VGA = 1 << 0, | |
META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1, | |
META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS = 1 << 2, | |
- META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 3, | |
- META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 4, | |
- META_KMS_DEVICE_FLAG_HAS_ADDFB2 = 1 << 5, | |
- META_KMS_DEVICE_FLAG_FORCE_LEGACY = 1 << 6, | |
- META_KMS_DEVICE_FLAG_DISABLE_CLIENT_MODIFIERS = 1 << 7, | |
+ META_KMS_DEVICE_FLAG_DISABLE_VRR = 1 << 3, | |
+ META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 4, | |
+ META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 5, | |
+ META_KMS_DEVICE_FLAG_HAS_ADDFB2 = 1 << 6, | |
+ META_KMS_DEVICE_FLAG_FORCE_LEGACY = 1 << 7, | |
+ META_KMS_DEVICE_FLAG_DISABLE_CLIENT_MODIFIERS = 1 << 8, | |
} MetaKmsDeviceFlag; | |
typedef enum _MetaKmsResourceChanges | |
diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c | |
index 0a9ed5fd1ad..fa854ce0c4a 100644 | |
--- a/src/backends/native/meta-udev.c | |
+++ b/src/backends/native/meta-udev.c | |
@@ -102,6 +102,13 @@ meta_is_udev_device_disable_modifiers (GUdevDevice *device) | |
"mutter-device-disable-client-modifiers"); | |
} | |
+gboolean | |
+meta_is_udev_device_disable_vrr (GUdevDevice *device) | |
+{ | |
+ return meta_has_udev_device_tag (device, | |
+ "mutter-device-disable-vrr"); | |
+} | |
+ | |
gboolean | |
meta_is_udev_device_ignore (GUdevDevice *device) | |
{ | |
diff --git a/src/backends/native/meta-udev.h b/src/backends/native/meta-udev.h | |
index dfd6337a045..dee8430f652 100644 | |
--- a/src/backends/native/meta-udev.h | |
+++ b/src/backends/native/meta-udev.h | |
@@ -34,6 +34,8 @@ gboolean meta_is_udev_device_boot_vga (GUdevDevice *device); | |
gboolean meta_is_udev_device_disable_client_modifiers (GUdevDevice *device); | |
+gboolean meta_is_udev_device_disable_vrr (GUdevDevice *device); | |
+ | |
gboolean meta_is_udev_device_ignore (GUdevDevice *device); | |
gboolean meta_is_udev_test_device (GUdevDevice *device); | |
-- | |
GitLab | |
From 3b14352ee2f1f14760454a40d46d06fbb591645b Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Fri, 10 Jun 2022 19:45:47 +0300 | |
Subject: [PATCH 21/25] output/kms: Allow setting the VRR mode of an output | |
Add a function to check if an output is capable of VRR, a function to | |
check if VRR is configured to be allowed on the output and a function | |
to set the VRR mode on the CRTC of a given output. | |
An output is considered capable of variable refresh rate when its | |
connector supports it, but only if it isn't disabled for the GPU. | |
--- | |
src/backends/meta-monitor-manager-private.h | 1 + | |
src/backends/meta-output.c | 19 ++++++++++++++ | |
src/backends/meta-output.h | 7 +++++ | |
src/backends/native/meta-output-kms.c | 29 +++++++++++++++++++++ | |
src/backends/native/meta-output-kms.h | 3 +++ | |
5 files changed, 59 insertions(+) | |
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h | |
index edf7e450196..19a5e135922 100644 | |
--- a/src/backends/meta-monitor-manager-private.h | |
+++ b/src/backends/meta-monitor-manager-private.h | |
@@ -102,6 +102,7 @@ struct _MetaOutputAssignment | |
gboolean is_underscanning; | |
gboolean has_max_bpc; | |
unsigned int max_bpc; | |
+ gboolean is_vrr_allowed; | |
}; | |
/* | |
diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c | |
index ed480750724..4dca7981fb7 100644 | |
--- a/src/backends/meta-output.c | |
+++ b/src/backends/meta-output.c | |
@@ -55,6 +55,8 @@ typedef struct _MetaOutputPrivate | |
gboolean has_max_bpc; | |
unsigned int max_bpc; | |
+ gboolean is_vrr_allowed; | |
+ | |
int backlight; | |
} MetaOutputPrivate; | |
@@ -177,6 +179,22 @@ meta_output_is_underscanning (MetaOutput *output) | |
return priv->has_max_bpc; | |
} | |
+gboolean | |
+meta_output_is_vrr_capable (MetaOutput *output) | |
+{ | |
+ const MetaOutputInfo *output_info = meta_output_get_info (output); | |
+ | |
+ return output_info->vrr_capable; | |
+} | |
+ | |
+gboolean | |
+meta_output_is_vrr_allowed (MetaOutput *output) | |
+{ | |
+ MetaOutputPrivate *priv = meta_output_get_instance_private (output); | |
+ | |
+ return priv->is_vrr_allowed; | |
+} | |
+ | |
void | |
meta_output_set_backlight (MetaOutput *output, | |
int backlight) | |
@@ -235,6 +253,8 @@ meta_output_assign_crtc (MetaOutput *output, | |
priv->has_max_bpc = output_assignment->has_max_bpc; | |
if (priv->has_max_bpc) | |
priv->max_bpc = output_assignment->max_bpc; | |
+ | |
+ priv->is_vrr_allowed = output_assignment->is_vrr_allowed; | |
} | |
void | |
diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h | |
index 6c90d7e69e4..27b1e32a933 100644 | |
--- a/src/backends/meta-output.h | |
+++ b/src/backends/meta-output.h | |
@@ -103,6 +103,8 @@ typedef struct _MetaOutputInfo | |
unsigned int max_bpc_min; | |
unsigned int max_bpc_max; | |
+ gboolean vrr_capable; | |
+ | |
/* | |
* Get a new preferred mode on hotplug events, to handle dynamic guest | |
* resizing. | |
@@ -178,6 +180,11 @@ gboolean meta_output_is_presentation (MetaOutput *output); | |
gboolean meta_output_get_max_bpc (MetaOutput *output, | |
unsigned int *max_bpc); | |
+gboolean meta_output_is_vrr_capable (MetaOutput *output); | |
+ | |
+META_EXPORT_TEST | |
+gboolean meta_output_is_vrr_allowed (MetaOutput *output); | |
+ | |
void meta_output_set_backlight (MetaOutput *output, | |
int backlight); | |
diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c | |
index fb658f29d45..a6196f0af94 100644 | |
--- a/src/backends/native/meta-output-kms.c | |
+++ b/src/backends/native/meta-output-kms.c | |
@@ -97,6 +97,32 @@ meta_output_kms_set_max_bpc (MetaOutputKms *output_kms, | |
} | |
} | |
+void | |
+meta_output_kms_set_vrr_mode (MetaOutputKms *output_kms, | |
+ gboolean enabled) | |
+{ | |
+ MetaOutput *output = META_OUTPUT (output_kms); | |
+ const MetaOutputInfo *output_info = meta_output_get_info (output); | |
+ MetaCrtc *crtc; | |
+ MetaKmsCrtc *kms_crtc; | |
+ MetaKmsDevice *kms_device; | |
+ MetaKms *kms; | |
+ MetaKmsUpdate *kms_update; | |
+ | |
+ g_assert (output_info->vrr_capable); | |
+ | |
+ crtc = meta_output_get_assigned_crtc (output); | |
+ kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); | |
+ kms_device = meta_kms_crtc_get_device (kms_crtc); | |
+ kms = meta_kms_device_get_kms (kms_device); | |
+ | |
+ kms_update = meta_kms_ensure_pending_update (kms, kms_device); | |
+ | |
+ meta_kms_update_set_vrr_mode (kms_update, | |
+ kms_crtc, | |
+ enabled); | |
+} | |
+ | |
static MetaPrivacyScreenState | |
meta_output_kms_get_privacy_screen_state (MetaOutput *output) | |
{ | |
@@ -405,6 +431,9 @@ meta_output_kms_new (MetaGpuKms *gpu_kms, | |
output_info->max_bpc_max = max_bpc_range->max_value; | |
} | |
+ output_info->vrr_capable = (connector_state->vrr_capable && | |
+ !meta_gpu_kms_disable_vrr (gpu_kms)); | |
+ | |
if (connector_state->edid_data) | |
meta_output_info_parse_edid (output_info, connector_state->edid_data); | |
diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h | |
index 52acc6032a0..54b1721a420 100644 | |
--- a/src/backends/native/meta-output-kms.h | |
+++ b/src/backends/native/meta-output-kms.h | |
@@ -40,6 +40,9 @@ void meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms, | |
void meta_output_kms_set_max_bpc (MetaOutputKms *output_kms, | |
MetaKmsUpdate *kms_update); | |
+void meta_output_kms_set_vrr_mode (MetaOutputKms *output_kms, | |
+ gboolean enabled); | |
+ | |
gboolean meta_output_kms_can_clone (MetaOutputKms *output_kms, | |
MetaOutputKms *other_output_kms); | |
-- | |
GitLab | |
From 39692b449f69ff71c7ff746a28f5e1cd0f1eda2a Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 17 Mar 2020 20:57:41 +0200 | |
Subject: [PATCH 22/25] monitor: Allow checking the state of variable refresh | |
rate | |
A monitor is considered to have variable refresh rate support if its | |
main output supports it. | |
--- | |
src/backends/meta-monitor.c | 19 +++++++++++++++++++ | |
src/backends/meta-monitor.h | 4 ++++ | |
2 files changed, 23 insertions(+) | |
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c | |
index 46cb05a6661..4ccfadb7f7e 100644 | |
--- a/src/backends/meta-monitor.c | |
+++ b/src/backends/meta-monitor.c | |
@@ -358,6 +358,25 @@ meta_monitor_get_max_bpc (MetaMonitor *monitor, | |
return meta_output_get_max_bpc (output, max_bpc); | |
} | |
+gboolean | |
+meta_monitor_is_vrr_capable (MetaMonitor *monitor) | |
+{ | |
+ const MetaOutputInfo *output_info = | |
+ meta_monitor_get_main_output_info (monitor); | |
+ | |
+ return output_info->vrr_capable; | |
+} | |
+ | |
+gboolean | |
+meta_monitor_is_vrr_allowed (MetaMonitor *monitor) | |
+{ | |
+ MetaOutput *output; | |
+ | |
+ output = meta_monitor_get_main_output (monitor); | |
+ | |
+ return meta_output_is_vrr_allowed (output); | |
+} | |
+ | |
gboolean | |
meta_monitor_is_laptop_panel (MetaMonitor *monitor) | |
{ | |
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h | |
index 066caa7f469..aaf68ecca5e 100644 | |
--- a/src/backends/meta-monitor.h | |
+++ b/src/backends/meta-monitor.h | |
@@ -118,6 +118,10 @@ gboolean meta_monitor_supports_underscanning (MetaMonitor *monitor); | |
gboolean meta_monitor_get_max_bpc (MetaMonitor *monitor, | |
unsigned int *max_bpc); | |
+gboolean meta_monitor_is_vrr_capable (MetaMonitor *monitor); | |
+ | |
+gboolean meta_monitor_is_vrr_allowed (MetaMonitor *monitor); | |
+ | |
gboolean meta_monitor_is_laptop_panel (MetaMonitor *monitor); | |
gboolean meta_monitor_is_virtual (MetaMonitor *monitor); | |
-- | |
GitLab | |
From 80456db5cb251122592426590db222731f53c0e4 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Tue, 17 Mar 2020 20:52:16 +0200 | |
Subject: [PATCH 23/25] monitor-manager: Add variable refresh rate | |
configuration | |
This allows enabling variable refresh rate on monitors that support it. | |
The configuration is persistent via monitors.xml and exposed in | |
DisplayConfig to be managed through DBus. | |
--- | |
.../org.gnome.Mutter.DisplayConfig.xml | 7 + | |
src/backends/meta-monitor-config-manager.c | 9 +- | |
src/backends/meta-monitor-config-manager.h | 1 + | |
src/backends/meta-monitor-config-store.c | 30 +++ | |
src/backends/meta-monitor-manager.c | 27 ++- | |
src/tests/meta-monitor-test-utils.c | 4 + | |
src/tests/meta-monitor-test-utils.h | 2 + | |
src/tests/monitor-configs/vrr-allowed.xml | 23 +++ | |
src/tests/monitor-store-unit-tests.c | 51 +++++ | |
src/tests/monitor-unit-tests.c | 194 ++++++++++++++++++ | |
10 files changed, 344 insertions(+), 4 deletions(-) | |
create mode 100644 src/tests/monitor-configs/vrr-allowed.xml | |
diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml | |
index af78ec0517d..23ebb772034 100644 | |
--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml | |
+++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml | |
@@ -343,6 +343,10 @@ | |
- "is-underscanning" (b): whether underscanning is enabled | |
(absence of this means underscanning | |
not being supported) | |
+ - "is-vrr-allowed" (b): whether variable refresh rate is allowed | |
+ (absence of this means variable refresh | |
+ rate not being supported) | |
+ | |
- "max-screen-size" (ii): the maximum size a screen may have | |
(absence of this means unlimited screen | |
size) | |
@@ -461,6 +465,9 @@ | |
- "enable_underscanning" (b): enable monitor underscanning; | |
may only be set when underscanning | |
is supported (see GetCurrentState). | |
+ - "allow_vrr" (b): allow variable refresh rate; may only be set | |
+ when variable refresh rate is supported (see | |
+ GetCurrentState). | |
@properties may effect the global monitor configuration state. Possible | |
properties are: | |
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c | |
index da3f1dd5442..95fd3ad6c84 100644 | |
--- a/src/backends/meta-monitor-config-manager.c | |
+++ b/src/backends/meta-monitor-config-manager.c | |
@@ -286,7 +286,8 @@ assign_monitor_crtc (MetaMonitor *monitor, | |
.is_presentation = assign_output_as_presentation, | |
.is_underscanning = data->monitor_config->enable_underscanning, | |
.has_max_bpc = data->monitor_config->has_max_bpc, | |
- .max_bpc = data->monitor_config->max_bpc | |
+ .max_bpc = data->monitor_config->max_bpc, | |
+ .is_vrr_allowed = data->monitor_config->allow_vrr, | |
}; | |
g_ptr_array_add (data->crtc_assignments, crtc_assignment); | |
@@ -691,7 +692,8 @@ create_monitor_config (MetaMonitor *monitor, | |
*monitor_config = (MetaMonitorConfig) { | |
.monitor_spec = meta_monitor_spec_clone (monitor_spec), | |
.mode_spec = g_memdup2 (mode_spec, sizeof (MetaMonitorModeSpec)), | |
- .enable_underscanning = meta_monitor_is_underscanning (monitor) | |
+ .enable_underscanning = meta_monitor_is_underscanning (monitor), | |
+ .allow_vrr = meta_monitor_is_vrr_allowed (monitor), | |
}; | |
monitor_config->has_max_bpc = | |
@@ -953,7 +955,8 @@ clone_monitor_config_list (GList *monitor_configs_in) | |
sizeof (MetaMonitorModeSpec)), | |
.enable_underscanning = monitor_config_in->enable_underscanning, | |
.has_max_bpc = monitor_config_in->has_max_bpc, | |
- .max_bpc = monitor_config_in->max_bpc | |
+ .max_bpc = monitor_config_in->max_bpc, | |
+ .allow_vrr = monitor_config_in->allow_vrr, | |
}; | |
monitor_configs_out = | |
g_list_append (monitor_configs_out, monitor_config_out); | |
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h | |
index a789e2f0882..fdf2db3a7dd 100644 | |
--- a/src/backends/meta-monitor-config-manager.h | |
+++ b/src/backends/meta-monitor-config-manager.h | |
@@ -34,6 +34,7 @@ typedef struct _MetaMonitorConfig | |
gboolean enable_underscanning; | |
gboolean has_max_bpc; | |
unsigned int max_bpc; | |
+ gboolean allow_vrr; | |
} MetaMonitorConfig; | |
typedef struct _MetaLogicalMonitorConfig | |
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c | |
index 5d48ec2ea5c..bb8c73c7f95 100644 | |
--- a/src/backends/meta-monitor-config-store.c | |
+++ b/src/backends/meta-monitor-config-store.c | |
@@ -167,6 +167,7 @@ typedef enum | |
STATE_MONITOR_MODE_FLAG, | |
STATE_MONITOR_UNDERSCANNING, | |
STATE_MONITOR_MAXBPC, | |
+ STATE_MONITOR_VRR_ALLOWED, | |
STATE_DISABLED, | |
STATE_POLICY, | |
STATE_STORES, | |
@@ -451,6 +452,10 @@ handle_start_element (GMarkupParseContext *context, | |
{ | |
parser->state = STATE_MONITOR_MAXBPC; | |
} | |
+ else if (g_str_equal (element_name, "vrr-allowed")) | |
+ { | |
+ parser->state = STATE_MONITOR_VRR_ALLOWED; | |
+ } | |
else | |
{ | |
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, | |
@@ -544,6 +549,13 @@ handle_start_element (GMarkupParseContext *context, | |
return; | |
} | |
+ case STATE_MONITOR_VRR_ALLOWED: | |
+ { | |
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, | |
+ "Invalid element '%s' under vrr-allowed", element_name); | |
+ return; | |
+ } | |
+ | |
case STATE_DISABLED: | |
{ | |
if (!g_str_equal (element_name, "monitorspec")) | |
@@ -818,6 +830,14 @@ handle_end_element (GMarkupParseContext *context, | |
return; | |
} | |
+ case STATE_MONITOR_VRR_ALLOWED: | |
+ { | |
+ g_assert (g_str_equal (element_name, "vrr-allowed")); | |
+ | |
+ parser->state = STATE_MONITOR; | |
+ return; | |
+ } | |
+ | |
case STATE_MONITOR: | |
{ | |
MetaLogicalMonitorConfig *logical_monitor_config; | |
@@ -1301,6 +1321,14 @@ handle_text (GMarkupParseContext *context, | |
return; | |
} | |
+ case STATE_MONITOR_VRR_ALLOWED: | |
+ { | |
+ read_bool (text, text_len, | |
+ &parser->current_monitor_config->allow_vrr, | |
+ error); | |
+ return; | |
+ } | |
+ | |
case STATE_STORE: | |
{ | |
MetaConfigStore store; | |
@@ -1476,6 +1504,8 @@ append_monitors (GString *buffer, | |
g_string_append (buffer, " </mode>\n"); | |
if (monitor_config->enable_underscanning) | |
g_string_append (buffer, " <underscanning>yes</underscanning>\n"); | |
+ if (monitor_config->allow_vrr) | |
+ g_string_append (buffer, " <vrr-allowed>yes</vrr-allowed>\n"); | |
if (monitor_config->has_max_bpc) | |
{ | |
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c | |
index 6d9b7f416b1..3e1d200dad4 100644 | |
--- a/src/backends/meta-monitor-manager.c | |
+++ b/src/backends/meta-monitor-manager.c | |
@@ -2034,6 +2034,15 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, | |
g_variant_new_boolean (is_underscanning)); | |
} | |
+ if (meta_monitor_is_vrr_capable (monitor)) | |
+ { | |
+ gboolean vrr_allowed = meta_monitor_is_vrr_allowed (monitor); | |
+ | |
+ g_variant_builder_add (&monitor_properties_builder, "{sv}", | |
+ "is-vrr-allowed", | |
+ g_variant_new_boolean (vrr_allowed)); | |
+ } | |
+ | |
is_builtin = meta_monitor_is_laptop_panel (monitor); | |
g_variant_builder_add (&monitor_properties_builder, "{sv}", | |
"is-builtin", | |
@@ -2353,6 +2362,8 @@ create_monitor_config_from_variant (MetaMonitorManager *manager, | |
g_autoptr (GVariant) properties_variant = NULL; | |
gboolean enable_underscanning = FALSE; | |
gboolean set_underscanning = FALSE; | |
+ gboolean allow_vrr = FALSE; | |
+ gboolean set_allow_vrr = FALSE; | |
g_variant_get (monitor_config_variant, "(ss@a{sv})", | |
&connector, | |
@@ -2388,6 +2399,19 @@ create_monitor_config_from_variant (MetaMonitorManager *manager, | |
} | |
} | |
+ set_allow_vrr = | |
+ g_variant_lookup (properties_variant, "allow_vrr", "b", | |
+ &allow_vrr); | |
+ if (set_allow_vrr) | |
+ { | |
+ if (allow_vrr && !meta_monitor_is_vrr_capable (monitor)) | |
+ { | |
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | |
+ "Variable refresh rate requested but unsupported"); | |
+ return NULL; | |
+ } | |
+ } | |
+ | |
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); | |
monitor_mode_spec = g_new0 (MetaMonitorModeSpec, 1); | |
@@ -2397,7 +2421,8 @@ create_monitor_config_from_variant (MetaMonitorManager *manager, | |
*monitor_config = (MetaMonitorConfig) { | |
.monitor_spec = monitor_spec, | |
.mode_spec = monitor_mode_spec, | |
- .enable_underscanning = enable_underscanning | |
+ .enable_underscanning = enable_underscanning, | |
+ .allow_vrr = allow_vrr, | |
}; | |
return monitor_config; | |
diff --git a/src/tests/meta-monitor-test-utils.c b/src/tests/meta-monitor-test-utils.c | |
index aab9e18589b..e74504750e4 100644 | |
--- a/src/tests/meta-monitor-test-utils.c | |
+++ b/src/tests/meta-monitor-test-utils.c | |
@@ -392,6 +392,10 @@ meta_check_monitor_configuration (MetaContext *context, | |
output_max_bpc = 0; | |
g_assert_cmpint (expect->monitors[i].max_bpc, ==, output_max_bpc); | |
+ | |
+ g_assert_cmpint (expect->monitors[i].is_vrr_allowed, | |
+ ==, | |
+ meta_output_is_vrr_allowed (output)); | |
} | |
meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm); | |
@@ -778,6 +781,7 @@ meta_create_monitor_test_setup (MetaBackend *backend, | |
.is_underscanning = setup->outputs[i].is_underscanning, | |
.has_max_bpc = !!setup->outputs[i].max_bpc, | |
.max_bpc = setup->outputs[i].max_bpc, | |
+ .is_vrr_allowed = setup->outputs[i].is_vrr_allowed, | |
}; | |
meta_output_assign_crtc (output, crtc, &output_assignment); | |
} | |
diff --git a/src/tests/meta-monitor-test-utils.h b/src/tests/meta-monitor-test-utils.h | |
index 988a4115e89..8d3c6cedaa5 100644 | |
--- a/src/tests/meta-monitor-test-utils.h | |
+++ b/src/tests/meta-monitor-test-utils.h | |
@@ -106,6 +106,7 @@ typedef struct _MonitorTestCaseOutput | |
gboolean is_laptop_panel; | |
gboolean is_underscanning; | |
unsigned int max_bpc; | |
+ gboolean is_vrr_allowed; | |
const char *serial; | |
MetaMonitorTransform panel_orientation_transform; | |
gboolean hotplug_mode; | |
@@ -157,6 +158,7 @@ typedef struct _MonitorTestCaseMonitor | |
int height_mm; | |
gboolean is_underscanning; | |
unsigned int max_bpc; | |
+ gboolean is_vrr_allowed; | |
} MonitorTestCaseMonitor; | |
typedef struct _MonitorTestCaseLogicalMonitor | |
diff --git a/src/tests/monitor-configs/vrr-allowed.xml b/src/tests/monitor-configs/vrr-allowed.xml | |
new file mode 100644 | |
index 00000000000..36846e0b2f8 | |
--- /dev/null | |
+++ b/src/tests/monitor-configs/vrr-allowed.xml | |
@@ -0,0 +1,23 @@ | |
+<monitors version="2"> | |
+ <configuration> | |
+ <logicalmonitor> | |
+ <x>0</x> | |
+ <y>0</y> | |
+ <primary>yes</primary> | |
+ <monitor> | |
+ <monitorspec> | |
+ <connector>DP-1</connector> | |
+ <vendor>MetaProduct's Inc.</vendor> | |
+ <product>MetaMonitor</product> | |
+ <serial>0x123456</serial> | |
+ </monitorspec> | |
+ <mode> | |
+ <width>1024</width> | |
+ <height>768</height> | |
+ <rate>60.000495910644531</rate> | |
+ </mode> | |
+ <vrr-allowed>yes</vrr-allowed> | |
+ </monitor> | |
+ </logicalmonitor> | |
+ </configuration> | |
+</monitors> | |
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c | |
index 38f4bc52fc3..6e85c9a3d32 100644 | |
--- a/src/tests/monitor-store-unit-tests.c | |
+++ b/src/tests/monitor-store-unit-tests.c | |
@@ -48,6 +48,7 @@ typedef struct _MonitorStoreTestCaseMonitor | |
MonitorStoreTestCaseMonitorMode mode; | |
gboolean is_underscanning; | |
unsigned int max_bpc; | |
+ gboolean is_vrr_allowed; | |
} MonitorStoreTestCaseMonitor; | |
typedef struct _MonitorStoreTestCaseLogicalMonitor | |
@@ -196,6 +197,9 @@ check_monitor_store_configuration (MetaMonitorConfigStore *config_store, | |
g_assert_cmpint (monitor_config->max_bpc, | |
==, | |
test_monitor->max_bpc); | |
+ g_assert_cmpint (monitor_config->allow_vrr, | |
+ ==, | |
+ test_monitor->is_vrr_allowed); | |
} | |
} | |
} | |
@@ -446,6 +450,51 @@ meta_test_monitor_store_underscanning (void) | |
check_monitor_store_configurations (&expect); | |
} | |
+static void | |
+meta_test_monitor_store_vrr_allowed (void) | |
+{ | |
+ MonitorStoreTestExpect expect = { | |
+ .configurations = { | |
+ { | |
+ .logical_monitors = { | |
+ { | |
+ .layout = { | |
+ .x = 0, | |
+ .y = 0, | |
+ .width = 1024, | |
+ .height = 768 | |
+ }, | |
+ .scale = 1, | |
+ .is_primary = TRUE, | |
+ .is_presentation = FALSE, | |
+ .monitors = { | |
+ { | |
+ .connector = "DP-1", | |
+ .vendor = "MetaProduct's Inc.", | |
+ .product = "MetaMonitor", | |
+ .serial = "0x123456", | |
+ .is_vrr_allowed = TRUE, | |
+ .mode = { | |
+ .width = 1024, | |
+ .height = 768, | |
+ .refresh_rate = 60.000495910644531 | |
+ } | |
+ } | |
+ }, | |
+ .n_monitors = 1, | |
+ }, | |
+ }, | |
+ .n_logical_monitors = 1 | |
+ } | |
+ }, | |
+ .n_configurations = 1 | |
+ }; | |
+ | |
+ meta_set_custom_monitor_config (test_context, "vrr-allowed.xml"); | |
+ | |
+ check_monitor_store_configurations (&expect); | |
+} | |
+ | |
static void | |
meta_test_monitor_store_scale (void) | |
{ | |
@@ -1013,6 +1062,8 @@ init_monitor_store_tests (void) | |
meta_test_monitor_store_underscanning); | |
g_test_add_func ("/backends/monitor-store/max-bpc", | |
meta_test_monitor_store_max_bpc); | |
+ g_test_add_func ("/backends/monitor-store/vrr-allowed", | |
+ meta_test_monitor_store_vrr_allowed); | |
g_test_add_func ("/backends/monitor-store/scale", | |
meta_test_monitor_store_scale); | |
g_test_add_func ("/backends/monitor-store/fractional-scale", | |
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c | |
index 6a807c60e38..4c4cdefbb3c 100644 | |
--- a/src/tests/monitor-unit-tests.c | |
+++ b/src/tests/monitor-unit-tests.c | |
@@ -3276,6 +3276,100 @@ meta_test_monitor_max_bpc_config (void) | |
check_monitor_test_clients_state (); | |
} | |
+static void | |
+meta_test_monitor_vrr_allowed_config (void) | |
+{ | |
+ MonitorTestCase test_case = { | |
+ .setup = { | |
+ .modes = { | |
+ { | |
+ .width = 1024, | |
+ .height = 768, | |
+ .refresh_rate = 60.0 | |
+ } | |
+ }, | |
+ .n_modes = 1, | |
+ .outputs = { | |
+ { | |
+ .crtc = 0, | |
+ .modes = { 0 }, | |
+ .n_modes = 1, | |
+ .preferred_mode = 0, | |
+ .possible_crtcs = { 0 }, | |
+ .n_possible_crtcs = 1, | |
+ .width_mm = 222, | |
+ .height_mm = 125, | |
+ .is_vrr_allowed = TRUE, | |
+ } | |
+ }, | |
+ .n_outputs = 1, | |
+ .crtcs = { | |
+ { | |
+ .current_mode = 0 | |
+ } | |
+ }, | |
+ .n_crtcs = 1 | |
+ }, | |
+ | |
+ .expect = { | |
+ .monitors = { | |
+ { | |
+ .outputs = { 0 }, | |
+ .n_outputs = 1, | |
+ .modes = { | |
+ { | |
+ .width = 1024, | |
+ .height = 768, | |
+ .refresh_rate = 60.0, | |
+ .crtc_modes = { | |
+ { | |
+ .output = 0, | |
+ .crtc_mode = 0 | |
+ } | |
+ } | |
+ } | |
+ }, | |
+ .n_modes = 1, | |
+ .current_mode = 0, | |
+ .width_mm = 222, | |
+ .height_mm = 125, | |
+ .is_vrr_allowed = TRUE, | |
+ } | |
+ }, | |
+ .n_monitors = 1, | |
+ .logical_monitors = { | |
+ { | |
+ .monitors = { 0 }, | |
+ .n_monitors = 1, | |
+ .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, | |
+ .scale = 1 | |
+ } | |
+ }, | |
+ .n_logical_monitors = 1, | |
+ .primary_logical_monitor = 0, | |
+ .n_outputs = 1, | |
+ .crtcs = { | |
+ { | |
+ .current_mode = 0, | |
+ } | |
+ }, | |
+ .n_crtcs = 1, | |
+ .screen_width = 1024, | |
+ .screen_height = 768 | |
+ } | |
+ }; | |
+ MetaMonitorTestSetup *test_setup; | |
+ | |
+ test_setup = meta_create_monitor_test_setup (test_backend, | |
+ &test_case.setup, | |
+ MONITOR_TEST_FLAG_NO_STORED); | |
+ emulate_hotplug (test_setup); | |
+ META_TEST_LOG_CALL ("Checking monitor configuration", | |
+ meta_check_monitor_configuration (test_context, | |
+ &test_case.expect)); | |
+ check_monitor_test_clients_state (); | |
+} | |
+ | |
static void | |
meta_test_monitor_preferred_non_first_mode (void) | |
{ | |
@@ -5522,6 +5616,102 @@ meta_test_monitor_custom_underscanning_config (void) | |
check_monitor_test_clients_state (); | |
} | |
+static void | |
+meta_test_monitor_custom_vrr_allowed_config (void) | |
+{ | |
+ MonitorTestCase test_case = { | |
+ .setup = { | |
+ .modes = { | |
+ { | |
+ .width = 1024, | |
+ .height = 768, | |
+ .refresh_rate = 60.000495910644531 | |
+ } | |
+ }, | |
+ .n_modes = 1, | |
+ .outputs = { | |
+ { | |
+ .crtc = 0, | |
+ .modes = { 0 }, | |
+ .n_modes = 1, | |
+ .preferred_mode = 0, | |
+ .possible_crtcs = { 0 }, | |
+ .n_possible_crtcs = 1, | |
+ .width_mm = 222, | |
+ .height_mm = 125 | |
+ }, | |
+ }, | |
+ .n_outputs = 1, | |
+ .crtcs = { | |
+ { | |
+ .current_mode = 0 | |
+ }, | |
+ }, | |
+ .n_crtcs = 1 | |
+ }, | |
+ | |
+ .expect = { | |
+ .monitors = { | |
+ { | |
+ .outputs = { 0 }, | |
+ .n_outputs = 1, | |
+ .modes = { | |
+ { | |
+ .width = 1024, | |
+ .height = 768, | |
+ .refresh_rate = 60.000495910644531, | |
+ .crtc_modes = { | |
+ { | |
+ .output = 0, | |
+ .crtc_mode = 0 | |
+ } | |
+ } | |
+ } | |
+ }, | |
+ .n_modes = 1, | |
+ .current_mode = 0, | |
+ .width_mm = 222, | |
+ .height_mm = 125, | |
+ .is_vrr_allowed = TRUE, | |
+ } | |
+ }, | |
+ .n_monitors = 1, | |
+ .logical_monitors = { | |
+ { | |
+ .monitors = { 0 }, | |
+ .n_monitors = 1, | |
+ .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, | |
+ .scale = 1 | |
+ } | |
+ }, | |
+ .n_logical_monitors = 1, | |
+ .primary_logical_monitor = 0, | |
+ .n_outputs = 1, | |
+ .crtcs = { | |
+ { | |
+ .current_mode = 0, | |
+ } | |
+ }, | |
+ .n_crtcs = 1, | |
+ .n_tiled_monitors = 0, | |
+ .screen_width = 1024, | |
+ .screen_height = 768 | |
+ } | |
+ }; | |
+ MetaMonitorTestSetup *test_setup; | |
+ | |
+ test_setup = meta_create_monitor_test_setup (test_backend, | |
+ &test_case.setup, | |
+ MONITOR_TEST_FLAG_NONE); | |
+ meta_set_custom_monitor_config (test_context, "vrr-allowed.xml"); | |
+ emulate_hotplug (test_setup); | |
+ | |
+ META_TEST_LOG_CALL ("Checking monitor configuration", | |
+ meta_check_monitor_configuration (test_context, | |
+ &test_case.expect)); | |
+ check_monitor_test_clients_state (); | |
+} | |
+ | |
static void | |
meta_test_monitor_custom_scale_config (void) | |
{ | |
@@ -9118,6 +9308,8 @@ init_monitor_tests (void) | |
meta_test_monitor_underscanning_config); | |
add_monitor_test ("/backends/monitor/max-bpc-config", | |
meta_test_monitor_max_bpc_config); | |
+ add_monitor_test ("/backends/monitor/vrr-allowed-config", | |
+ meta_test_monitor_vrr_allowed_config); | |
add_monitor_test ("/backends/monitor/preferred-non-first-mode", | |
meta_test_monitor_preferred_non_first_mode); | |
add_monitor_test ("/backends/monitor/non-upright-panel", | |
@@ -9148,6 +9340,8 @@ init_monitor_tests (void) | |
meta_test_monitor_custom_primary_config); | |
add_monitor_test ("/backends/monitor/custom/underscanning-config", | |
meta_test_monitor_custom_underscanning_config); | |
+ add_monitor_test ("/backends/monitor/custom/vrr-allowed-config", | |
+ meta_test_monitor_custom_vrr_allowed_config); | |
add_monitor_test ("/backends/monitor/custom/scale-config", | |
meta_test_monitor_custom_scale_config); | |
add_monitor_test ("/backends/monitor/custom/fractional-scale-config", | |
-- | |
GitLab | |
From 3a760033d996c708e25784601c89a37779f77b11 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Sat, 4 Jul 2020 01:03:19 +0300 | |
Subject: [PATCH 24/25] renderer-view: Keep track of the associated MetaOutput | |
It will be used in a following commit to perform operations in the | |
context of a MetaOutput from the MetaRendererViewNative. | |
--- | |
src/backends/meta-renderer-view.c | 27 +++++++++++++++++++ | |
src/backends/meta-renderer-view.h | 2 ++ | |
src/backends/native/meta-renderer-native.c | 1 + | |
.../x11/nested/meta-renderer-x11-nested.c | 1 + | |
4 files changed, 31 insertions(+) | |
diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c | |
index c16ba351c91..348ce0fb8ce 100644 | |
--- a/src/backends/meta-renderer-view.c | |
+++ b/src/backends/meta-renderer-view.c | |
@@ -33,6 +33,7 @@ | |
#include "backends/meta-renderer-view.h" | |
#include "backends/meta-crtc.h" | |
+#include "backends/meta-output.h" | |
#include "backends/meta-renderer.h" | |
#include "clutter/clutter-mutter.h" | |
#include "compositor/region-utils.h" | |
@@ -43,6 +44,7 @@ enum | |
PROP_TRANSFORM, | |
PROP_CRTC, | |
+ PROP_OUTPUT, | |
PROP_LAST | |
}; | |
@@ -54,6 +56,7 @@ typedef struct _MetaRendererViewPrivate | |
MetaMonitorTransform transform; | |
MetaCrtc *crtc; | |
+ MetaOutput *output; | |
} MetaRendererViewPrivate; | |
G_DEFINE_TYPE_WITH_PRIVATE (MetaRendererView, meta_renderer_view, | |
@@ -77,6 +80,15 @@ meta_renderer_view_get_crtc (MetaRendererView *view) | |
return priv->crtc; | |
} | |
+MetaOutput * | |
+meta_renderer_view_get_output (MetaRendererView *view) | |
+{ | |
+ MetaRendererViewPrivate *priv = | |
+ meta_renderer_view_get_instance_private (view); | |
+ | |
+ return priv->output; | |
+} | |
+ | |
static void | |
meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view, | |
graphene_matrix_t *matrix) | |
@@ -187,6 +199,9 @@ meta_renderer_view_get_property (GObject *object, | |
case PROP_CRTC: | |
g_value_set_object (value, priv->crtc); | |
break; | |
+ case PROP_OUTPUT: | |
+ g_value_set_object (value, priv->output); | |
+ break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
@@ -211,6 +226,9 @@ meta_renderer_view_set_property (GObject *object, | |
case PROP_CRTC: | |
priv->crtc = g_value_get_object (value); | |
break; | |
+ case PROP_OUTPUT: | |
+ priv->output = g_value_get_object (value); | |
+ break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
@@ -258,5 +276,14 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass) | |
G_PARAM_CONSTRUCT_ONLY | | |
G_PARAM_STATIC_STRINGS); | |
+ obj_props[PROP_OUTPUT] = | |
+ g_param_spec_object ("output", | |
+ "MetaOutput", | |
+ "MetaOutput", | |
+ META_TYPE_OUTPUT, | |
+ G_PARAM_READWRITE | | |
+ G_PARAM_CONSTRUCT_ONLY | | |
+ G_PARAM_STATIC_STRINGS); | |
+ | |
g_object_class_install_properties (object_class, PROP_LAST, obj_props); | |
} | |
diff --git a/src/backends/meta-renderer-view.h b/src/backends/meta-renderer-view.h | |
index b6247f38c1c..355e75e9643 100644 | |
--- a/src/backends/meta-renderer-view.h | |
+++ b/src/backends/meta-renderer-view.h | |
@@ -36,4 +36,6 @@ MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view); | |
MetaCrtc *meta_renderer_view_get_crtc (MetaRendererView *view); | |
+MetaOutput *meta_renderer_view_get_output (MetaRendererView *view); | |
+ | |
#endif /* META_RENDERER_VIEW_H */ | |
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c | |
index a45b2080604..d1b0df07cea 100644 | |
--- a/src/backends/native/meta-renderer-native.c | |
+++ b/src/backends/native/meta-renderer-native.c | |
@@ -1358,6 +1358,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, | |
"stage", meta_backend_get_stage (backend), | |
"layout", &view_layout, | |
"crtc", crtc, | |
+ "output", output, | |
"scale", scale, | |
"framebuffer", framebuffer, | |
"offscreen", offscreen, | |
diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c | |
index 7c1a4facfdb..2f9eca5ba36 100644 | |
--- a/src/backends/x11/nested/meta-renderer-x11-nested.c | |
+++ b/src/backends/x11/nested/meta-renderer-x11-nested.c | |
@@ -223,6 +223,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer, | |
"stage", meta_backend_get_stage (backend), | |
"layout", &view_layout, | |
"crtc", crtc, | |
+ "output", output, | |
"refresh-rate", mode_info->refresh_rate, | |
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen), | |
"offscreen", COGL_FRAMEBUFFER (offscreen), | |
-- | |
GitLab | |
From 74efe59b5a35fdfb59ebcdadff49184bf82a3833 Mon Sep 17 00:00:00 2001 | |
From: Dor Askayo <dor.askayo@gmail.com> | |
Date: Fri, 10 Jun 2022 21:12:49 +0300 | |
Subject: [PATCH 25/25] renderer-view/native: Enable VRR and actor sync when | |
applicable | |
If an actor is tracked for synchronization and VRR is configured to | |
be enabled for the output, set the synchronization mode to | |
META_FRAME_SYNC_MODE_ENABLED. | |
If an actor isn't tracked for synchronization or VRR is not configured | |
to be enabled for the output, set the synchronization mode to | |
META_FRAME_SYNC_MODE_DISABLED. | |
When the synchronization mode is set to META_FRAME_SYNC_MODE_ENABLED, | |
enable the VRR mode on the output, and when it's set to | |
META_FRAME_SYNC_MODE_DISABLED, disable it. | |
Synchronizing frame clock updates with actor updates on the stage view | |
effectively communicates the rate at which the actor updates with the | |
DRM driver. Combined with enabling VRR on the CRTC, it allows the DRM | |
driver to adjust the monitor's refresh rate to the rate at which the | |
actor updates. | |
--- | |
.../native/meta-renderer-view-native.c | 27 ++++++++++++++++++- | |
1 file changed, 26 insertions(+), 1 deletion(-) | |
diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c | |
index c2b38e980b8..d3abcd0212c 100644 | |
--- a/src/backends/native/meta-renderer-view-native.c | |
+++ b/src/backends/native/meta-renderer-view-native.c | |
@@ -24,6 +24,11 @@ | |
#include "backends/native/meta-renderer-view-native.h" | |
+#include "backends/meta-output.h" | |
+#include "backends/native/meta-crtc-kms.h" | |
+#include "backends/native/meta-kms.h" | |
+#include "backends/native/meta-kms-device.h" | |
+#include "backends/native/meta-output-kms.h" | |
#include "clutter/clutter.h" | |
typedef enum _MetaFrameSyncMode | |
@@ -112,20 +117,24 @@ meta_renderer_view_native_set_frame_sync_actor (MetaRendererViewNative *view_nat | |
static void | |
meta_renderer_view_native_set_frame_sync (MetaRendererViewNative *view_native, | |
+ MetaOutput *output, | |
MetaFrameSyncMode sync_mode) | |
{ | |
ClutterFrameClock *frame_clock = | |
clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (view_native)); | |
+ MetaOutputKms *output_kms = META_OUTPUT_KMS (output); | |
switch (sync_mode) | |
{ | |
case META_FRAME_SYNC_MODE_ENABLED: | |
clutter_frame_clock_set_mode (frame_clock, | |
CLUTTER_FRAME_CLOCK_MODE_VARIABLE); | |
+ meta_output_kms_set_vrr_mode (output_kms, TRUE); | |
break; | |
case META_FRAME_SYNC_MODE_DISABLED: | |
clutter_frame_clock_set_mode (frame_clock, | |
CLUTTER_FRAME_CLOCK_MODE_FIXED); | |
+ meta_output_kms_set_vrr_mode (output_kms, FALSE); | |
break; | |
case META_FRAME_SYNC_MODE_INIT: | |
g_assert_not_reached (); | |
@@ -137,12 +146,21 @@ meta_renderer_view_native_set_frame_sync (MetaRendererViewNative *view_native, | |
static MetaFrameSyncMode | |
meta_renderer_view_native_get_applicable_sync_mode (MetaRendererViewNative *view_native) | |
{ | |
- return META_FRAME_SYNC_MODE_DISABLED; | |
+ MetaRendererView *view = META_RENDERER_VIEW (view_native); | |
+ MetaOutput *output = meta_renderer_view_get_output (view); | |
+ | |
+ if (view_native->frame_sync_actor != NULL && | |
+ meta_output_is_vrr_allowed (output)) | |
+ return META_FRAME_SYNC_MODE_ENABLED; | |
+ else | |
+ return META_FRAME_SYNC_MODE_DISABLED; | |
} | |
void | |
meta_renderer_view_native_maybe_set_frame_sync (MetaRendererViewNative *view_native) | |
{ | |
+ MetaRendererView *view; | |
+ MetaOutput *output; | |
MetaFrameSyncMode applicable_sync_mode; | |
if (G_LIKELY (!view_native->frame_sync_mode_update_queued)) | |
@@ -150,12 +168,19 @@ meta_renderer_view_native_maybe_set_frame_sync (MetaRendererViewNative *view_nat | |
view_native->frame_sync_mode_update_queued = FALSE; | |
+ view = META_RENDERER_VIEW (view_native); | |
+ output = meta_renderer_view_get_output (view); | |
+ | |
+ if (!meta_output_is_vrr_capable (output)) | |
+ return; | |
+ | |
applicable_sync_mode = | |
meta_renderer_view_native_get_applicable_sync_mode (view_native); | |
if (applicable_sync_mode != view_native->frame_sync_mode) | |
{ | |
meta_renderer_view_native_set_frame_sync (view_native, | |
+ output, | |
applicable_sync_mode); | |
} | |
} | |
-- | |
GitLab | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment