xserver: Branch 'server-1.20-branch' - 5 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 13 19:46:57 UTC 2019


 hw/xfree86/common/xf86Init.c             |   60 ++++++------
 hw/xfree86/drivers/modesetting/driver.h  |    1 
 hw/xfree86/drivers/modesetting/present.c |    3 
 hw/xfree86/drivers/modesetting/vblank.c  |  148 ++++++++++++++++++++++++++++++-
 randr/rrcrtc.c                           |   15 ++-
 5 files changed, 186 insertions(+), 41 deletions(-)

New commits:
commit 03b91e17ce72649b2d6946213f5a7d152bfe7098
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Wed Nov 6 10:45:43 2019 -0800

    xfree86: Call ScreenInit for protocol screens before GPU screens
    
    During startup, the xfree86 DDX's InitOutput() calls PreInit for
    protocol screens first, and then GPU screens. On teardown, dix_main()
    calls CloseScreen in the reverse order: GPU screens first starting with
    the last one and then working backwards, and then protocol screens also
    in reverse order.
    
    InitOutput() calls ScreenInit in the wrong order: for GPU screens first and then
    for protocol screens. This causes a problem for drivers that have global state
    that is tied to the first screen that calls ScreenInit.
    
    Fix this by simply re-ordering the for loops to call PreInit for
    protocol screens first and then for GPU screens second.
    
    (cherry picked from commit e5e9a8ca91d1c087edd8788a110251ad940dbc94)

diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index cabf8716b..fc60f68d3 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -682,36 +682,6 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
     if (!dixRegisterPrivateKey(&xf86ScreenKeyRec, PRIVATE_SCREEN, 0))
         FatalError("Cannot register DDX private keys");
 
-    for (i = 0; i < xf86NumGPUScreens; i++) {
-        ScrnInfoPtr pScrn = xf86GPUScreens[i];
-        xf86VGAarbiterLock(pScrn);
-
-        /*
-         * Almost everything uses these defaults, and many of those that
-         * don't, will wrap them.
-         */
-        pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
-#ifdef XFreeXDGA
-        pScrn->SetDGAMode = xf86SetDGAMode;
-#endif
-        pScrn->DPMSSet = NULL;
-        pScrn->LoadPalette = NULL;
-        pScrn->SetOverscan = NULL;
-        pScrn->DriverFunc = NULL;
-        pScrn->pScreen = NULL;
-        scr_index = AddGPUScreen(xf86ScreenInit, argc, argv);
-        xf86VGAarbiterUnlock(pScrn);
-        if (scr_index == i) {
-            dixSetPrivate(&screenInfo.gpuscreens[scr_index]->devPrivates,
-                          xf86ScreenKey, xf86GPUScreens[i]);
-            pScrn->pScreen = screenInfo.gpuscreens[scr_index];
-            /* The driver should set this, but make sure it is set anyway */
-            pScrn->vtSema = TRUE;
-        } else {
-            FatalError("AddScreen/ScreenInit failed for gpu driver %d %d\n", i, scr_index);
-        }
-    }
-
     for (i = 0; i < xf86NumScreens; i++) {
         xf86VGAarbiterLock(xf86Screens[i]);
         /*
@@ -767,6 +737,36 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
         xf86EnsureRANDR(xf86Screens[i]->pScreen);
     }
 
+    for (i = 0; i < xf86NumGPUScreens; i++) {
+        ScrnInfoPtr pScrn = xf86GPUScreens[i];
+        xf86VGAarbiterLock(pScrn);
+
+        /*
+         * Almost everything uses these defaults, and many of those that
+         * don't, will wrap them.
+         */
+        pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
+#ifdef XFreeXDGA
+        pScrn->SetDGAMode = xf86SetDGAMode;
+#endif
+        pScrn->DPMSSet = NULL;
+        pScrn->LoadPalette = NULL;
+        pScrn->SetOverscan = NULL;
+        pScrn->DriverFunc = NULL;
+        pScrn->pScreen = NULL;
+        scr_index = AddGPUScreen(xf86ScreenInit, argc, argv);
+        xf86VGAarbiterUnlock(pScrn);
+        if (scr_index == i) {
+            dixSetPrivate(&screenInfo.gpuscreens[scr_index]->devPrivates,
+                          xf86ScreenKey, xf86GPUScreens[i]);
+            pScrn->pScreen = screenInfo.gpuscreens[scr_index];
+            /* The driver should set this, but make sure it is set anyway */
+            pScrn->vtSema = TRUE;
+        } else {
+            FatalError("AddScreen/ScreenInit failed for gpu driver %d %d\n", i, scr_index);
+        }
+    }
+
     for (i = 0; i < xf86NumGPUScreens; i++)
         AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
 
commit 325f694e97a117aec47aa2e1a9b2b28c3c47994e
Author: Alex Goins <agoins at nvidia.com>
Date:   Tue Sep 17 18:36:35 2019 -0500

    modesetting: Implement ms_covering_randr_crtc() for ms_present_get_crtc()
    
    ms_present_get_crtc() returns an RRCrtcPtr, but derives it from a xf86CrtcPtr
    found via ms_dri2_crtc_covering_drawable()=>ms_covering_crtc(). As a result, it
    depends on all associated DIX ScreenRecs having an xf86CrtcConfigPtr DDX
    private.
    
    Some DIX ScreenRecs don't have an xf86CrtcConfigPtr DDX private, but do have an
    rrScrPrivPtr DDX private. Given that we can derive all of the information we
    need from RandR, we can support these screens by avoiding the use of xf86Crtc.
    This change implements an RandR-based path for ms_present_get_crtc(), allowing
    drawables to successfully fall back to syncing to the primary output, even if
    the slave doesn't have an xf86CrtcConfigPtr DDX private.
    
    Without this change, if a slave doesn't have an xf86CrtcConfigPtr DDX private,
    drawables will fall back to 1 FPS if they overlap an output on that slave.
    
    Signed-off-by: Alex Goins <agoins at nvidia.com>
    (cherry picked from commit 562c7888be538c4d043ec1f374a9d9afa0b305a4)

diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index c8db4b8a4..493280c1d 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -147,6 +147,7 @@ void ms_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq);
 Bool ms_crtc_on(xf86CrtcPtr crtc);
 
 xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
+RRCrtcPtr   ms_randr_crtc_covering_drawable(DrawablePtr pDraw);
 
 int ms_get_crtc_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
 
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index dda7cc064..ab79fe778 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -59,8 +59,7 @@ struct ms_present_vblank_event {
 static RRCrtcPtr
 ms_present_get_crtc(WindowPtr window)
 {
-    xf86CrtcPtr xf86_crtc = ms_dri2_crtc_covering_drawable(&window->drawable);
-    return xf86_crtc ? xf86_crtc->randr_crtc : NULL;
+    return ms_randr_crtc_covering_drawable(&window->drawable);
 }
 
 static int
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 7ab2a095f..31ff244ad 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -77,6 +77,28 @@ static void ms_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
         crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
 }
 
+static void ms_randr_crtc_box(RRCrtcPtr crtc, BoxPtr crtc_box)
+{
+    if (crtc->mode) {
+        crtc_box->x1 = crtc->x;
+        crtc_box->y1 = crtc->y;
+        switch (crtc->rotation) {
+            case RR_Rotate_0:
+            case RR_Rotate_180:
+            default:
+                crtc_box->x2 = crtc->x + crtc->mode->mode.width;
+                crtc_box->y2 = crtc->y + crtc->mode->mode.height;
+                break;
+            case RR_Rotate_90:
+            case RR_Rotate_270:
+                crtc_box->x2 = crtc->x + crtc->mode->mode.height;
+                crtc_box->y2 = crtc->y + crtc->mode->mode.width;
+                break;
+        }
+    } else
+        crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
+}
+
 static int ms_box_area(BoxPtr box)
 {
     return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
@@ -129,7 +151,7 @@ static RROutputPtr ms_first_output(ScreenPtr pScreen)
  */
 
 static xf86CrtcPtr
-ms_covering_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
+ms_covering_xf86_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -184,7 +206,74 @@ ms_covering_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
             if (!slave->is_output_slave)
                 continue;
 
-            if (ms_covering_crtc(slave, box, FALSE)) {
+            if (ms_covering_xf86_crtc(slave, box, FALSE)) {
+                /* The drawable is on a slave output, return primary crtc */
+                return crtc;
+            }
+        }
+    }
+
+    return best_crtc;
+}
+
+static RRCrtcPtr
+ms_covering_randr_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+    rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
+    RRCrtcPtr crtc, best_crtc;
+    int coverage, best_coverage;
+    int c;
+    BoxRec crtc_box, cover_box;
+    Bool crtc_on;
+
+    best_crtc = NULL;
+    best_coverage = 0;
+
+    if (!pScrPriv)
+        return NULL;
+
+    for (c = 0; c < pScrPriv->numCrtcs; c++) {
+        crtc = pScrPriv->crtcs[c];
+
+        if (screen_is_ms) {
+            crtc_on = ms_crtc_on((xf86CrtcPtr) crtc->devPrivate);
+        } else {
+            crtc_on = !!crtc->mode;
+        }
+
+        /* If the CRTC is off, treat it as not covering */
+        if (!crtc_on)
+            continue;
+
+        ms_randr_crtc_box(crtc, &crtc_box);
+        ms_box_intersect(&cover_box, &crtc_box, box);
+        coverage = ms_box_area(&cover_box);
+        if (coverage > best_coverage) {
+            best_crtc = crtc;
+            best_coverage = coverage;
+        }
+    }
+
+    /* Fallback to primary crtc for drawable's on slave outputs */
+    if (best_crtc == NULL && !pScreen->isGPU) {
+        RROutputPtr primary_output = NULL;
+        ScreenPtr slave;
+
+        if (dixPrivateKeyRegistered(rrPrivKey))
+            primary_output = ms_first_output(scrn->pScreen);
+        if (!primary_output || !primary_output->crtc)
+            return NULL;
+
+        crtc = primary_output->crtc;
+        if (!ms_crtc_on((xf86CrtcPtr) crtc->devPrivate))
+            return NULL;
+
+        xorg_list_for_each_entry(slave, &pScreen->slave_list, slave_head) {
+            if (!slave->is_output_slave)
+                continue;
+
+            if (ms_covering_randr_crtc(slave, box, FALSE)) {
                 /* The drawable is on a slave output, return primary crtc */
                 return crtc;
             }
@@ -205,7 +294,21 @@ ms_dri2_crtc_covering_drawable(DrawablePtr pDraw)
     box.x2 = box.x1 + pDraw->width;
     box.y2 = box.y1 + pDraw->height;
 
-    return ms_covering_crtc(pScreen, &box, TRUE);
+    return ms_covering_xf86_crtc(pScreen, &box, TRUE);
+}
+
+RRCrtcPtr
+ms_randr_crtc_covering_drawable(DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    BoxRec box;
+
+    box.x1 = pDraw->x;
+    box.y1 = pDraw->y;
+    box.x2 = box.x1 + pDraw->width;
+    box.y2 = box.y1 + pDraw->height;
+
+    return ms_covering_randr_crtc(pScreen, &box, TRUE);
 }
 
 static Bool
commit aa43dce15f69624ce939bb69bafc3df5a9b78dbb
Author: Alex Goins <agoins at nvidia.com>
Date:   Tue Sep 17 18:03:34 2019 -0500

    modesetting: Fix ms_covering_crtc() segfault with non-xf86Crtc slave
    
    DIX ScreenRecs don't necessarily have an xf86CrtcConfigPtr DDX private.
    ms_covering_crtc() assumes that they do, which can result in a segfault.
    
    Update ms_covering_crtc() to check the XF86_CRTC_CONFIG_PTR() returned pointer
    before dereferencing it. This will still mean that ms_covering_crtc() can't fall
    back to the primary output when a drawable overlaps a slave output (going to the
    1 FPS default instead), but it won't segfault.
    
    Signed-off-by: Alex Goins <agoins at nvidia.com>
    (cherry picked from commit 797e7a0ceb673fe2870c673e248835526a84d000)

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index df1d6aad8..7ab2a095f 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -141,6 +141,10 @@ ms_covering_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
 
     best_crtc = NULL;
     best_coverage = 0;
+
+    if (!xf86_config)
+        return NULL;
+
     for (c = 0; c < xf86_config->num_crtc; c++) {
         crtc = xf86_config->crtc[c];
 
commit 341a4787157c68597951727d5d11a2813a31ec7e
Author: Alex Goins <agoins at nvidia.com>
Date:   Wed Aug 28 18:24:16 2019 -0500

    modesetting: Fix ms_covering_crtc() segfault with non-modesetting slave primary
    
    ms_covering_crtc() uses RRFirstOutput() to determine a primary output to fall
    back to if a drawable is overlapping a slave output.
    
    If the primary output is a slave output, RRFirstOutput() will return a slave
    output even if passed a master ScreenPtr. ms_covering_crtc() dereferences the
    output's devPrivate, which is invalid for non-modesetting outputs, and can
    crash.
    
    Changing RRFirstOutput() could have unintended side effects for other callers,
    so this change replaces the call to RRFirstOutput() with ms_first_output().
    ms_first_output() ignores the primary output if it doesn't match the given
    ScreenPtr, choosing the first connected output instead.
    
    Signed-off-by: Alex Goins <agoins at nvidia.com>
    (cherry picked from commit 3ef9029ace4245d9f8929aa71e22bc6a6f40b7b3)

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 561229f30..df1d6aad8 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -91,6 +91,39 @@ ms_crtc_on(xf86CrtcPtr crtc)
 }
 
 /*
+ * Return the first output which is connected to an active CRTC on this screen.
+ *
+ * RRFirstOutput() will return an output from a slave screen if it is primary,
+ * which is not the behavior that ms_covering_crtc() wants.
+ */
+
+static RROutputPtr ms_first_output(ScreenPtr pScreen)
+{
+    rrScrPriv(pScreen);
+    RROutputPtr output;
+    int i, j;
+
+    if (!pScrPriv)
+        return NULL;
+
+    if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc &&
+        (pScrPriv->primaryOutput->pScreen == pScreen)) {
+        return pScrPriv->primaryOutput;
+    }
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++) {
+        RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+        for (j = 0; j < pScrPriv->numOutputs; j++) {
+            output = pScrPriv->outputs[j];
+            if (output->crtc == crtc)
+                return output;
+        }
+    }
+    return NULL;
+}
+
+/*
  * Return the crtc covering 'box'. If two crtcs cover a portion of
  * 'box', then prefer the crtc with greater coverage.
  */
@@ -135,7 +168,7 @@ ms_covering_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
         ScreenPtr slave;
 
         if (dixPrivateKeyRegistered(rrPrivKey))
-            primary_output = RRFirstOutput(scrn->pScreen);
+            primary_output = ms_first_output(scrn->pScreen);
         if (!primary_output || !primary_output->crtc)
             return NULL;
 
commit 2dd9dfc8d9a5dc906ee06d667a756ab267f55e64
Author: Alex Goins <agoins at nvidia.com>
Date:   Wed Sep 4 12:25:31 2019 -0500

    randr: Fix RRCrtcDetachScanoutPixmap() segfault during server teardown
    
    During server teardown, mrootdraw is NULL, which can cause segfaults if
    master->Stop{,Flipping}PixmapTracking() don't do NULL checking. In this case we
    shouldn't need to do master->Stop{,Flipping}PixmapTracking() anyway, so just
    skip it.
    
    Signed-off-by: Alex Goins <agoins at nvidia.com>
    (cherry picked from commit c82f814313a813d7e1a2d7d3b1f7561810446b34)

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index a851aebcc..ae7e30605 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -401,17 +401,22 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
         if (crtc->scanout_pixmap_back) {
             pScrPriv->rrDisableSharedPixmapFlipping(crtc);
 
-            master->StopFlippingPixmapTracking(mrootdraw,
-                                               crtc->scanout_pixmap,
-                                               crtc->scanout_pixmap_back);
+            if (mrootdraw) {
+                master->StopFlippingPixmapTracking(mrootdraw,
+                                                   crtc->scanout_pixmap,
+                                                   crtc->scanout_pixmap_back);
+            }
 
             rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
             crtc->scanout_pixmap_back = NULL;
         }
         else {
             pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
-            master->StopPixmapTracking(mrootdraw,
-                                       crtc->scanout_pixmap);
+
+            if (mrootdraw) {
+                master->StopPixmapTracking(mrootdraw,
+                                           crtc->scanout_pixmap);
+            }
         }
 
         rrDestroySharedPixmap(crtc, crtc->scanout_pixmap);


More information about the xorg-commit mailing list