This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch overline-textgrid
in repository efl.

View the commit online.

commit ce34c0c5d7bf7392f07b412063ebc44a070333bc
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Aug 4 22:02:07 2026 -0600

    ecore_drm2: fix crtc mode matching and pick the best output mode
    
    _output_modes_create() decides which mode an output comes up in by
    comparing the crtc's current mode against the connector's mode list:
    
        if (!memcmp(&crtc_mode, &omode->info, sizeof(crtc_mode)))
          current = omode;
    
    That comparison can never succeed. drmModeGetCrtc() leaves type and name
    zeroed, while the same mode as listed on the connector carries the type
    bits and a name. On a rockchip eDP panel the two differ by exactly that:
    
        connector mode[0]: 1920x1080 @60 clock=148500 type=0x68 name='1920x1080'
        crtc mode        : 1920x1080 @60 clock=148500 type=0    name=''
    
    so every startup falls into the crtc_mode.clock != 0 branch, appends a
    duplicate of a mode already in the list - minus its DRM_MODE_TYPE_PREFERRED
    flag - and makes that duplicate current_mode. The mode list has therefore
    been carrying a bogus extra entry, and the preferred fallback below it
    has been dead code.
    
    Compare the timings that define a mode instead of memcmp'ing the whole
    drmModeModeInfo.
    
    While here, make best actually mean best. It was assigned unconditionally
    inside a reverse walk, so it held whichever entry came last - the head of
    the list - regardless of what was in it. Score modes properly: largest
    resolution first, then a refresh floor so a 24Hz cinema mode does not win
    a tie, then the highest refresh, then let the display's own preferred
    timing settle the rest.
    
    Prefer that over the crtc's current mode when choosing what to bring the
    output up in. What the firmware or a previous session left behind is
    frequently a low fallback resolution, and it is not what the user wants
    to land on. An off-list crtc mode is still recorded so the current state
    can be described, but it is no longer what we boot into, and any stored
    per-screen configuration is applied afterwards and still wins.
    
    Note the separate preferred fallback is gone rather than reordered: the
    DRM_MODE_TYPE_PREFERRED flag is now a tie-break inside the scoring, and
    a standalone fallback would be unreachable anyway since best is set for
    any connector with at least one mode.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/lib/ecore_drm2/ecore_drm2_outputs.c | 76 +++++++++++++++++++++++++++++----
 1 file changed, 68 insertions(+), 8 deletions(-)

diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c
index 77123c948a..d80bbb1dc4 100644
--- a/src/lib/ecore_drm2/ecore_drm2_outputs.c
+++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c
@@ -334,6 +334,60 @@ _output_mode_add(Ecore_Drm2_Output *output, const drmModeModeInfo *info)
    return mode;
 }
 
+/* Lowest refresh we still consider "full speed".  Ecore_Drm2_Output_Mode's
+ * refresh is already rounded to whole Hz by _output_mode_add(), so 59.94Hz
+ * modes arrive here as 60; this is purely a floor that keeps 50/30/24Hz
+ * modes from winning a tie against a full rate one. */
+#define _MODE_REFRESH_MIN 59
+
+/* A CRTC's mode and the same mode as listed on the connector are not
+ * byte-identical: the kernel leaves 'type' and 'name' zeroed on what it
+ * hands back from drmModeGetCrtc(). memcmp() over the whole struct
+ * therefore never matches, so compare the timings that actually define
+ * the mode instead. */
+static Eina_Bool
+_output_mode_same(const drmModeModeInfo *a, const 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->flags == b->flags));
+}
+
+/* Highest resolution wins.  Among equal resolutions prefer something
+ * running at a sane refresh rate over, say, a 24Hz cinema mode, then the
+ * highest refresh, and finally let the display's own preferred timing
+ * break any remaining tie. */
+static Eina_Bool
+_output_mode_better(Ecore_Drm2_Output_Mode *m, Ecore_Drm2_Output_Mode *best)
+{
+   long long ma, ba;
+   Eina_Bool mok, bok;
+
+   if (!best) return EINA_TRUE;
+
+   ma = (long long)m->width * (long long)m->height;
+   ba = (long long)best->width * (long long)best->height;
+   if (ma != ba) return (ma > ba);
+
+   mok = (m->refresh >= _MODE_REFRESH_MIN);
+   bok = (best->refresh >= _MODE_REFRESH_MIN);
+   if (mok != bok) return mok;
+
+   if (m->refresh != best->refresh) return (m->refresh > best->refresh);
+
+   return ((m->flags & DRM_MODE_TYPE_PREFERRED) &&
+           (!(best->flags & DRM_MODE_TYPE_PREFERRED)));
+}
+
 static void
 _output_modes_create(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output, const drmModeConnector *conn)
 {
@@ -342,7 +396,7 @@ _output_modes_create(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output, const dr
    drmModeEncoder *enc;
    drmModeModeInfo crtc_mode;
    Ecore_Drm2_Output_Mode *omode;
-   Ecore_Drm2_Output_Mode *current = NULL, *preferred = NULL, *best = NULL;
+   Ecore_Drm2_Output_Mode *current = NULL, *best = NULL;
    Eina_List *l = NULL;
 
    memset(&crtc_mode, 0, sizeof(crtc_mode));
@@ -365,22 +419,28 @@ _output_modes_create(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output, const dr
 
    EINA_LIST_REVERSE_FOREACH(output->modes, l, omode)
      {
-        if (!memcmp(&crtc_mode, &omode->info, sizeof(crtc_mode)))
+        if (_output_mode_same(&crtc_mode, &omode->info))
           current = omode;
-        if (omode->flags & DRM_MODE_TYPE_PREFERRED)
-          preferred = omode;
-        best = omode;
+        if (_output_mode_better(omode, best))
+          best = omode;
      }
 
+   /* Only if the CRTC is running something the connector does not list at
+    * all - keep it around so we can still describe the current state. NB:
+    * this is deliberately not folded into the 'best' search above, as an
+    * off-list mode should never be what we boot into. */
    if ((!current) && (crtc_mode.clock != 0))
      {
         current = _output_mode_add(output, &crtc_mode);
         if (!current) goto err;
      }
 
-   if (current) output->current_mode = current;
-   else if (preferred) output->current_mode = preferred;
-   else if (best) output->current_mode = best;
+   /* Prefer the best mode the display can actually do over whatever the
+    * CRTC was left at by the firmware or a previous session - the latter
+    * is frequently a low fallback resolution. Any stored per-screen
+    * configuration is applied afterwards and still wins over this. */
+   if (best) output->current_mode = best;
+   else if (current) output->current_mode = current;
 
    if (!output->current_mode) goto err;
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to