<html>
    <head>
      <base href="https://bugs.freedesktop.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - gbm creates BO with wrong pitch when dri3_get_modifiers returns modifiers, causing drmModeAddFB2WithModifiers to fail"
   href="https://bugs.freedesktop.org/show_bug.cgi?id=111306">111306</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>gbm creates BO with wrong pitch when dri3_get_modifiers returns modifiers, causing drmModeAddFB2WithModifiers to fail
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>Mesa
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>19.1
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Other
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>medium
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Mesa core
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>mesa-dev@lists.freedesktop.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>jwrdegoede@fedoraproject.org
          </td>
        </tr>

        <tr>
          <th>QA Contact</th>
          <td>mesa-dev@lists.freedesktop.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This was first discussed here:
<a href="https://gitlab.freedesktop.org/xorg/xserver/merge_requests/254">https://gitlab.freedesktop.org/xorg/xserver/merge_requests/254</a>

Where I came up with a completely wrong fix.

The easiest way to reproduce this is:

1) Take a Skylake iGPU (in my case with 2 1920x1080 monitors attached)
2) Run Xorg master with the modesetting driver (master is necessary because
glamor has support for modifiers enabled only in master)
3) Run a recent gnome-shell on top of Xorg
4) Run xrandr --fb <width>x<height> changing the width to be 32 pixels larger
then necessary (or any other value not a multiple of 64)
5) Watch Xorg.log filling with errors like these:

[ 28843.414] (WW) modeset(0): Page flip failed: Invalid argument
[ 28843.414] (EE) modeset(0): present flip failed
[ 28843.595] (WW) modeset(0): Page flip failed: Invalid argument
[ 28843.595] (EE) modeset(0): present flip failed

<a href="https://gitlab.freedesktop.org/xorg/xserver/merge_requests/254">https://gitlab.freedesktop.org/xorg/xserver/merge_requests/254</a> has a completely
wrong workaround for this by disabling modifier support when a secondary GPU
with outputs is present, but that just happen to cause a fb width which was not
a multiple of 64.

As mentioned above the problem can be reproduced on a single GPU. The problem
seems to be that when the xserver's dri3_get_modifiers method returns a
non-empty modifier list, gbm creates buffer-objects using these modifiers
(fine) without taking the pitch requirements into account. Or at least without
taking the pitch requirements for using these modifiers on a BO which is to be
used as a framebuffer into account. This causes the Present extension flip done
with a pixmap backed by this BO to fail (the xserver will fallback to a bitblt
in this case).

Fixing this may require new API, since currently when using modifiers it is not
possible to indicate that the BO will be used for scanout AFAICT.

Another Xserver level workaround is this:

--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -693,6 +693,12 @@ xf86RandR12ScreenSetSize(ScreenPtr pScreen,
     if (pRoot && pScrn->vtSema)
         (*pScrn->EnableDisableFBAccess) (pScrn, FALSE);

+    /*
+     * Present flipping with modifiers may fail if our screen width is not
+     * a multiple of 64.
+     */
+    width = (width + 63) & ~63;
+
     /* Let the driver update virtualX and virtualY */
     if (!(*config->funcs->resize) (pScrn, width, height))
         goto finish;

Which works, but meh.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are the assignee for the bug.</li>
          <li>You are the QA Contact for the bug.</li>
      </ul>
    </body>
</html>