]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[drm] Try to maintain current mode when overridden
authorRay Strode <rstrode@redhat.com>
Mon, 14 Jun 2010 03:16:48 +0000 (23:16 -0400)
committerRay Strode <rstrode@redhat.com>
Mon, 14 Jun 2010 03:16:48 +0000 (23:16 -0400)
plymouth has naïvely been treating the first available mode in
the connector object as the active mode. While this is true
most of the time, it doesn't hold true if the user overrides the
mode on the kernel command line.

This commit changes things to look up the actual active mode, and go
with that, which should help prevent flicker at start up in some cases.

This patch is based heavily on a patch from Forest Bond
<forest@alittletooquiet.net> here:

http://lists.freedesktop.org/archives/plymouth/2010-June/000369.html

and first mentioned in commit abfda7550ac2fca6d816862e271126c2f44fa3cc

src/plugins/renderers/drm/plugin.c

index a77fbe9692904369a5007e711fb9822bb74428cc..f936d0a6c9e6ccadf7ff39089ef2daa7c41f0ff5 100644 (file)
@@ -707,6 +707,65 @@ find_encoder_for_connector (ply_renderer_backend_t *backend,
   return find_unused_encoder_for_connector (backend, connector);
 }
 
+static bool
+modes_are_equal (drmModeModeInfo *a,
+                 drmModeModeInfo *b)
+{
+  return a->clock == b->clock &&
+         a->hdisplay == b->hdisplay &&
+         a->hsync_start == b->hsync_start &&
+         a->hsync_end == b->hsync_end &&
+         a->htotal == b->htotal &&
+         a->hskew == b->hskew &&
+         a->vdisplay == b->vdisplay &&
+         a->vsync_start == b->vsync_start &&
+         a->vsync_end == b->vsync_end &&
+         a->vtotal == b->vtotal &&
+         a->vscan == b->vscan &&
+         a->vrefresh == b->vrefresh &&
+         a->flags == b->flags &&
+         a->type == b->type;
+
+}
+
+static int
+find_index_of_mode (ply_renderer_backend_t *backend,
+                    drmModeConnector       *connector,
+                    drmModeModeInfo        *mode)
+{
+  int i;
+
+  for (i = 0; i < connector->count_modes; i++)
+    {
+      if (modes_are_equal (&connector->modes[i], mode))
+        {
+          ply_trace ("Found connector mode index %d for mode %dx%d",
+                     i, mode->hdisplay, mode->vdisplay);
+
+          return i;
+        }
+    }
+
+  return -1;
+}
+
+static int
+get_index_of_active_mode (ply_renderer_backend_t *backend,
+                          drmModeCrtc            *controller,
+                          drmModeConnector       *connector)
+{
+  if (!controller->mode_valid)
+    {
+      ply_trace ("No valid mode currently active on monitor");
+      return -1;
+    }
+
+  ply_trace ("Looking for connector mode index of active mode %dx%d",
+             controller->mode.hdisplay, controller->mode.vdisplay);
+
+  return find_index_of_mode (backend, connector, &controller->mode);
+}
+
 static bool
 create_heads_for_active_connectors (ply_renderer_backend_t *backend)
 {
@@ -761,13 +820,15 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend)
 
       controller_id = controller->crtc_id;
 
-      /* The kernel orders the mode list such that the one picked by default is
-       * the first one.
-       *
-       * FIXME: This falls over if the mode is explicitly overridden on
-       * the kernel command line
+      connector_mode_index = get_index_of_active_mode (backend, controller, connector);
+
+      /* If we couldn't find the current active mode, fall back to the first available.
        */
-      connector_mode_index = 0;
+      if (connector_mode_index < 0)
+        {
+          ply_trace ("falling back to first available mode");
+          connector_mode_index = 0;
+        }
 
       console_buffer_id = controller->buffer_id;
       drmModeFreeCrtc (controller);