1From cf89234a530bd85e575b7386b30f1425e2305411 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Fri, 25 Feb 2022 17:48:58 +0800
4Subject: [PATCH 30/33] kmssink: Support setting prefered frame syncing mode
5
6Tested with:
7gst-launch-1.0 videotestsrc ! kmssink sync-mode=vblank
8gst-launch-1.0 videotestsrc ! kmssink sync-mode=none
9
10Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
11---
12 sys/kms/gstkmssink.c | 62 +++++++++++++++++++++++++++++++++++++++-----
13 sys/kms/gstkmssink.h | 10 +++++++
14 2 files changed, 66 insertions(+), 6 deletions(-)
15
16diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
17index af80c8e..bfca332 100644
18--- a/sys/kms/gstkmssink.c
19+++ b/sys/kms/gstkmssink.c
20@@ -99,11 +99,14 @@ enum
21   PROP_CONNECTOR_PROPS,
22   PROP_PLANE_PROPS,
23   PROP_FORCE_ASPECT_RATIO,
24+  PROP_SYNC_MODE,
25   PROP_N,
26 };
27
28 static GParamSpec *g_properties[PROP_N] = { NULL, };
29
30+static GstKMSSyncMode DEFAULT_SYNC_MODE = GST_KMS_SYNC_AUTO;
31+
32 static void
33 gst_kms_sink_set_render_rectangle (GstVideoOverlay * overlay,
34     gint x, gint y, gint width, gint height)
35@@ -1491,7 +1494,7 @@ static gboolean
36 gst_kms_sink_sync (GstKMSSink * self)
37 {
38   gint ret;
39-  gboolean waiting;
40+  gboolean waiting, pageflip;
41   drmEventContext evctxt = {
42     .version = DRM_EVENT_CONTEXT_VERSION,
43     .page_flip_handler = sync_handler,
44@@ -1510,8 +1513,18 @@ gst_kms_sink_sync (GstKMSSink * self)
45   else if (self->pipe > 1)
46     vbl.request.type |= self->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
47
48+  if (self->sync_mode == GST_KMS_SYNC_FLIP) {
49+    pageflip = TRUE;
50+  } else if (self->sync_mode == GST_KMS_SYNC_VBLANK) {
51+    pageflip = FALSE;
52+  } else if (self->sync_mode == GST_KMS_SYNC_AUTO) {
53+    pageflip = self->modesetting_enabled;
54+  } else {
55+    return TRUE;
56+  }
57+
58   waiting = TRUE;
59-  if (!self->has_async_page_flip && !self->modesetting_enabled) {
60+  if (!pageflip) {
61     ret = drmWaitVBlank (self->fd, &vbl);
62     if (ret)
63       goto vblank_failed;
64@@ -1916,10 +1929,12 @@ retry_set_plane:
65   }
66
67 sync_frame:
68-  /* Wait for the previous frame to complete redraw */
69-  if (!gst_kms_sink_sync (self)) {
70-    GST_OBJECT_UNLOCK (self);
71-    goto bail;
72+  if (self->sync_mode != GST_KMS_SYNC_NONE) {
73+    /* Wait for the previous frame to complete redraw */
74+    if (!gst_kms_sink_sync (self)) {
75+      GST_OBJECT_UNLOCK (self);
76+      goto bail;
77+    }
78   }
79
80   /* Save the rendered buffer and its metadata in case a redraw is needed */
81@@ -2074,6 +2089,9 @@ gst_kms_sink_set_property (GObject * object, guint prop_id,
82     case PROP_FORCE_ASPECT_RATIO:
83       sink->keep_aspect = g_value_get_boolean (value);
84       break;
85+    case PROP_SYNC_MODE:
86+      sink->sync_mode = g_value_get_enum (value);
87+      break;
88     default:
89       if (!gst_video_overlay_set_property (object, PROP_N, prop_id, value))
90         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91@@ -2130,6 +2148,9 @@ gst_kms_sink_get_property (GObject * object, guint prop_id,
92     case PROP_FORCE_ASPECT_RATIO:
93       g_value_set_boolean (value, sink->keep_aspect);
94       break;
95+    case PROP_SYNC_MODE:
96+      g_value_set_enum (value, sink->sync_mode);
97+      break;
98     default:
99       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100       break;
101@@ -2161,11 +2182,31 @@ gst_kms_sink_init (GstKMSSink * sink)
102   sink->saved_zpos = -1;
103   sink->can_scale = TRUE;
104   sink->keep_aspect = TRUE;
105+  sink->sync_mode = DEFAULT_SYNC_MODE;
106   gst_poll_fd_init (&sink->pollfd);
107   sink->poll = gst_poll_new (TRUE);
108   gst_video_info_init (&sink->vinfo);
109 }
110
111+#define GST_TYPE_KMS_SYNC_MODE (gst_kms_sync_mode_get_type ())
112+static GType
113+gst_kms_sync_mode_get_type (void)
114+{
115+  static GType mode = 0;
116+
117+  if (!mode) {
118+    static const GEnumValue modes[] = {
119+      {GST_KMS_SYNC_AUTO, "Sync with page flip or vblank event", "auto"},
120+      {GST_KMS_SYNC_FLIP, "Sync with page flip event", "flip"},
121+      {GST_KMS_SYNC_VBLANK, "Sync with vblank event", "vblank"},
122+      {GST_KMS_SYNC_NONE, "Ignore syncing", "none"},
123+      {0, NULL, NULL}
124+    };
125+    mode = g_enum_register_static ("GstKMSSyncMode", modes);
126+  }
127+  return mode;
128+}
129+
130 static void
131 gst_kms_sink_class_init (GstKMSSinkClass * klass)
132 {
133@@ -2335,6 +2376,15 @@ gst_kms_sink_class_init (GstKMSSinkClass * klass)
134       "When enabled, scaling will respect original aspect ratio", TRUE,
135       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
136
137+  if (g_getenv ("KMSSINK_DISABLE_VSYNC"))
138+    DEFAULT_SYNC_MODE = GST_KMS_SYNC_NONE;
139+
140+  g_properties[PROP_SYNC_MODE] =
141+      g_param_spec_enum ("sync-mode", "Sync mode",
142+      "Prefered frame syncing mode",
143+      GST_TYPE_KMS_SYNC_MODE, DEFAULT_SYNC_MODE,
144+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
145+
146   g_object_class_install_properties (gobject_class, PROP_N, g_properties);
147
148   gst_video_overlay_install_properties (gobject_class, PROP_N);
149diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
150index ab70ec4..274351e 100644
151--- a/sys/kms/gstkmssink.h
152+++ b/sys/kms/gstkmssink.h
153@@ -44,6 +44,14 @@ G_BEGIN_DECLS
154 typedef struct _GstKMSSink GstKMSSink;
155 typedef struct _GstKMSSinkClass GstKMSSinkClass;
156
157+typedef enum
158+{
159+  GST_KMS_SYNC_AUTO = 0,
160+  GST_KMS_SYNC_FLIP = 1,
161+  GST_KMS_SYNC_VBLANK = 2,
162+  GST_KMS_SYNC_NONE = 3,
163+} GstKMSSyncMode;
164+
165 struct _GstKMSSink {
166   GstVideoSink videosink;
167
168@@ -98,6 +106,8 @@ struct _GstKMSSink {
169   guintptr window_handle;
170
171   gboolean keep_aspect;
172+
173+  GstKMSSyncMode sync_mode;
174 };
175
176 struct _GstKMSSinkClass {
177--
1782.20.1
179
180