xserver: Branch 'master' - 11 commits

Adam Jackson ajax at kemper.freedesktop.org
Mon Jun 20 15:37:40 UTC 2016


 dix/dispatch.c                                   |   30 +++++++-----
 exa/exa_render.c                                 |    3 -
 hw/xfree86/dri2/dri2.c                           |    7 ++
 hw/xfree86/drivers/modesetting/drmmode_display.c |   54 +++++++++++------------
 hw/xfree86/drivers/modesetting/present.c         |    9 +++
 hw/xfree86/modes/xf86RandR12.c                   |   11 ----
 include/scrnintstr.h                             |   15 ++----
 present/present.c                                |   35 +++++++++-----
 randr/randr.c                                    |   54 +++++++++++------------
 randr/rrcrtc.c                                   |   16 +++++-
 randr/rrmonitor.c                                |   17 +++++--
 randr/rroutput.c                                 |   10 +---
 randr/rrprovider.c                               |   50 ++++++---------------
 randr/rrscreen.c                                 |   12 +++--
 render/picture.h                                 |    2 
 15 files changed, 176 insertions(+), 149 deletions(-)

New commits:
commit 266cf39a8f108e2f365a9772f4ee4d9fca88eb36
Merge: fa7b70a 848089e
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Jun 20 11:21:40 2016 -0400

    Merge remote-tracking branch 'hans/for-master'

commit 848089e0dde38f043c85332785520946103e77c1
Author: Lyude Paul <cpaul at redhat.com>
Date:   Mon Jun 13 15:31:02 2016 -0400

    modesetting: Clear drmmode->fb_id before unflipping
    
    [fix copied from 40191d82370e in xf86-video-ati]
    
    Without this, we end up setting rotated CRTCs back to their previous
    framebuffer right after we perform a rotation. Reproducer:
    
    - Have two monitors connected at the same resolution
    - Rotate one monitor from normal straight to inverted
    - Watch as the monitor you didn't rotate either freezes or shows intense
      flickering
    
    Signed-off-by: Lyude <cpaul at redhat.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index d65c8c8..9a596de 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -626,6 +626,15 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id)
 	if (!crtc->enabled)
 	    continue;
 
+	/* info->drmmode.fb_id still points to the FB for the last flipped BO.
+	 * Clear it, drmmode_set_mode_major will re-create it
+	 */
+	if (drmmode_crtc->drmmode->fb_id) {
+		drmModeRmFB(drmmode_crtc->drmmode->fd,
+			    drmmode_crtc->drmmode->fb_id);
+		drmmode_crtc->drmmode->fb_id = 0;
+	}
+
 	if (drmmode_crtc->dpms_mode == DPMSModeOn)
 	    crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 					crtc->x, crtc->y);
commit 4313122dea0df9affc280ee698e929489061ccc6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jun 1 15:14:32 2016 +0200

    modesetting: Only add main fb if necessary
    
    If we're doing reverse-prime; or doing rotation the main fb is not used,
    and there is no reason to add it in this case.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 6aa935f..7e5901a 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -408,24 +408,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
     int output_count = 0;
     Bool ret = TRUE;
     int i;
-    uint32_t fb_id;
+    uint32_t fb_id = 0;
     drmModeModeInfo kmode;
-    int height;
-
-    height = pScrn->virtualY;
-
-    if (drmmode->fb_id == 0) {
-        ret = drmModeAddFB(drmmode->fd,
-                           pScrn->virtualX, height,
-                           pScrn->depth, pScrn->bitsPerPixel,
-                           drmmode_bo_get_pitch(&drmmode->front_bo),
-                           drmmode_bo_get_handle(&drmmode->front_bo),
-                           &drmmode->fb_id);
-        if (ret < 0) {
-            ErrorF("failed to add fb %d\n", ret);
-            return FALSE;
-        }
-    }
 
     saved_mode = crtc->mode;
     saved_x = crtc->x;
@@ -484,6 +468,22 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
             fb_id = drmmode_crtc->rotate_fb_id;
             x = y = 0;
         }
+
+        if (fb_id == 0) {
+            ret = drmModeAddFB(drmmode->fd,
+                               pScrn->virtualX, pScrn->virtualY,
+                               pScrn->depth, pScrn->bitsPerPixel,
+                               drmmode_bo_get_pitch(&drmmode->front_bo),
+                               drmmode_bo_get_handle(&drmmode->front_bo),
+                               &drmmode->fb_id);
+            if (ret < 0) {
+                ErrorF("failed to add fb %d\n", ret);
+                ret = FALSE;
+                goto done;
+            }
+            fb_id = drmmode->fb_id;
+        }
+
         if (drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
                            fb_id, x, y, output_ids, output_count, &kmode)) {
             xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
commit 877453212166fdc912e0d687cdecee11aba563b5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jun 1 15:11:05 2016 +0200

    modesetting: Remove unnecessary fb addition from drmmode_xf86crtc_resize
    
    drmmode_set_mode_major() is the only user of drmmode->fb_id and will
    create it if necessary.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index e6bc80d..6aa935f 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -1697,7 +1697,6 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
         drmmode_crtc = xf86_config->crtc[0]->driver_private;
     drmmode_ptr drmmode = drmmode_crtc->drmmode;
     drmmode_bo old_front;
-    Bool ret;
     ScreenPtr screen = xf86ScrnToScreen(scrn);
     uint32_t old_fb_id;
     int i, pitch, old_width, old_height, old_pitch;
@@ -1719,8 +1718,9 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
     old_width = scrn->virtualX;
     old_height = scrn->virtualY;
     old_pitch = drmmode_bo_get_pitch(&drmmode->front_bo);
-    old_fb_id = drmmode->fb_id;
     old_front = drmmode->front_bo;
+    old_fb_id = drmmode->fb_id;
+    drmmode->fb_id = 0;
 
     if (!drmmode_create_bo(drmmode, &drmmode->front_bo,
                            width, height, scrn->bitsPerPixel))
@@ -1732,13 +1732,6 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
     scrn->virtualY = height;
     scrn->displayWidth = pitch / cpp;
 
-    ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
-                       scrn->bitsPerPixel, pitch,
-                       drmmode_bo_get_handle(&drmmode->front_bo),
-                       &drmmode->fb_id);
-    if (ret)
-        goto fail;
-
     if (!drmmode->gbm) {
         new_pixels = drmmode_map_front_bo(drmmode);
         if (!new_pixels)
commit 210d83ad492f0e91889472eaae549106d9b4ebf5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jun 1 15:07:22 2016 +0200

    modesetting: Set ppix->fb_id to 0 after removing the fb
    
    This ensures the fb gets re-added when a shared pixmap is re-used for
    a second drmmode_set_scanout_pixmap_cpu call.
    
    Note currently the xserver never re-uses a shared pixmap in this way,
    so this is mostly a sanity fix.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 04d9df3..e6bc80d 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -693,6 +693,7 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
         if (crtc->randr_crtc->scanout_pixmap) {
             ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
             drmModeRmFB(drmmode->fd, ppriv->fb_id);
+            ppriv->fb_id = 0;
         }
         if (drmmode_crtc->slave_damage) {
             DamageUnregister(drmmode_crtc->slave_damage);
commit b8ef71fb07a8ba9587aeaca942b4de20b59266ca
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jun 1 14:59:38 2016 +0200

    modesetting: Properly cleanup fb for reverse-prime-offload
    
    drmmode_set_scanout_pixmap_gpu(pix) adds drmmod->fb_id through a call
    to drmmode_xf86crtc_resize(), but on a subsequent
    drmmode_set_scanout_pixmap_gpu(NULL) it would not remove the fb.
    
    This keeps the crtc marked as busy, which causes the dgpu to not
    being able to runtime suspend, after an output attached to the dgpu
    has been used once. Which causes burning through an additional 10W
    of power and the laptop to run quite hot.
    
    This commit adds the missing remove fb call, allowing the dgpu to runtime
    suspend after an external monitor has been plugged into the laptop.
    
    Note this also makes drmmode_set_scanout_pixmap_gpu(NULL) match the
    behavior of drmmode_set_scanout_pixmap_cpu(NULL) which was already
    removing the fb.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index d192d05..04d9df3 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -635,11 +635,17 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
     PixmapPtr screenpix = screen->GetScreenPixmap(screen);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
     int c, total_width = 0, max_height = 0, this_x = 0;
 
     if (!ppix) {
-        if (crtc->randr_crtc->scanout_pixmap)
+        if (crtc->randr_crtc->scanout_pixmap) {
             PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
+            if (drmmode->fb_id) {
+                drmModeRmFB(drmmode->fd, drmmode->fb_id);
+                drmmode->fb_id = 0;
+            }
+        }
         drmmode_crtc->prime_pixmap_x = 0;
         return TRUE;
     }
commit 15595d29c2c3992f260a3314f26fa691f1e5cec8
Author: Nikhil Mahale <nmahale at nvidia.com>
Date:   Thu May 26 21:50:16 2016 +0530

    randr: Adjust master's last set time with slaves
    
    In prime configurations master's last set time may not be latest
    and greatest, adjust it with slaves last set time, pick up greatest
    one. Otherwise xserver may end with events which has
    lastSetTime < lastConfigTime even if that's not
    the case and confuse xrandr client.
    
    [hdegoede: rebase on "xrandrprovider: Do not use separate lists for unbound /
     source / offload slaves"]
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/randr/randr.c b/randr/randr.c
index 95ed7e5..0138dc1 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -580,6 +580,18 @@ RRTellChanged(ScreenPtr pScreen)
         mastersp = pScrPriv;
     }
 
+    xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
+        pSlaveScrPriv = rrGetScrPriv(iter);
+
+        if (!iter->is_output_slave)
+            continue;
+
+        if (CompareTimeStamps(mastersp->lastSetTime,
+                              pSlaveScrPriv->lastSetTime) == EARLIER) {
+            mastersp->lastSetTime = pSlaveScrPriv->lastSetTime;
+        }
+    }
+
     if (mastersp->changed) {
         UpdateCurrentTimeIf();
         if (mastersp->configChanged) {
commit 5c7af02b103790ac1fb6a71822788892c70290b6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri May 13 15:58:10 2016 +0200

    xrandrprovider: Do not use separate lists for unbound / source / offload slaves
    
    A single provider can be both a offload and source slave at the same time,
    the use of seperate lists breaks in this case e.g. :
    
    xrandr --listproviders
    Providers: number : 2
    Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 0 name:modesetting
    Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 0 name:modesetting
    
    xrandr --setprovideroutputsource 1 0x7b
    xrandr --listproviders
    Providers: number : 2
    Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 1 name:modesetting
    Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 1 name:modesetting
    
    xrandr --setprovideroffloadsink 1 0x7b
    xrandr --listproviders
    Providers: number : 3
    Provider 0: id: 0x7b cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 2 associated providers: 2 name:modesetting
    Provider 1: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 2 name:modesetting
    Provider 2: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 2 outputs: 5 associated providers: 2 name:modesetting
    
    Not good. The problem is that the provider with id 0x46 now is on both
    the output_slave_list and the offload_slave_list of the master screen.
    
    This commit fixes this by unifying all 3 lists into a single slaves list.
    
    Note that this does change the struct _Screen definition, so this is an ABI
    break. I do not expect any of the drivers to actually use the removed / changed
    fields so a recompile should suffice.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 86124c6..8a7eff7 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3789,9 +3789,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
     pScreen->CreateScreenResources = 0;
 
     xorg_list_init(&pScreen->pixmap_dirty_list);
-    xorg_list_init(&pScreen->unattached_list);
-    xorg_list_init(&pScreen->output_slave_list);
-    xorg_list_init(&pScreen->offload_slave_list);
+    xorg_list_init(&pScreen->slave_list);
 
     /*
      * This loop gets run once for every Screen that gets added,
@@ -3950,7 +3948,7 @@ AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
 {
     assert(new->isGPU);
     assert(!new->current_master);
-    xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
+    xorg_list_add(&new->slave_head, &pScreen->slave_list);
     new->current_master = pScreen;
 }
 
@@ -3958,7 +3956,9 @@ void
 DetachUnboundGPU(ScreenPtr slave)
 {
     assert(slave->isGPU);
-    xorg_list_del(&slave->unattached_head);
+    assert(!slave->is_output_slave);
+    assert(!slave->is_offload_slave);
+    xorg_list_del(&slave->slave_head);
     slave->current_master = NULL;
 }
 
@@ -3966,31 +3966,35 @@ void
 AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
 {
     assert(new->isGPU);
-    xorg_list_add(&new->output_head, &pScreen->output_slave_list);
-    new->current_master = pScreen;
+    assert(!new->is_output_slave);
+    assert(new->current_master == pScreen);
+    new->is_output_slave = TRUE;
+    new->current_master->output_slaves++;
 }
 
 void
 DetachOutputGPU(ScreenPtr slave)
 {
     assert(slave->isGPU);
-    xorg_list_del(&slave->output_head);
-    slave->current_master = NULL;
+    assert(slave->is_output_slave);
+    slave->current_master->output_slaves--;
+    slave->is_output_slave = FALSE;
 }
 
 void
 AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
 {
     assert(new->isGPU);
-    xorg_list_add(&new->offload_head, &pScreen->offload_slave_list);
-    new->current_master = pScreen;
+    assert(!new->is_offload_slave);
+    assert(new->current_master == pScreen);
+    new->is_offload_slave = TRUE;
 }
 
 void
 DetachOffloadGPU(ScreenPtr slave)
 {
     assert(slave->isGPU);
-    xorg_list_del(&slave->offload_head);
-    slave->current_master = NULL;
+    assert(slave->is_offload_slave);
+    slave->is_offload_slave = FALSE;
 }
 
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index f80599f..2165603 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -186,12 +186,15 @@ static ScreenPtr
 GetScreenPrime(ScreenPtr master, int prime_id)
 {
     ScreenPtr slave;
-    if (prime_id == 0 || xorg_list_is_empty(&master->offload_slave_list)) {
+    if (prime_id == 0) {
         return master;
     }
-    xorg_list_for_each_entry(slave, &master->offload_slave_list, offload_head) {
+    xorg_list_for_each_entry(slave, &master->slave_list, slave_head) {
         DRI2ScreenPtr ds;
 
+        if (!slave->is_offload_slave)
+            continue;
+
         ds = DRI2GetScreen(slave);
         if (ds == NULL)
             continue;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 60d2254..4a21766 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1836,10 +1836,7 @@ xf86RandR14ProviderSetOutputSource(ScreenPtr pScreen,
 {
     if (!source_provider) {
         if (provider->output_source) {
-            ScreenPtr cmScreen = pScreen->current_master;
-
             xf86DetachOutputGPU(pScreen);
-            AttachUnboundGPU(cmScreen, pScreen);
         }
         provider->output_source = NULL;
         return TRUE;
@@ -1850,7 +1847,6 @@ xf86RandR14ProviderSetOutputSource(ScreenPtr pScreen,
 
     SetRootClip(source_provider->pScreen, ROOT_CLIP_NONE);
 
-    DetachUnboundGPU(pScreen);
     AttachOutputGPU(source_provider->pScreen, pScreen);
 
     provider->output_source = source_provider;
@@ -1865,9 +1861,7 @@ xf86RandR14ProviderSetOffloadSink(ScreenPtr pScreen,
 {
     if (!sink_provider) {
         if (provider->offload_sink) {
-            ScreenPtr cmScreen = pScreen->current_master;
             xf86DetachOutputGPU(pScreen);
-            AttachUnboundGPU(cmScreen, pScreen);
         }
 
         provider->offload_sink = NULL;
@@ -1877,7 +1871,6 @@ xf86RandR14ProviderSetOffloadSink(ScreenPtr pScreen,
     if (provider->offload_sink == sink_provider)
         return TRUE;
 
-    DetachUnboundGPU(pScreen);
     AttachOffloadGPU(sink_provider->pScreen, pScreen);
 
     provider->offload_sink = sink_provider;
@@ -1956,12 +1949,12 @@ xf86RandR14ProviderDestroy(ScreenPtr screen, RRProviderPtr provider)
             config->randr_provider->offload_sink = NULL;
             RRSetChanged(screen);
         }
-        else if (config->randr_provider->output_source) {
+        if (config->randr_provider->output_source) {
             xf86DetachOutputGPU(screen);
             config->randr_provider->output_source = NULL;
             RRSetChanged(screen);
         }
-        else if (screen->current_master)
+        if (screen->current_master)
             DetachUnboundGPU(screen);
     }
     config->randr_provider = NULL;
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 2e617c4..63ef55c 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -590,13 +590,14 @@ typedef struct _Screen {
 
     Bool isGPU;
 
-    struct xorg_list unattached_list;
-    struct xorg_list unattached_head;
-
+    /* Info on this screen's slaves (if any) */
+    struct xorg_list slave_list;
+    struct xorg_list slave_head;
+    int output_slaves;
+    /* Info for when this screen is a slave */
     ScreenPtr current_master;
-
-    struct xorg_list output_slave_list;
-    struct xorg_list output_head;
+    Bool is_output_slave;
+    Bool is_offload_slave;
 
     SharePixmapBackingProcPtr SharePixmapBacking;
     SetSharedPixmapBackingProcPtr SetSharedPixmapBacking;
@@ -605,8 +606,6 @@ typedef struct _Screen {
     StopPixmapTrackingProcPtr StopPixmapTracking;
 
     struct xorg_list pixmap_dirty_list;
-    struct xorg_list offload_slave_list;
-    struct xorg_list offload_head;
 
     ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
     XYToWindowProcPtr XYToWindow;
diff --git a/present/present.c b/present/present.c
index cebd2f7..5210832 100644
--- a/present/present.c
+++ b/present/present.c
@@ -145,7 +145,7 @@ present_check_flip(RRCrtcPtr    crtc,
         return FALSE;
 
     /* Fail to flip if we have slave outputs */
-    if (!xorg_list_is_empty(&screen->output_slave_list))
+    if (screen->output_slaves)
         return FALSE;
 
     /* Make sure the window hasn't been redirected with Composite */
diff --git a/randr/randr.c b/randr/randr.c
index 3aabb19..95ed7e5 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -483,7 +483,10 @@ TellChanged(WindowPtr pWin, void *value)
                     RRDeliverCrtcEvent(client, pWin, crtc);
             }
 
-            xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
+            xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
+                if (!iter->is_output_slave)
+                    continue;
+
                 pSlaveScrPriv = rrGetScrPriv(iter);
                 for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) {
                     RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i];
@@ -502,7 +505,10 @@ TellChanged(WindowPtr pWin, void *value)
                     RRDeliverOutputEvent(client, pWin, output);
             }
 
-            xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
+            xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
+                if (!iter->is_output_slave)
+                    continue;
+
                 pSlaveScrPriv = rrGetScrPriv(iter);
                 for (i = 0; i < pSlaveScrPriv->numOutputs; i++) {
                     RROutputPtr output = pSlaveScrPriv->outputs[i];
@@ -514,17 +520,7 @@ TellChanged(WindowPtr pWin, void *value)
         }
 
         if (pRREvent->mask & RRProviderChangeNotifyMask) {
-            xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
-                pSlaveScrPriv = rrGetScrPriv(iter);
-                if (pSlaveScrPriv->provider->changed)
-                    RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
-            }
-            xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
-                pSlaveScrPriv = rrGetScrPriv(iter);
-                if (pSlaveScrPriv->provider->changed)
-                    RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
-            }
-            xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
+            xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
                 pSlaveScrPriv = rrGetScrPriv(iter);
                 if (pSlaveScrPriv->provider->changed)
                     RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
@@ -602,21 +598,15 @@ RRTellChanged(ScreenPtr pScreen)
         for (i = 0; i < pScrPriv->numCrtcs; i++)
             pScrPriv->crtcs[i]->changed = FALSE;
 
-        xorg_list_for_each_entry(iter, &master->output_slave_list, output_head) {
-            pSlaveScrPriv = rrGetScrPriv(iter);
-            pSlaveScrPriv->provider->changed = FALSE;
-            for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
-                pSlaveScrPriv->outputs[i]->changed = FALSE;
-            for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
-                pSlaveScrPriv->crtcs[i]->changed = FALSE;
-        }
-        xorg_list_for_each_entry(iter, &master->offload_slave_list, offload_head) {
-            pSlaveScrPriv = rrGetScrPriv(iter);
-            pSlaveScrPriv->provider->changed = FALSE;
-        }
-        xorg_list_for_each_entry(iter, &master->unattached_list, unattached_head) {
+        xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
             pSlaveScrPriv = rrGetScrPriv(iter);
             pSlaveScrPriv->provider->changed = FALSE;
+            if (iter->is_output_slave) {
+                for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
+                    pSlaveScrPriv->outputs[i]->changed = FALSE;
+                for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
+                    pSlaveScrPriv->crtcs[i]->changed = FALSE;
+            }
         }
 
         if (mastersp->layoutChanged) {
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 5447133..ea91ab7 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -526,8 +526,12 @@ rrCheckPixmapBounding(ScreenPtr pScreen,
         RegionUnion(&total_region, &total_region, &new_crtc_region);
     }
 
-    xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &pScreen->slave_list, slave_head) {
         rrScrPrivPtr    slave_priv = rrGetScrPriv(slave);
+
+        if (!slave->is_output_slave)
+            continue;
+
         for (c = 0; c < slave_priv->numCrtcs; c++) {
             RRCrtcPtr slave_crtc = slave_priv->crtcs[c];
 
@@ -1700,7 +1704,10 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
     if (ret == TRUE)
         return;
 
-    xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &pScreen->slave_list, slave_head) {
+        if (!slave->is_output_slave)
+            continue;
+
         ret = check_all_screen_crtcs(slave, x, y);
         if (ret == TRUE)
             return;
@@ -1711,7 +1718,10 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
     if (ret == TRUE)
         return;
 
-    xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &pScreen->slave_list, slave_head) {
+        if (!slave->is_output_slave)
+            continue;
+
         ret = constrain_all_screen_crtcs(pDev, slave, x, y);
         if (ret == TRUE)
             return;
diff --git a/randr/rrmonitor.c b/randr/rrmonitor.c
index ba310ea..3f6e03e 100644
--- a/randr/rrmonitor.c
+++ b/randr/rrmonitor.c
@@ -202,8 +202,12 @@ RRMonitorInitList(ScreenPtr screen, RRMonitorListPtr mon_list, Bool get_active)
 
     /* Count the number of crtcs in this and any slave screens */
     numCrtcs = pScrPriv->numCrtcs;
-    xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
         rrScrPrivPtr pSlavePriv;
+
+        if (!slave->is_output_slave)
+            continue;
+
         pSlavePriv = rrGetScrPriv(slave);
         numCrtcs += pSlavePriv->numCrtcs;
     }
@@ -220,8 +224,12 @@ RRMonitorInitList(ScreenPtr screen, RRMonitorListPtr mon_list, Bool get_active)
             mon_list->server_crtc[c] = pScrPriv->crtcs[sc];
     }
 
-    xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
         rrScrPrivPtr pSlavePriv;
+
+        if (!slave->is_output_slave)
+            continue;
+
         pSlavePriv = rrGetScrPriv(slave);
         for (sc = 0; sc < pSlavePriv->numCrtcs; sc++, c++) {
             if (pSlavePriv->crtcs[sc]->mode != NULL)
@@ -471,7 +479,10 @@ RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor)
         return BadValue;
     }
 
-    xorg_list_for_each_entry(slave, &screen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
+        if (!slave->is_output_slave)
+            continue;
+
         if (RRMonitorMatchesOutputName(slave, monitor->name)) {
             client->errorValue = monitor->name;
             return BadValue;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 686ae49..a8efec4 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -570,12 +570,10 @@ ProcRRSetOutputPrimary(ClientPtr client)
         RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
 
         xorg_list_for_each_entry(slave,
-                                 &pWin->drawable.pScreen->output_slave_list,
-                                 output_head) {
-            rrScrPrivPtr pSlavePriv;
-            pSlavePriv = rrGetScrPriv(slave);
-
-            RRSetPrimaryOutput(slave, pSlavePriv, output);
+                                 &pWin->drawable.pScreen->slave_list,
+                                 slave_head) {
+            if (slave->is_output_slave)
+                RRSetPrimaryOutput(slave, rrGetScrPriv(slave), output);
         }
     }
 
diff --git a/randr/rrprovider.c b/randr/rrprovider.c
index 5329f41..8ef4726 100644
--- a/randr/rrprovider.c
+++ b/randr/rrprovider.c
@@ -72,15 +72,7 @@ ProcRRGetProviders (ClientPtr client)
 
     if (pScrPriv->provider)
         total_providers++;
-    xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
-        pScrPriv = rrGetScrPriv(iter);
-        total_providers += pScrPriv->provider ? 1 : 0;
-    }
-    xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
-        pScrPriv = rrGetScrPriv(iter);
-        total_providers += pScrPriv->provider ? 1 : 0;
-    }
-    xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
+    xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
         pScrPriv = rrGetScrPriv(iter);
         total_providers += pScrPriv->provider ? 1 : 0;
     }
@@ -116,13 +108,7 @@ ProcRRGetProviders (ClientPtr client)
 
         providers = (RRProvider *)extra;
         ADD_PROVIDER(pScreen);
-        xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
-            ADD_PROVIDER(iter);
-        }
-        xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
-            ADD_PROVIDER(iter);
-        }
-        xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
+        xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
             ADD_PROVIDER(iter);
         }
     }
@@ -182,12 +168,13 @@ ProcRRGetProviderInfo (ClientPtr client)
     /* count associated providers */
     if (provider->offload_sink)
         rep.nAssociatedProviders++;
-    if (provider->output_source)
-        rep.nAssociatedProviders++;
-    xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head)
-        rep.nAssociatedProviders++;
-    xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head)
+    if (provider->output_source &&
+            provider->output_source != provider->offload_sink)
         rep.nAssociatedProviders++;
+    xorg_list_for_each_entry(provscreen, &pScreen->slave_list, slave_head) {
+        if (provscreen->is_output_slave || provscreen->is_offload_slave)
+            rep.nAssociatedProviders++;
+    }
 
     rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
                   (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
@@ -237,27 +224,22 @@ ProcRRGetProviderInfo (ClientPtr client)
             swapl(&prov_cap[i]);
         i++;
     }
-    xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(provscreen, &pScreen->slave_list, slave_head) {
+        if (!provscreen->is_output_slave && !provscreen->is_offload_slave)
+            continue;
         pScrProvPriv = rrGetScrPriv(provscreen);
         providers[i] = pScrProvPriv->provider->id;
         if (client->swapped)
             swapl(&providers[i]);
-        prov_cap[i] = RR_Capability_SinkOutput;
+        prov_cap[i] = 0;
+        if (provscreen->is_output_slave)
+            prov_cap[i] |= RR_Capability_SinkOutput;
+        if (provscreen->is_offload_slave)
+            prov_cap[i] |= RR_Capability_SourceOffload;
         if (client->swapped)
             swapl(&prov_cap[i]);
         i++;
     }
-    xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) {
-        pScrProvPriv = rrGetScrPriv(provscreen);
-        providers[i] = pScrProvPriv->provider->id;
-        if (client->swapped)
-            swapl(&providers[i]);
-        prov_cap[i] = RR_Capability_SourceOffload;
-        if (client->swapped)
-            swapl(&prov_cap[i]);
-        i++;
-    }
-
 
     memcpy(name, provider->name, rep.nameLength);
     if (client->swapped) {
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index b5e2090..d6c4995 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -394,7 +394,10 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
 
     update_totals(pScreen, pScrPriv);
 
-    xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
+        if (!iter->is_output_slave)
+            continue;
+
         pScrPriv = rrGetScrPriv(iter);
 
         if (query)
@@ -450,7 +453,10 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
     }
     update_arrays(pScreen, pScrPriv, primary_crtc, has_primary);
 
-    xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
+    xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
+        if (!iter->is_output_slave)
+            continue;
+
         pScrPriv = rrGetScrPriv(iter);
 
         update_arrays(iter, pScrPriv, primary_crtc, has_primary);
@@ -503,7 +509,7 @@ rrGetScreenResources(ClientPtr client, Bool query)
         if (!RRGetInfo(pScreen, query))
             return BadAlloc;
 
-    if (!xorg_list_is_empty(&pScreen->output_slave_list))
+    if (pScreen->output_slaves)
         return rrGetMultiScreenResources(client, query, pScreen);
 
     if (!pScrPriv) {
commit bab0f450a719a11799491043b82c2f293fed27fe
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Feb 14 09:58:44 2015 +0000

    present: Fix presentation of flips out of order
    
    The flip queue currently only holds events submitted to the driver for
    flipping, awaiting the completion notifier. It is short. We therefore
    can speed up interrupt processing by keeping the small number of events
    ready to be flipped on the end of the flip queue. By appending the
    events to the flip_queue in the order that they become ready, we also
    resolve one issue causing Present to display frames out of order.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    Reviewed-and-tested-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/present/present.c b/present/present.c
index 2ae7d3a..cebd2f7 100644
--- a/present/present.c
+++ b/present/present.c
@@ -353,10 +353,10 @@ present_re_execute(present_vblank_ptr vblank)
 static void
 present_flip_try_ready(ScreenPtr screen)
 {
-    present_vblank_ptr  vblank, tmp;
+    present_vblank_ptr  vblank;
 
-    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
-        if (vblank->flip_ready) {
+    xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) {
+        if (vblank->queued) {
             present_re_execute(vblank);
             return;
         }
@@ -656,6 +656,8 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             DebugPresent(("\tr %lld %p (pending %p unflip %lld)\n",
                           vblank->event_id, vblank,
                           screen_priv->flip_pending, screen_priv->unflip_event_id));
+            xorg_list_del(&vblank->event_queue);
+            xorg_list_append(&vblank->event_queue, &present_flip_queue);
             vblank->flip_ready = TRUE;
             return;
         }
@@ -994,6 +996,7 @@ present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64
     xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) {
         if (vblank->event_id == event_id) {
             xorg_list_del(&vblank->event_queue);
+            vblank->queued = FALSE;
             return;
         }
     }
commit fbe660b7652b945bdd8e3eb0780179d83cc7de96
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Feb 14 09:58:43 2015 +0000

    present: Improve scaling of vblank handler
    
    With large numbers of queued vblank, the list iteration on every
    interupt dominates processing time. If we reorder the list to be in
    ascending event order, then not only is also likely to be in order for
    notification queries (i.e. the notification will be near the start of
    the list), we can also stop iterating when past the target event_id.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    Reviewed-and-tested-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/present/present.c b/present/present.c
index 105e2bf..2ae7d3a 100644
--- a/present/present.c
+++ b/present/present.c
@@ -517,19 +517,22 @@ present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
 void
 present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc)
 {
-    present_vblank_ptr  vblank, tmp;
+    present_vblank_ptr  vblank;
     int                 s;
 
     if (!event_id)
         return;
     DebugPresent(("\te %lld ust %lld msc %lld\n", event_id, ust, msc));
-    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
-        if (vblank->event_id == event_id) {
+    xorg_list_for_each_entry(vblank, &present_exec_queue, event_queue) {
+        int64_t match = event_id - vblank->event_id;
+        if (match == 0) {
             present_execute(vblank, ust, msc);
             return;
         }
+        if (match < 0)
+            break;
     }
-    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+    xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) {
         if (vblank->event_id == event_id) {
             present_flip_notify(vblank, ust, msc);
             return;
@@ -943,7 +946,7 @@ present_pixmap(WindowPtr window,
                       vblank->pixmap->drawable.id, vblank->window->drawable.id,
                       target_crtc, vblank->flip, vblank->sync_flip, vblank->serial));
 
-    xorg_list_add(&vblank->event_queue, &present_exec_queue);
+    xorg_list_append(&vblank->event_queue, &present_exec_queue);
     vblank->queued = TRUE;
     if (msc_is_after(target_msc, crtc_msc)) {
         ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc);
@@ -967,7 +970,7 @@ no_mem:
 void
 present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 {
-    present_vblank_ptr  vblank, tmp;
+    present_vblank_ptr  vblank;
 
     if (crtc == NULL)
         present_fake_abort_vblank(screen, event_id, msc);
@@ -978,14 +981,17 @@ present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64
         (*screen_priv->info->abort_vblank) (crtc, event_id, msc);
     }
 
-    xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
-        if (vblank->event_id == event_id) {
+    xorg_list_for_each_entry(vblank, &present_exec_queue, event_queue) {
+        int64_t match = event_id - vblank->event_id;
+        if (match == 0) {
             xorg_list_del(&vblank->event_queue);
             vblank->queued = FALSE;
             return;
         }
+        if (match < 0)
+            break;
     }
-    xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+    xorg_list_for_each_entry(vblank, &present_flip_queue, event_queue) {
         if (vblank->event_id == event_id) {
             xorg_list_del(&vblank->event_queue);
             return;
commit c6511d0142040654140bdedd6f03d43af0abba21
Author: Maarten Lankhorst <maarten.lankhorst at canonical.com>
Date:   Wed Oct 2 15:47:54 2013 +0200

    exa: only draw valid trapezoids
    
    Fixes freedesktop.org bug https://bugs.freedesktop.org/show_bug.cgi?id=67484
    
    If t->bottom is close to MIN_INT, removing top can wraparound, so do the check properly.
    A similar fix should also be applied to pixman.
    
    Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/exa/exa_render.c b/exa/exa_render.c
index fc3ddea..b24bec0 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -1141,7 +1141,8 @@ exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 
         exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
         for (; ntrap; ntrap--, traps++)
-            (*ps->RasterizeTrapezoid) (pPicture, traps, -bounds.x1, -bounds.y1);
+            if (xTrapezoidValid(traps))
+                (*ps->RasterizeTrapezoid) (pPicture, traps, -bounds.x1, -bounds.y1);
         exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
 
         xRel = bounds.x1 + xSrc - xDst;
diff --git a/render/picture.h b/render/picture.h
index 087e54d..4499a00 100644
--- a/render/picture.h
+++ b/render/picture.h
@@ -211,7 +211,7 @@ typedef pixman_fixed_t xFixed;
 /* whether 't' is a well defined not obviously empty trapezoid */
 #define xTrapezoidValid(t)  ((t)->left.p1.y != (t)->left.p2.y && \
 			     (t)->right.p1.y != (t)->right.p2.y && \
-			     (int) ((t)->bottom - (t)->top) > 0)
+			     ((t)->bottom > (t)->top))
 
 /*
  * Standard NTSC luminance conversions:


More information about the xorg-commit mailing list