xserver: Branch 'master' - 15 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Jun 29 21:06:36 PDT 2015


 configure.ac                                     |    4 
 dix/cursor.c                                     |    8 
 glamor/glamor.h                                  |   37 +
 glamor/glamor_egl.c                              |  117 ++++-
 glamor/glamor_egl_stubs.c                        |    2 
 glamor/glamor_fbo.c                              |   13 
 hw/kdrive/ephyr/ephyrcursor.c                    |    4 
 hw/xfree86/common/xf86Config.c                   |   13 
 hw/xfree86/drivers/modesetting/driver.c          |   82 +++-
 hw/xfree86/drivers/modesetting/driver.h          |    9 
 hw/xfree86/drivers/modesetting/drmmode_display.c |  117 +++++
 hw/xfree86/drivers/modesetting/drmmode_display.h |   12 
 hw/xfree86/drivers/modesetting/present.c         |  450 ++++++++++++++++++++++-
 hw/xfree86/drivers/modesetting/vblank.c          |   23 -
 hw/xfree86/modes/xf86Cursors.c                   |    8 
 hw/xfree86/modes/xf86Rotate.c                    |    6 
 hw/xfree86/ramdac/xf86Cursor.c                   |    2 
 hw/xfree86/ramdac/xf86Cursor.h                   |    4 
 hw/xfree86/ramdac/xf86HWCurs.c                   |    6 
 hw/xquartz/xpr/xprCursor.c                       |    2 
 hw/xwayland/xwayland-glamor.c                    |    2 
 include/cursorstr.h                              |    2 
 include/dix-config.h.in                          |    3 
 mi/midispcur.c                                   |   20 -
 xfixes/cursor.c                                  |    2 
 25 files changed, 821 insertions(+), 127 deletions(-)

New commits:
commit 8a8d51358cea782147bb9b5b2e0902b1e47fcf4a
Merge: b22534d 13c7d53
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jun 29 21:04:53 2015 -0700

    Merge remote-tracking branch 'airlied/for-keithp'

commit 13c7d53df8dac45ea2a685826cd45a39bcb51657
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Mon Jan 26 21:29:23 2015 -0800

    modesetting: Implement page flipping support for Present.
    
    Based on code by Keith Packard, Eric Anholt, and Jason Ekstrand.
    
    v2:
    - Fix double free and flip_count underrun (caught by Mario Kleiner).
    - Don't leak flip_vblank_event on the error_out path (Mario).
    - Use the updated ms_flush_drm_events API (Mario, Ken).
    
    v3: Hack around DPMS shenanigans.  If all monitors are DPMS off, then
        there is no active framebuffer; attempting to pageflip will hit the
        error_undo paths, causing us to drmModeRmFB with no framebuffer,
        which confuses the kernel into doing full modesets and generally
        breaks things.  To avoid this, make ms_present_check_flip check that
        some CRTCs are enabled and DPMS on.  This is an ugly hack that would
        get better with atomic modesetting, or some core Present work.
    
    v4:
    - Don't do pageflipping if CRTCs are rotated (caught by Jason Ekstrand).
    - Make pageflipping optional (Option "PageFlip" in xorg.conf.d), but
      enabled by default.
    
    v5: Initialize num_crtcs_on to 0 (caught by Michel Dänzer).
    
    [airlied: took over]
    v6: merge async flip support from Mario Kleiner
    free sequence after failed vblank queue
    handle unflip while DPMS'ed off (Michel)
    move flip tracking into its own structure, and
    fix up reference counting issues, and add comments.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Acked-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index ae562a1..8603338 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -123,6 +123,7 @@ typedef enum {
     OPTION_DEVICE_PATH,
     OPTION_SHADOW_FB,
     OPTION_ACCEL_METHOD,
+    OPTION_PAGEFLIP,
 } modesettingOpts;
 
 static const OptionInfoRec Options[] = {
@@ -130,6 +131,7 @@ static const OptionInfoRec Options[] = {
     {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE},
     {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
     {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
+    {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
     {-1, NULL, OPTV_NONE, {0}, FALSE}
 };
 
@@ -820,6 +822,8 @@ PreInit(ScrnInfoPtr pScrn, int flags)
     try_enable_glamor(pScrn);
 
     if (ms->drmmode.glamor) {
+        ms->drmmode.pageflip =
+            xf86ReturnOptValBool(ms->Options, OPTION_PAGEFLIP, TRUE);
     } else {
         Bool prefer_shadow = TRUE;
 
@@ -836,6 +840,8 @@ PreInit(ScrnInfoPtr pScrn, int flags)
                    "ShadowFB: preferred %s, enabled %s\n",
                    prefer_shadow ? "YES" : "NO",
                    ms->drmmode.shadow_enable ? "YES" : "NO");
+
+        ms->drmmode.pageflip = FALSE;
     }
 
     if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 843a105..9ae4966 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -101,6 +101,12 @@ typedef struct _modesettingRec {
 
     drmEventContext event_context;
 
+    /**
+     * Page flipping stuff.
+     *  @{
+     */
+    /** @} */
+
     DamagePtr damage;
     Bool dirty_enabled;
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 506ea24..8dbac07 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -51,7 +51,8 @@
 #include "driver.h"
 
 static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
-static int
+
+int
 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
 {
     int ret;
@@ -72,7 +73,7 @@ drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
     return 0;
 }
 
-static uint32_t
+uint32_t
 drmmode_bo_get_pitch(drmmode_bo *bo)
 {
 #ifdef GLAMOR_HAS_GBM
@@ -143,6 +144,35 @@ drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
 }
 
 Bool
+drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr pixmap)
+{
+    ScreenPtr screen = xf86ScrnToScreen(drmmode->scrn);
+    uint16_t pitch;
+    uint32_t size;
+    int fd;
+
+#ifdef GLAMOR_HAS_GBM
+    if (drmmode->glamor) {
+        bo->gbm = glamor_gbm_bo_from_pixmap(screen, pixmap);
+        bo->dumb = NULL;
+        return bo->gbm != NULL;
+    }
+#endif
+
+    fd = glamor_fd_from_pixmap(screen, pixmap, &pitch, &size);
+    if (fd < 0) {
+        xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
+                   "Failed to get fd for flip to new front.\n");
+        return FALSE;
+    }
+
+    bo->dumb = dumb_get_bo_from_fd(drmmode->fd, fd, pitch, size);
+    close(fd);
+
+    return bo->dumb != NULL;
+}
+
+Bool
 drmmode_SetSlaveBO(PixmapPtr ppix,
                    drmmode_ptr drmmode, int fd_handle, int pitch, int size)
 {
@@ -368,6 +398,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
         if (crtc->scrn->pScreen)
             xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
 
+        drmmode_crtc->need_modeset = FALSE;
         crtc->funcs->dpms(crtc, DPMSModeOn);
 
         /* go through all the outputs and force DPMS them back on? */
@@ -1003,6 +1034,7 @@ static void
 drmmode_output_dpms(xf86OutputPtr output, int mode)
 {
     drmmode_output_private_ptr drmmode_output = output->driver_private;
+    xf86CrtcPtr crtc = output->crtc;
     drmModeConnectorPtr koutput = drmmode_output->mode_output;
     drmmode_ptr drmmode = drmmode_output->drmmode;
 
@@ -1011,6 +1043,13 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
 
     drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
                                 drmmode_output->dpms_enum_id, mode);
+
+    if (mode == DPMSModeOn && crtc) {
+        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+        if (drmmode_crtc->need_modeset)
+            drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+                                   crtc->x, crtc->y);
+    }
     return;
 }
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 85a0ec4..fe363c5 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -46,7 +46,6 @@ typedef struct {
 typedef struct {
     int fd;
     unsigned fb_id;
-    unsigned old_fb_id;
     drmModeFBPtr mode_fb;
     int cpp;
     ScrnInfoPtr scrn;
@@ -63,6 +62,8 @@ typedef struct {
 
     Bool glamor;
     Bool shadow_enable;
+    /** Is Option "PageFlip" enabled? */
+    Bool pageflip;
     void *shadow_fb;
 
     /**
@@ -107,6 +108,8 @@ typedef struct {
     uint32_t msc_prev;
     uint64_t msc_high;
     /** @} */
+
+    Bool need_modeset;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
@@ -141,6 +144,9 @@ extern DevPrivateKeyRec msPixmapPrivateKeyRec;
 
 #define msGetPixmapPriv(drmmode, p) ((msPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &(drmmode)->pixmapPrivateKeyRec))
 
+Bool drmmode_bo_for_pixmap(drmmode_ptr drmmode, drmmode_bo *bo, PixmapPtr pixmap);
+int drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo);
+uint32_t drmmode_bo_get_pitch(drmmode_bo *bo);
 uint32_t drmmode_bo_get_handle(drmmode_bo *bo);
 Bool drmmode_glamor_handle_new_screen_pixmap(drmmode_ptr drmmode);
 void *drmmode_map_slave_bo(drmmode_ptr drmmode, msPixmapPrivPtr ppriv);
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index 43df148..0905398 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -44,6 +44,7 @@
 #include <present.h>
 
 #include "driver.h"
+#include "drmmode_display.h"
 
 #if 0
 #define DebugPresent(x) ErrorF x
@@ -174,8 +175,10 @@ ms_present_queue_vblank(RRCrtcPtr crtc,
         /* If we hit EBUSY, then try to flush events.  If we can't, then
          * this is an error.
          */
-        if (errno != EBUSY || ms_flush_drm_events(screen) < 0)
+        if (errno != EBUSY || ms_flush_drm_events(screen) < 0) {
+	    ms_drm_abort_seq(scrn, seq);
             return BadAlloc;
+        }
     }
     DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
                  (long long) event_id, seq, (long long) msc,
@@ -221,6 +224,413 @@ ms_present_flush(WindowPtr window)
 #endif
 }
 
+#ifdef GLAMOR
+
+/*
+ * Event data for an in progress flip.
+ * This contains a pointer to the vblank event,
+ * and information about the flip in progress.
+ * a reference to this is stored in the per-crtc
+ * flips.
+ */
+struct ms_flipdata {
+    ScreenPtr screen;
+    struct ms_present_vblank_event *event;
+    /* number of CRTC events referencing this */
+    int flip_count;
+    uint64_t fe_msc;
+    uint64_t fe_usec;
+    uint32_t old_fb_id;
+};
+
+/*
+ * Per crtc pageflipping infomation,
+ * These are submitted to the queuing code
+ * one of them per crtc per flip.
+ */
+struct ms_crtc_pageflip {
+    Bool on_reference_crtc;
+    /* reference to the ms_flipdata */
+    struct ms_flipdata *flipdata;
+};
+
+/**
+ * Free an ms_crtc_pageflip.
+ *
+ * Drops the reference count on the flipdata.
+ */
+static void
+ms_present_flip_free(struct ms_crtc_pageflip *flip)
+{
+    struct ms_flipdata *flipdata = flip->flipdata;
+
+    free(flip);
+    if (--flipdata->flip_count > 0)
+        return;
+    free(flipdata);
+}
+
+/**
+ * Callback for the DRM event queue when a single flip has completed
+ *
+ * Once the flip has been completed on all pipes, notify the
+ * extension code telling it when that happened
+ */
+static void
+ms_flip_handler(uint64_t msc, uint64_t ust, void *data)
+{
+    struct ms_crtc_pageflip *flip = data;
+    ScreenPtr screen = flip->flipdata->screen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    struct ms_flipdata *flipdata = flip->flipdata;
+
+    DebugPresent(("\t\tms:fh %lld c %d msc %llu ust %llu\n",
+                  (long long) flipdata->event->event_id,
+                  flipdata->flip_count,
+                  (long long) msc, (long long) ust));
+
+    if (flip->on_reference_crtc) {
+        flipdata->fe_msc = msc;
+        flipdata->fe_usec = ust;
+    }
+
+    if (flipdata->flip_count == 1) {
+        DebugPresent(("\t\tms:fc %lld c %d msc %llu ust %llu\n",
+                      (long long) flipdata->event->event_id,
+                      flipdata->flip_count,
+                      (long long) flipdata->fe_msc, (long long) flipdata->fe_usec));
+
+
+        ms_present_vblank_handler(flipdata->fe_msc,
+                                  flipdata->fe_usec,
+                                  flipdata->event);
+
+        drmModeRmFB(ms->fd, flipdata->old_fb_id);
+    }
+    ms_present_flip_free(flip);
+}
+
+/*
+ * Callback for the DRM queue abort code.  A flip has been aborted.
+ */
+static void
+ms_present_flip_abort(void *data)
+{
+    struct ms_crtc_pageflip *flip = data;
+    struct ms_flipdata *flipdata = flip->flipdata;
+
+    DebugPresent(("\t\tms:fa %lld c %d\n", (long long) flipdata->event->event_id, flipdata->flip_count));
+
+    if (flipdata->flip_count == 1)
+        free(flipdata->event);
+
+    ms_present_flip_free(flip);
+}
+
+static Bool
+queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
+                   struct ms_flipdata *flipdata,
+                   int ref_crtc_vblank_pipe, uint32_t flags)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    struct ms_crtc_pageflip *flip;
+    uint32_t seq;
+    int err;
+
+    flip = calloc(1, sizeof(struct ms_crtc_pageflip));
+    if (flip == NULL) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "flip queue: carrier alloc failed.\n");
+        return FALSE;
+    }
+
+    /* Only the reference crtc will finally deliver its page flip
+     * completion event. All other crtc's events will be discarded.
+     */
+    flip->on_reference_crtc = (drmmode_crtc->vblank_pipe == ref_crtc_vblank_pipe);
+    flip->flipdata = flipdata;
+
+    seq = ms_drm_queue_alloc(crtc, flip, ms_flip_handler, ms_present_flip_abort);
+    if (!seq) {
+        free(flip);
+        return FALSE;
+    }
+
+    DebugPresent(("\t\tms:fq %lld c %d -> %d seq %llu\n",
+                  (long long) flipdata->event->event_id,
+                  flipdata->flip_count, flipdata->flip_count + 1,
+                  (long long) seq));
+
+    /* take a reference on flipdata for use in flip */
+    flipdata->flip_count++;
+
+    while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
+                           ms->drmmode.fb_id, flags, (void *) (uintptr_t) seq)) {
+        err = errno;
+        /* We may have failed because the event queue was full.  Flush it
+         * and retry.  If there was nothing to flush, then we failed for
+         * some other reason and should just return an error.
+         */
+        if (ms_flush_drm_events(screen) <= 0) {
+            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                       "flip queue failed: %s\n", strerror(err));
+            /* Aborting will also decrement flip_count and free(flip). */
+            ms_drm_abort_seq(scrn, seq);
+            return FALSE;
+        }
+
+        /* We flushed some events, so try again. */
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
+    }
+
+    /* The page flip succeded. */
+    return TRUE;
+}
+
+
+static Bool
+ms_do_pageflip(ScreenPtr screen,
+               PixmapPtr new_front,
+               struct ms_present_vblank_event *event,
+               int ref_crtc_vblank_pipe,
+               Bool async)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    drmmode_bo new_front_bo;
+    uint32_t flags;
+    int i;
+    struct ms_flipdata *flipdata;
+    glamor_block_handler(screen);
+
+    new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front);
+    new_front_bo.dumb = NULL;
+    if (!new_front_bo.gbm) {
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                   "Failed to get GBM bo for flip to new front.\n");
+        return FALSE;
+    }
+
+    flipdata = calloc(1, sizeof(struct ms_flipdata));
+    if (!flipdata) {
+        drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                   "Failed to allocate flipdata.\n");
+        return FALSE;
+    }
+
+    flipdata->event = event;
+    flipdata->screen = screen;
+
+    /*
+     * Take a local reference on flipdata.
+     * if the first flip fails, the sequence abort
+     * code will free the crtc flip data, and drop
+     * it's reference which would cause this to be
+     * freed when we still required it.
+     */
+    flipdata->flip_count++;
+
+    /* Create a new handle for the back buffer */
+    flipdata->old_fb_id = ms->drmmode.fb_id;
+    if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY,
+                     scrn->depth, scrn->bitsPerPixel,
+                     drmmode_bo_get_pitch(&new_front_bo),
+                     drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) {
+        goto error_out;
+    }
+
+    drmmode_bo_destroy(&ms->drmmode, &new_front_bo);
+
+    flags = DRM_MODE_PAGE_FLIP_EVENT;
+    if (async)
+        flags |= DRM_MODE_PAGE_FLIP_ASYNC;
+
+    /* Queue flips on all enabled CRTCs.
+     *
+     * Note that if/when we get per-CRTC buffers, we'll have to update this.
+     * Right now it assumes a single shared fb across all CRTCs, with the
+     * kernel fixing up the offset of each CRTC as necessary.
+     *
+     * Also, flips queued on disabled or incorrectly configured displays
+     * may never complete; this is a configuration error.
+     */
+    for (i = 0; i < config->num_crtc; i++) {
+        xf86CrtcPtr crtc = config->crtc[i];
+
+        if (!ms_crtc_on(crtc))
+            continue;
+
+        if (!queue_flip_on_crtc(screen, crtc, flipdata,
+                                ref_crtc_vblank_pipe,
+                                flags)) {
+            goto error_undo;
+        }
+    }
+
+    /*
+     * Do we have more than our local reference,
+     * if so and no errors, then drop our local
+     * reference and return now.
+     */
+    if (flipdata->flip_count > 1) {
+        flipdata->flip_count--;
+        return TRUE;
+    }
+
+error_undo:
+
+    /*
+     * Have we just got the local reference?
+     * free the framebuffer if so since nobody successfully
+     * submitted anything
+     */
+    if (flipdata->flip_count == 1) {
+        drmModeRmFB(ms->fd, ms->drmmode.fb_id);
+        ms->drmmode.fb_id = flipdata->old_fb_id;
+    }
+
+error_out:
+    xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
+               strerror(errno));
+    /* if only the local reference - free the structure,
+     * else drop the local reference and return */
+    if (flipdata->flip_count == 1)
+        free(flipdata);
+    else
+        flipdata->flip_count--;
+
+    return FALSE;
+}
+
+/*
+ * Test to see if page flipping is possible on the target crtc
+ */
+static Bool
+ms_present_check_flip(RRCrtcPtr crtc,
+                      WindowPtr window,
+                      PixmapPtr pixmap,
+                      Bool sync_flip)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    int num_crtcs_on = 0;
+    int i;
+
+    if (!ms->drmmode.pageflip)
+        return FALSE;
+
+    if (!scrn->vtSema)
+        return FALSE;
+
+    for (i = 0; i < config->num_crtc; i++) {
+        drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private;
+
+        /* Don't do pageflipping if CRTCs are rotated. */
+        if (drmmode_crtc->rotate_bo.gbm)
+            return FALSE;
+
+        if (ms_crtc_on(config->crtc[i]))
+            num_crtcs_on++;
+    }
+
+    /* We can't do pageflipping if all the CRTCs are off. */
+    if (num_crtcs_on == 0)
+        return FALSE;
+
+    /* Check stride, can't change that on flip */
+    if (pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo))
+        return FALSE;
+
+    /* Make sure there's a bo we can get to */
+    /* XXX: actually do this.  also...is it sufficient?
+     * if (!glamor_get_pixmap_private(pixmap))
+     *     return FALSE;
+     */
+
+    return TRUE;
+}
+
+/*
+ * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true,
+ * then wait for vblank. Otherwise, flip immediately
+ */
+static Bool
+ms_present_flip(RRCrtcPtr crtc,
+                uint64_t event_id,
+                uint64_t target_msc,
+                PixmapPtr pixmap,
+                Bool sync_flip)
+{
+    ScreenPtr screen = crtc->pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+    Bool ret;
+    struct ms_present_vblank_event *event;
+
+    if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+        return FALSE;
+
+    event = calloc(1, sizeof(struct ms_present_vblank_event));
+    if (!event)
+        return FALSE;
+
+    event->event_id = event_id;
+    ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip);
+    if (!ret)
+        xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
+
+    return ret;
+}
+
+/*
+ * Queue a flip back to the normal frame buffer
+ */
+static void
+ms_present_unflip(ScreenPtr screen, uint64_t event_id)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    int i;
+    struct ms_present_vblank_event *event;
+
+    event = calloc(1, sizeof(struct ms_present_vblank_event));
+    if (!event)
+        return;
+
+    event->event_id = event_id;
+
+    if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) &&
+        ms_do_pageflip(screen, pixmap, event, -1, FALSE)) {
+        return;
+    }
+
+    for (i = 0; i < config->num_crtc; i++) {
+        xf86CrtcPtr crtc = config->crtc[i];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	if (!crtc->enabled)
+	    continue;
+
+	if (drmmode_crtc->dpms_mode == DPMSModeOn)
+	    crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+					crtc->x, crtc->y);
+	else
+	    drmmode_crtc->need_modeset = TRUE;
+    }
+
+    present_event_notify(event_id, 0, 0);
+}
+#endif
+
 static present_screen_info_rec ms_present_screen_info = {
     .version = PRESENT_SCREEN_INFO_VERSION,
 
@@ -231,13 +641,24 @@ static present_screen_info_rec ms_present_screen_info = {
     .flush = ms_present_flush,
 
     .capabilities = PresentCapabilityNone,
-    .check_flip = 0,
-    .flip = 0,
-    .unflip = 0,
+    .check_flip = ms_present_check_flip,
+#ifdef GLAMOR
+    .flip = ms_present_flip,
+    .unflip = ms_present_unflip,
+#endif
 };
 
 Bool
 ms_present_screen_init(ScreenPtr screen)
 {
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    modesettingPtr ms = modesettingPTR(scrn);
+    uint64_t value;
+    int ret;
+
+    ret = drmGetCap(ms->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+    if (ret == 0 && value == 1)
+        ms_present_screen_info.capabilities |= PresentCapabilityAsync;
+
     return present_screen_init(screen, &ms_present_screen_info);
 }
commit 4342369e843ca2c6ca0a8c42475893cffb077a54
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Jun 26 09:20:13 2015 +1000

    modesetting: don't try and load dri2
    
    Since we are shipped with the server and the server has it built-in,
    don't bother trying to load it.
    
    Don't remove or invert the if statement on purpose as a later
    patch adds stuff in here.
    
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index f421668..ae562a1 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -820,7 +820,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)
     try_enable_glamor(pScrn);
 
     if (ms->drmmode.glamor) {
-        xf86LoadSubModule(pScrn, "dri2");
     } else {
         Bool prefer_shadow = TRUE;
 
commit edec6394a47be590f3133f6a90186356afd00829
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Jun 26 09:19:37 2015 +1000

    modesetting: drop unused struct in vblank.c
    
    this isn't used anywhere here.
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 776dcef..0b7bf9d 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -50,11 +50,6 @@
 static struct xorg_list ms_drm_queue;
 static uint32_t ms_drm_seq;
 
-struct ms_pageflip {
-    ScreenPtr screen;
-    Bool crtc_for_msc_ust;
-};
-
 static void ms_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
 {
     dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
commit bf262b43007050180d336defd48251de80894801
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Mon Jan 26 21:25:58 2015 -0800

    modesetting: Implement an ms_drm_abort_seq() function.
    
    This is a specialization of ms_drm_abort that matches based on the drm
    event queue's sequence number.
    
    Based on code by Keith Packard.
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>

diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 4b6ae87..843a105 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -117,6 +117,7 @@ uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
 void ms_drm_abort(ScrnInfoPtr scrn,
                   Bool (*match)(void *data, void *match_data),
                   void *match_data);
+void ms_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq);
 
 Bool ms_crtc_on(xf86CrtcPtr crtc);
 
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 91cfcf2..776dcef 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -323,6 +323,22 @@ ms_drm_abort_scrn(ScrnInfoPtr scrn)
     }
 }
 
+/**
+ * Abort by drm queue sequence number.
+ */
+void
+ms_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
+{
+    struct ms_drm_queue *q, *tmp;
+
+    xorg_list_for_each_entry_safe(q, tmp, &ms_drm_queue, list) {
+        if (q->seq == seq) {
+            ms_drm_abort_one(q);
+            break;
+        }
+    }
+}
+
 /*
  * Externally usable abort function that uses a callback to match a single
  * queued entry to abort
commit b8ccc5d36b0436bac57f07969ff3eb8d479a8511
Author: Jason Ekstrand <jason.ekstrand at intel.com>
Date:   Tue Jan 13 17:00:28 2015 -0800

    glamor: Add a new glamor_gbm_bo_from_pixmap() function.
    
    v2: Rebase on commit e0788a03144 (drop "base").
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index f402d7d..0931bbc 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -198,6 +198,21 @@ extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
 extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap,
                                              CARD16 *stride, CARD32 *size);
 
+/* @glamor_gbm_bo_from_pixmap: Get a GBM bo from a pixmap.
+ *
+ * @screen: Current screen pointer.
+ * @pixmap: The pixmap from which we want the fd.
+ * @stride, @size: Pointers to fill the stride and size of the
+ * 		   buffer associated to the fd.
+ *
+ * the pixmap and the buffer represented by the gbm_bo will share the same
+ * content.
+ *
+ * Returns the gbm_bo on success, NULL on error.
+ * */
+extern _X_EXPORT void *glamor_gbm_bo_from_pixmap(ScreenPtr screen,
+                                                 PixmapPtr pixmap);
+
 /* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd.
  *
  * @screen: Current screen pointer.
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 25a9fbe..e01f723 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -395,13 +395,10 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
 }
 #endif
 
-int
-glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
-                                 PixmapPtr pixmap,
-                                 unsigned int tex,
-                                 Bool want_name, CARD16 *stride, CARD32 *size)
-{
 #ifdef GLAMOR_HAS_GBM
+static void *
+_get_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, unsigned int tex)
+{
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_pixmap_private *pixmap_priv =
         glamor_get_pixmap_private(pixmap);
@@ -410,7 +407,6 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     struct gbm_bo *bo;
-    int fd = -1;
 
     EGLint attribs[] = {
         EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
@@ -430,7 +426,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                                   (EGLClientBuffer) (uintptr_t)
                                   tex, attribs);
         if (image == EGL_NO_IMAGE_KHR)
-            goto failure;
+            return NULL;
 
         glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
         glamor_egl_set_pixmap_image(pixmap, image);
@@ -438,6 +434,57 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0);
     if (!bo)
+        return NULL;
+
+    pixmap->devKind = gbm_bo_get_stride(bo);
+
+    return bo;
+}
+#endif
+
+void *
+glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
+{
+#ifdef GLAMOR_HAS_GBM
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
+    glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (pixmap_priv == NULL || !glamor_priv->dri3_enabled)
+        return NULL;
+    switch (pixmap_priv->type) {
+    case GLAMOR_TEXTURE_DRM:
+    case GLAMOR_TEXTURE_ONLY:
+        if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0))
+            return NULL;
+        return _get_gbm_bo_from_pixmap(screen, pixmap,
+                                       pixmap_priv->fbo->tex);
+    default:
+        break;
+    }
+    return NULL;
+#else
+    return NULL;
+#endif
+}
+
+int
+glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
+                                 PixmapPtr pixmap,
+                                 unsigned int tex,
+                                 Bool want_name, CARD16 *stride, CARD32 *size)
+{
+#ifdef GLAMOR_HAS_GBM
+    struct glamor_egl_screen_private *glamor_egl;
+    struct gbm_bo *bo;
+    int fd = -1;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    bo = _get_gbm_bo_from_pixmap(screen, pixmap, tex);
+    if (!bo)
         goto failure;
 
     pixmap->devKind = gbm_bo_get_stride(bo);
commit f2171d0a20d3b3858a282c51c1561432de1b29ef
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Tue Jan 6 21:02:44 2015 -0800

    modesetting: Make ms_crtc_on non-static.
    
    I want to use this in present.c.
    
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>

diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 3decc3e..4b6ae87 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -118,6 +118,8 @@ void ms_drm_abort(ScrnInfoPtr scrn,
                   Bool (*match)(void *data, void *match_data),
                   void *match_data);
 
+Bool ms_crtc_on(xf86CrtcPtr crtc);
+
 xf86CrtcPtr ms_dri2_crtc_covering_drawable(DrawablePtr pDraw);
 xf86CrtcPtr ms_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
                              xf86CrtcPtr desired, BoxPtr crtc_box_ret);
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index a342662..91cfcf2 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -88,7 +88,7 @@ static int ms_box_area(BoxPtr box)
     return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
 }
 
-static Bool
+Bool
 ms_crtc_on(xf86CrtcPtr crtc)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
commit f6853baebaec6a68078fa7f90486e9547d59dcbd
Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Sun Feb 8 17:21:58 2015 -0800

    modesetting: Improve the ms_flush_drm_events() API.
    
    Previously, ms_flush_drm_events() returned a boolean value, and it was
    very easy to interpret the meaning incorrectly.  Now, we return an
    integer value.
    
    The possible outcomes of this call are:
    - poll() raised an error (formerly TRUE, now -1 - poll's return value)
    - poll() said there are no events (formerly TRUE, now 0).
    - drmHandleEvent() raised an error (formerly FALSE, now the negative
      value returned by drmHandleEvent).
    - An event was successfully handled (formerly TRUE, now 1).
    
    The nice part is that this allows you to distinguish errors (< 0),
    nothing to do (= 0), and success (1).  We no longer conflate errors
    with success.
    
    v2: Change ms_present_queue_vblank to < 0 instead of <= 0, fixing an
        unintentional behavior change.  libdrm may return EBUSY if it's
        received EINTR for more than a second straight; just keep retrying
        in that case.  Suggested by Jasper St. Pierre.
    
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>

diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index 359e113..43df148 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -72,8 +72,11 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 
 /*
  * Flush the DRM event queue when full; makes space for new events.
+ *
+ * Returns a negative value on error, 0 if there was nothing to process,
+ * or 1 if we handled any events.
  */
-static Bool
+static int
 ms_flush_drm_events(ScreenPtr screen)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -86,10 +89,19 @@ ms_flush_drm_events(ScreenPtr screen)
             r = poll(&p, 1, 0);
     } while (r == -1 && (errno == EINTR || errno == EAGAIN));
 
+    /* If there was an error, r will be < 0.  Return that.  If there was
+     * nothing to process, r == 0.  Return that.
+     */
     if (r <= 0)
-        return TRUE;
+        return r;
+
+    /* Try to handle the event.  If there was an error, return it. */
+    r = drmHandleEvent(ms->fd, &ms->event_context);
+    if (r < 0)
+        return r;
 
-    return drmHandleEvent(ms->fd, &ms->event_context) >= 0;
+    /* Otherwise return 1 to indicate that we handled an event. */
+    return 1;
 }
 
 /*
@@ -159,7 +171,10 @@ ms_present_queue_vblank(RRCrtcPtr crtc,
         ret = drmWaitVBlank(ms->fd, &vbl);
         if (!ret)
             break;
-        if (errno != EBUSY || !ms_flush_drm_events(screen))
+        /* If we hit EBUSY, then try to flush events.  If we can't, then
+         * this is an error.
+         */
+        if (errno != EBUSY || ms_flush_drm_events(screen) < 0)
             return BadAlloc;
     }
     DebugPresent(("\t\tmq %lld seq %u msc %llu (hw msc %u)\n",
commit 7328fb3f2b468048faf4ed4c29db720b5bf00b05
Author: Dave Airlie <airlied at gmail.com>
Date:   Wed Jun 10 13:41:02 2015 +1000

    modesetting: reverse prime support (v1.1)
    
    This adds support for reverse prime to the modesetting driver.
    
    Reverse prime is where we have two GPUs in the display chain,
    but the second GPU can't scanout from the shared pixmap, so needs
    an extra copy to the on screen pixmap.
    
    This allows modesetting to support this scenario while still
    supporting the USB offload one.
    
    v1.1:
    fix comment + ret = bits (Eric)
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 092cc53..f421668 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -572,7 +572,7 @@ msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
     pScreen->BlockHandler(pScreen, pTimeout, pReadmask);
     ms->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = msBlockHandler;
-    if (pScreen->isGPU)
+    if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode)
         dispatch_slave_dirty(pScreen);
     else if (ms->dirty_enabled)
         dispatch_dirty(pScreen);
@@ -999,10 +999,18 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     modesettingPtr ms = modesettingPTR(scrn);
     Bool ret;
-    int size = ppix->devKind * ppix->drawable.height;
     int ihandle = (int) (long) fd_handle;
 
-    ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size);
+    if (ms->drmmode.reverse_prime_offload_mode) {
+        ret = glamor_back_pixmap_from_fd(ppix, ihandle,
+                                         ppix->drawable.width,
+                                         ppix->drawable.height,
+                                         ppix->devKind, ppix->drawable.depth,
+                                         ppix->drawable.bitsPerPixel);
+    } else {
+        int size = ppix->devKind * ppix->drawable.height;
+        ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size);
+    }
     if (ret == FALSE)
         return ret;
 
@@ -1190,6 +1198,9 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                        "Failed to initialize the Present extension.\n");
         }
+        /* enable reverse prime if we are a GPU screen, and accelerated */
+        if (pScreen->isGPU)
+            ms->drmmode.reverse_prime_offload_mode = TRUE;
     }
 #endif
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index f3c9909..506ea24 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -50,6 +50,7 @@
 
 #include "driver.h"
 
+static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
 static int
 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
 {
@@ -343,10 +344,14 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
         fb_id = drmmode->fb_id;
         if (crtc->randr_crtc->scanout_pixmap) {
-            msPixmapPrivPtr ppriv =
-                msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
-            fb_id = ppriv->fb_id;
-            x = y = 0;
+            if (!drmmode->reverse_prime_offload_mode) {
+                msPixmapPrivPtr ppriv =
+                    msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
+                fb_id = ppriv->fb_id;
+                x = 0;
+            } else
+                x = drmmode_crtc->prime_pixmap_x;
+            y = 0;
         }
         else if (drmmode_crtc->rotate_fb_id) {
             fb_id = drmmode_crtc->rotate_fb_id;
@@ -502,7 +507,54 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
 }
 
 static Bool
-drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
+drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
+{
+    ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
+    PixmapPtr screenpix = screen->GetScreenPixmap(screen);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    int c, total_width = 0, max_height = 0, this_x = 0;
+
+    if (!ppix) {
+        if (crtc->randr_crtc->scanout_pixmap)
+            PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
+        drmmode_crtc->prime_pixmap_x = 0;
+        return TRUE;
+    }
+    /* iterate over all the attached crtcs to work out the bounding box */
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+        xf86CrtcPtr iter = xf86_config->crtc[c];
+        if (!iter->enabled && iter != crtc)
+            continue;
+        if (iter == crtc) {
+            this_x = total_width;
+            total_width += ppix->drawable.width;
+            if (max_height < ppix->drawable.height)
+                max_height = ppix->drawable.height;
+        } else {
+            total_width += iter->mode.HDisplay;
+            if (max_height < iter->mode.VDisplay)
+                max_height = iter->mode.VDisplay;
+        }
+    }
+
+    if (total_width != screenpix->drawable.width ||
+        max_height != screenpix->drawable.height) {
+
+        if (!drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height))
+            return FALSE;
+
+        screenpix = screen->GetScreenPixmap(screen);
+        screen->width = screenpix->drawable.width = total_width;
+        screen->height = screenpix->drawable.height = max_height;
+    }
+    drmmode_crtc->prime_pixmap_x = this_x;
+    PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
+    return TRUE;
+}
+
+static Bool
+drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
     drmmode_ptr drmmode = drmmode_crtc->drmmode;
@@ -543,6 +595,18 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
     return TRUE;
 }
 
+static Bool
+drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
+{
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+    if (drmmode->reverse_prime_offload_mode)
+        return drmmode_set_scanout_pixmap_gpu(crtc, ppix);
+    else
+        return drmmode_set_scanout_pixmap_cpu(crtc, ppix);
+}
+
 static void *
 drmmode_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 {
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index b0e45b6..85a0ec4 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -79,6 +79,8 @@ typedef struct {
     uint32_t triple_buffer_name;
 
     DevPrivateKeyRec pixmapPrivateKeyRec;
+
+    Bool reverse_prime_offload_mode;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
@@ -93,7 +95,7 @@ typedef struct {
 
     drmmode_bo rotate_bo;
     unsigned rotate_fb_id;
-
+    unsigned prime_pixmap_x;
     /**
      * @{ MSC (vblank count) handling for the PRESENT extension.
      *
commit 1f10ee221edb87561900f5d2b1336db1c4a9f05c
Author: Dave Airlie <airlied at gmail.com>
Date:   Wed Jun 10 13:38:39 2015 +1000

    glamor: egl: add function to back a pixmap with a dma-buf. (v1.1)
    
    Rather than create the pixmap, this uses the file descriptor
    to change an existing pixmaps backing store.
    
    This is required for reverse prime slaves, where we create
    the slave pixmap, then set the backing store.
    
    v1.1: use local pScreen (Eric)
    
    Reviewed-by: Eric Anholt <eric at annholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 657354d..f402d7d 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -218,6 +218,25 @@ extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
                                                  CARD8 depth,
                                                  CARD8 bpp);
 
+/* @glamor_back_pixmap_from_fd: Backs an existing pixmap with a dma-buf fd.
+ *
+ * @pixmap: Pixmap to change backing for
+ * @fd: The dma-buf fd to import.
+ * @width: The width of the buffer.
+ * @height: The height of the buffer.
+ * @stride: The stride of the buffer.
+ * @depth: The depth of the buffer.
+ * @bpp: The number of bpp of the buffer.
+ *
+ * Returns TRUE if successful, FALSE on failure.
+ * */
+extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap,
+                                                 int fd,
+                                                 CARD16 width,
+                                                 CARD16 height,
+                                                 CARD16 stride,
+                                                 CARD8 depth,
+                                                 CARD8 bpp);
 #ifdef GLAMOR_FOR_XORG
 
 #define GLAMOR_EGL_MODULE_NAME  "glamoregl"
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 4c0db6a..25a9fbe 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -461,19 +461,19 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 #endif
 }
 
-_X_EXPORT PixmapPtr
-glamor_pixmap_from_fd(ScreenPtr screen,
-                      int fd,
-                      CARD16 width,
-                      CARD16 height,
-                      CARD16 stride, CARD8 depth, CARD8 bpp)
+_X_EXPORT Bool
+glamor_back_pixmap_from_fd(PixmapPtr pixmap,
+                           int fd,
+                           CARD16 width,
+                           CARD16 height,
+                           CARD16 stride, CARD8 depth, CARD8 bpp)
 {
 #ifdef GLAMOR_HAS_GBM
+    ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_egl_screen_private *glamor_egl;
     struct gbm_bo *bo;
     EGLImageKHR image;
-    PixmapPtr pixmap;
     Bool ret = FALSE;
 
     EGLint attribs[] = {
@@ -489,10 +489,10 @@ glamor_pixmap_from_fd(ScreenPtr screen,
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
     if (!glamor_egl->dri3_capable)
-        return NULL;
+        return FALSE;
 
     if (bpp != 32 || !(depth == 24 || depth == 32) || width == 0 || height == 0)
-        return NULL;
+        return FALSE;
 
     attribs[1] = width;
     attribs[3] = height;
@@ -504,29 +504,48 @@ glamor_pixmap_from_fd(ScreenPtr screen,
                               NULL, attribs);
 
     if (image == EGL_NO_IMAGE_KHR)
-        return NULL;
+        return FALSE;
 
     /* EGL_EXT_image_dma_buf_import can impose restrictions on the
      * usage of the image. Use gbm_bo to bypass the limitations. */
-
     bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0);
     eglDestroyImageKHR(glamor_egl->display, image);
 
     if (!bo)
-        return NULL;
+        return FALSE;
 
-    pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
     screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
 
     ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo);
     gbm_bo_destroy(bo);
 
     if (ret)
-        return pixmap;
-    else {
+        return TRUE;
+    return FALSE;
+#else
+    return FALSE;
+#endif
+}
+
+_X_EXPORT PixmapPtr
+glamor_pixmap_from_fd(ScreenPtr screen,
+                      int fd,
+                      CARD16 width,
+                      CARD16 height,
+                      CARD16 stride, CARD8 depth, CARD8 bpp)
+{
+#ifdef GLAMOR_HAS_GBM
+    PixmapPtr pixmap;
+    Bool ret;
+
+    pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
+    ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height,
+                                     stride, depth, bpp);
+    if (ret == FALSE) {
         screen->DestroyPixmap(pixmap);
         return NULL;
     }
+    return pixmap;
 #else
     return NULL;
 #endif
commit a79fbfd707e1d745b670def08287241c87e11c28
Author: Dave Airlie <airlied at gmail.com>
Date:   Tue Jun 9 17:15:44 2015 +1000

    modesetting: add output master support
    
    This allows a glamor enabled master device to have
    slave USB devices attached.
    
    Tested with modesetting on SNB + USB.
    
    It relies on the previous patch to export linear
    buffers from glamor.
    
    Acked-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index e90e4b8..092cc53 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -532,6 +532,38 @@ dispatch_slave_dirty(ScreenPtr pScreen)
 }
 
 static void
+redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
+{
+
+        RegionRec pixregion;
+
+        PixmapRegionInit(&pixregion, dirty->slave_dst);
+        DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+        PixmapSyncDirtyHelper(dirty, &pixregion);
+
+        DamageRegionProcessPending(&dirty->slave_dst->drawable);
+        RegionUninit(&pixregion);
+}
+
+static void
+ms_dirty_update(ScreenPtr screen)
+{
+        RegionPtr region;
+        PixmapDirtyUpdatePtr ent;
+
+        if (xorg_list_is_empty(&screen->pixmap_dirty_list))
+                return;
+
+        xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
+                region = DamageRegion(ent->damage);
+                if (RegionNotEmpty(region)) {
+                        redisplay_dirty(screen, ent);
+                        DamageEmpty(ent->damage);
+                }
+        }
+}
+
+static void
 msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
 {
     modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
@@ -544,6 +576,8 @@ msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
         dispatch_slave_dirty(pScreen);
     else if (ms->dirty_enabled)
         dispatch_dirty(pScreen);
+
+    ms_dirty_update(pScreen);
 }
 
 static void
@@ -727,6 +761,10 @@ PreInit(ScrnInfoPtr pScrn, int flags)
     if (ret == 0) {
         if (value & DRM_PRIME_CAP_IMPORT)
             pScrn->capabilities |= RR_Capability_SinkOutput;
+#if GLAMOR_HAS_GBM_LINEAR
+        if (value & DRM_PRIME_CAP_EXPORT)
+            pScrn->capabilities |= RR_Capability_SourceOutput;
+#endif
     }
 #endif
     drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp);
@@ -938,6 +976,23 @@ msShadowInit(ScreenPtr pScreen)
 }
 
 static Bool
+msSharePixmapBacking(PixmapPtr ppix, ScreenPtr screen, void **handle)
+{
+#ifdef GLAMOR_HAS_GBM
+    int ret;
+    CARD16 stride;
+    CARD32 size;
+    ret = glamor_fd_from_pixmap(ppix->drawable.pScreen, ppix, &stride, &size);
+    if (ret == -1)
+        return FALSE;
+
+    *handle = (void *)(long)(ret);
+    return TRUE;
+#endif
+    return FALSE;
+}
+
+static Bool
 msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
 {
     ScreenPtr screen = ppix->drawable.pScreen;
@@ -1089,7 +1144,10 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
     ms->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = msBlockHandler;
 
+    pScreen->SharePixmapBacking = msSharePixmapBacking;
     pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking;
+    pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
+    pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
 
     if (!xf86CrtcScreenInit(pScreen))
         return FALSE;
commit ea0e4d752b778c1f2132f8d29542f7dabc296415
Author: Dave Airlie <airlied at gmail.com>
Date:   Wed Jun 10 14:46:22 2015 +1000

    glamor: add support for allocating linear buffers (v2)
    
    We need this for doing USB offload scenarios using glamor
    and modesetting driver.
    
    unfortunately only gbm in mesa 10.6 has support for the
    linear API.
    
    v1.1: fix bad define
    v2: update the configure.ac test as per amdgpu. (Michel)
    set linear bos to external to avoid cache. (Eric)
    
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/configure.ac b/configure.ac
index f760730..592e133 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2105,6 +2105,10 @@ if test "x$GLAMOR" = xyes; then
 	if test "x$GBM" = xyes; then
 		AC_DEFINE(GLAMOR_HAS_GBM, 1,
 			  [Build glamor with GBM-based EGL support])
+		AC_CHECK_DECL(GBM_BO_USE_LINEAR,
+			[AC_DEFINE(GLAMOR_HAS_GBM_LINEAR, 1, [Have GBM_BO_USE_LINEAR])], [],
+			[#include <stdlib.h>
+			 #include <gbm.h>])
 	fi
 
 fi
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 0d57fff..657354d 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -142,7 +142,8 @@ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen);
 extern _X_EXPORT unsigned int glamor_egl_create_argb8888_based_texture(ScreenPtr
                                                                        screen,
                                                                        int w,
-                                                                       int h);
+                                                                       int h,
+                                                                       Bool linear);
 extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr,
                                                       unsigned int, Bool,
                                                       CARD16 *, CARD32 *);
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index dc54561..4c0db6a 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -187,7 +187,7 @@ glamor_egl_get_gbm_device(ScreenPtr screen)
 }
 
 unsigned int
-glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
+glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_egl_screen_private *glamor_egl;
@@ -200,6 +200,9 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
     bo = gbm_bo_create(glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888,
+#ifdef GLAMOR_HAS_GBM_LINEAR
+                       (linear ? GBM_BO_USE_LINEAR : 0) |
+#endif
                        GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
     if (!bo)
         return 0;
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index a93f62d..c11e6d5 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -50,7 +50,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 }
 
 unsigned int
-glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
+glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear)
 {
     return 0;
 }
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index ea0e801..6017f5e 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -228,6 +228,9 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
     fbo->external = FALSE;
     fbo->format = format;
 
+    if (flag == CREATE_PIXMAP_USAGE_SHARED)
+        fbo->external = TRUE;
+
     if (flag != GLAMOR_CREATE_FBO_NO_FBO) {
         if (glamor_pixmap_ensure_fb(glamor_priv, fbo) != 0) {
             glamor_purge_fbo(glamor_priv, fbo);
@@ -313,7 +316,7 @@ glamor_destroy_fbo(glamor_screen_private *glamor_priv,
 
 static int
 _glamor_create_tex(glamor_screen_private *glamor_priv,
-                   int w, int h, GLenum format)
+                   int w, int h, GLenum format, Bool linear)
 {
     unsigned int tex = 0;
 
@@ -323,7 +326,7 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
      * an ARGB8888 based texture for us. */
     if (glamor_priv->dri3_enabled && format == GL_RGBA) {
         tex = glamor_egl_create_argb8888_based_texture(glamor_priv->screen,
-                                                       w, h);
+                                                       w, h, linear);
     }
     if (!tex) {
         glamor_make_current(glamor_priv);
@@ -344,14 +347,14 @@ glamor_create_fbo(glamor_screen_private *glamor_priv,
     glamor_pixmap_fbo *fbo;
     GLint tex = 0;
 
-    if (flag == GLAMOR_CREATE_FBO_NO_FBO)
+    if (flag == GLAMOR_CREATE_FBO_NO_FBO || flag == CREATE_PIXMAP_USAGE_SHARED)
         goto new_fbo;
 
     fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, format);
     if (fbo)
         return fbo;
  new_fbo:
-    tex = _glamor_create_tex(glamor_priv, w, h, format);
+    tex = _glamor_create_tex(glamor_priv, w, h, format, flag == CREATE_PIXMAP_USAGE_SHARED);
     fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
 
     return fbo;
@@ -531,7 +534,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
         if (!pixmap_priv->fbo->tex)
             pixmap_priv->fbo->tex =
                 _glamor_create_tex(glamor_priv, pixmap->drawable.width,
-                                   pixmap->drawable.height, format);
+                                   pixmap->drawable.height, format, FALSE);
 
         if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0)
             if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0)
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 6b6e597..ece7dbe 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -415,7 +415,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 }
 
 unsigned int
-glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
+glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear)
 {
     return 0;
 }
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 76f45f5..c2ba434 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -503,6 +503,9 @@
 /* Build glamor's GBM-based EGL support */
 #undef GLAMOR_HAS_GBM
 
+/* Build glamor/gbm has linear support */
+#undef GLAMOR_HAS_GBM_LINEAR
+
 /* byte order */
 #undef X_BYTE_ORDER
 
commit 5c555605386c76be2f02193d434a4617218b67be
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jun 11 14:29:48 2015 +1000

    xf86: restrict when we auto add devices as gpu devices.
    
    Michel pointed out I broke Zaphod with the initial auto add
    gpu devices change,
    
    Fix this, by only auto adding GPU devices if we are screen 0
    and there are no other screens in the layout. Anyone who
    wants to assign GPU devices can specify it in the xorg.conf
    for this use case.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Tested-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index b8ec8a0..2b4df0c 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -123,7 +123,7 @@ static ModuleDefault ModuleDefaults[] = {
 
 /* Forward declarations */
 static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen,
-                         int scrnum, MessageType from);
+                         int scrnum, MessageType from, Bool auto_gpu_device);
 static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor);
 static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device,
                          Bool active, Bool gpu);
@@ -1524,7 +1524,7 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
         else
             scrnum = adjp->adj_scrnum;
         if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum,
-                          X_CONFIG)) {
+                          X_CONFIG, (scrnum == 0 && !adjp->list.next))) {
             do {
                 free(slp[count].screen);
             } while (count--);
@@ -1574,7 +1574,7 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
         FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
         slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
         if (!configScreen(slp[0].screen, screen,
-                          0, X_CONFIG)) {
+                          0, X_CONFIG, TRUE)) {
             free(slp[0].screen);
             free(slp);
             return FALSE;
@@ -1703,7 +1703,7 @@ configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen,
     slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec));
     slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
     slp[1].screen = NULL;
-    if (!configScreen(slp[0].screen, conf_screen, 0, from)) {
+    if (!configScreen(slp[0].screen, conf_screen, 0, from, TRUE)) {
         free(slp);
         return FALSE;
     }
@@ -1768,7 +1768,7 @@ configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor)
 
 static Bool
 configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
-             MessageType from)
+             MessageType from, Bool auto_gpu_device)
 {
     int count = 0;
     XF86ConfDisplayPtr dispptr;
@@ -1825,7 +1825,8 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
         screenp->device = NULL;
     }
 
-    if (conf_screen->num_gpu_devices == 0 && xf86configptr->conf_device_lst) {
+    if (auto_gpu_device && conf_screen->num_gpu_devices == 0 &&
+        xf86configptr->conf_device_lst) {
         XF86ConfDevicePtr sdevice = xf86configptr->conf_device_lst->list.next;
 
         for (i = 0; i < MAX_GPUDEVICES; i++) {
commit 5064ee276fe0f6cebc33ea08e57f1de91f092d88
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Jun 12 15:13:47 2015 +1000

    xf86Rotate: remove unused macros.
    
    These macros aren't used anywhere.
    
    v1.1: drop comment (Aaron)
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 9c00a44..bc1ea21 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -43,12 +43,6 @@
 #include "X11/extensions/dpmsconst.h"
 #include "X11/Xatom.h"
 
-/* borrowed from composite extension, move to Render and publish? */
-
-#define F(x)	IntToxFixed(x)
-
-#define toF(x)	((float) (x) / 65536.0f)
-
 static void
 xf86RotateCrtcRedisplay(xf86CrtcPtr crtc, RegionPtr region)
 {
commit 8218dadd30eb0c87efbac6db5d8e3862a236b6a4
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 9 15:30:22 2015 +1000

    cursor: drop ARGB_CURSOR
    
    I doubt anyone builds with this turned off or has done for a long
    time.
    
    It helps my eyes bleed slightly less when reading the code, I've left
    the define in place as some drivers use it.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/dix/cursor.c b/dix/cursor.c
index 1525857..e459456 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -80,9 +80,7 @@ FreeCursorBits(CursorBitsPtr bits)
         return;
     free(bits->source);
     free(bits->mask);
-#ifdef ARGB_CURSOR
     free(bits->argb);
-#endif
     dixFiniPrivates(bits, PRIVATE_CURSOR_BITS);
     if (bits->refcnt == 0) {
         GlyphSharePtr *prev, this;
@@ -165,7 +163,6 @@ CheckForEmptyMask(CursorBitsPtr bits)
     while (n--)
         if (*(msk++) != 0)
             return;
-#ifdef ARGB_CURSOR
     if (bits->argb) {
         CARD32 *argb = bits->argb;
 
@@ -174,7 +171,6 @@ CheckForEmptyMask(CursorBitsPtr bits)
             if (*argb++ & 0xff000000)
                 return;
     }
-#endif
     bits->emptyMask = TRUE;
 }
 
@@ -259,9 +255,7 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
     dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
         bits->source = psrcbits;
     bits->mask = pmaskbits;
-#ifdef ARGB_CURSOR
     bits->argb = argb;
-#endif
     bits->width = cm->width;
     bits->height = cm->height;
     bits->xhot = cm->xhot;
@@ -400,9 +394,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
         dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS);
         bits->source = srcbits;
         bits->mask = mskbits;
-#ifdef ARGB_CURSOR
         bits->argb = 0;
-#endif
         bits->width = cm.width;
         bits->height = cm.height;
         bits->xhot = cm.xhot;
diff --git a/hw/kdrive/ephyr/ephyrcursor.c b/hw/kdrive/ephyr/ephyrcursor.c
index 852be33..808b3c7 100644
--- a/hw/kdrive/ephyr/ephyrcursor.c
+++ b/hw/kdrive/ephyr/ephyrcursor.c
@@ -100,7 +100,6 @@ ephyrRealizeCoreCursor(EphyrScrPriv *scr, CursorPtr cursor)
     xcb_free_pixmap(conn, mask);
 }
 
-#ifdef ARGB_CURSOR
 static xcb_render_pictformat_t
 get_argb_format(void)
 {
@@ -170,7 +169,6 @@ can_argb_cursor(void)
 
     return v->major_version == 0 && v->minor_version >= 5;
 }
-#endif
 
 static Bool
 ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
@@ -179,11 +177,9 @@ ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
     KdScreenInfo *kscr = pScreenPriv->screen;
     EphyrScrPriv *scr = kscr->driver;
 
-#ifdef ARGB_CURSOR
     if (cursor->bits->argb && can_argb_cursor())
         ephyrRealizeARGBCursor(scr, cursor);
     else
-#endif
     {
         ephyrRealizeCoreCursor(scr, cursor);
     }
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 379a27a..321cde7 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -258,9 +258,7 @@ xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
     CARD32 bits;
     const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
 
-#ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
-#endif
 
     for (y = 0; y < cursor_info->MaxHeight; y++)
         for (x = 0; x < cursor_info->MaxWidth; x++) {
@@ -458,9 +456,7 @@ xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
     CARD8 *cursor_image;
     const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
 
-#ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
-#endif
 
     if (rotation == RR_Rotate_0)
         cursor_image = src;
@@ -632,12 +628,10 @@ xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags)
     cursor_info->HideCursor = xf86_hide_cursors;
     cursor_info->ShowCursor = xf86_show_cursors;
     cursor_info->UseHWCursor = xf86_use_hw_cursor;
-#ifdef ARGB_CURSOR
     if (flags & HARDWARE_CURSOR_ARGB) {
         cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
         cursor_info->LoadCursorARGBCheck = xf86_load_cursor_argb;
     }
-#endif
 
     xf86_config->cursor = NULL;
     xf86_hide_cursors(scrn);
@@ -691,11 +685,9 @@ xf86_reload_cursors(ScreenPtr screen)
         void *src =
             dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey,
                                    screen);
-#ifdef ARGB_CURSOR
         if (cursor->bits->argb && xf86DriverHasLoadCursorARGB(cursor_info))
             xf86DriverLoadCursorARGB(cursor_info, cursor);
         else if (src)
-#endif
             xf86DriverLoadCursorImage(cursor_info, src);
 
         x += scrn->frameX0 + cursor_screen_priv->HotX;
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 04496d5..2a54571 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -340,12 +340,10 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
         if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) &&
             (ScreenPriv->ForceHWCursorCount ||
              ((
-#ifdef ARGB_CURSOR
                cursor->bits->argb &&
                infoPtr->UseHWCursorARGB &&
                (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) ||
               (cursor->bits->argb == 0 &&
-#endif
                (cursor->bits->height <= infoPtr->MaxHeight) &&
                (cursor->bits->width <= infoPtr->MaxWidth) &&
                (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) {
diff --git a/hw/xfree86/ramdac/xf86Cursor.h b/hw/xfree86/ramdac/xf86Cursor.h
index a389a99..8c98bb1 100644
--- a/hw/xfree86/ramdac/xf86Cursor.h
+++ b/hw/xfree86/ramdac/xf86Cursor.h
@@ -19,11 +19,9 @@ typedef struct _xf86CursorInfoRec {
     unsigned char *(*RealizeCursor) (struct _xf86CursorInfoRec *, CursorPtr);
     Bool (*UseHWCursor) (ScreenPtr, CursorPtr);
 
-#ifdef ARGB_CURSOR
     Bool (*UseHWCursorARGB) (ScreenPtr, CursorPtr);
     void (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr);
     Bool (*LoadCursorARGBCheck) (ScrnInfoPtr, CursorPtr);
-#endif
 
 } xf86CursorInfoRec, *xf86CursorInfoPtr;
 
@@ -77,8 +75,6 @@ extern _X_EXPORT void xf86ForceHWCursor(ScreenPtr pScreen, Bool on);
 #define HARDWARE_CURSOR_NIBBLE_SWAPPED			0x00000800
 #define HARDWARE_CURSOR_SHOW_TRANSPARENT		0x00001000
 #define HARDWARE_CURSOR_UPDATE_UNHIDDEN			0x00002000
-#ifdef ARGB_CURSOR
 #define HARDWARE_CURSOR_ARGB				0x00004000
-#endif
 
 #endif                          /* _XF86CURSOR_H */
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index be7154e..84febe0 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -139,9 +139,7 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
     x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
     y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
 
-#ifdef ARGB_CURSOR
     if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
-#endif
         if (!bits) {
             bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
             dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
@@ -151,12 +149,10 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
     if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
         (*infoPtr->HideCursor) (infoPtr->pScrn);
 
-#ifdef ARGB_CURSOR
     if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
         if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
             return FALSE;
     } else
-#endif
     if (bits)
         if (!xf86DriverLoadCursorImage (infoPtr, bits))
             return FALSE;
@@ -213,12 +209,10 @@ xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
                                                xf86CursorScreenKey);
     xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
 
-#ifdef ARGB_CURSOR
     /* recoloring isn't applicable to ARGB cursors and drivers
        shouldn't have to ignore SetCursorColors requests */
     if (pCurs->bits->argb)
         return;
-#endif
 
     if (ScreenPriv->PalettedCursor) {
         xColorItem sourceColor, maskColor;
diff --git a/hw/xquartz/xpr/xprCursor.c b/hw/xquartz/xpr/xprCursor.c
index 4168f7c..5e89348 100644
--- a/hw/xquartz/xpr/xprCursor.c
+++ b/hw/xquartz/xpr/xprCursor.c
@@ -85,7 +85,6 @@ load_cursor(CursorPtr src, int screen)
     hot_x = src->bits->xhot;
     hot_y = src->bits->yhot;
 
-#ifdef ARGB_CURSOR
     if (src->bits->argb != NULL) {
 #if BITMAP_BIT_ORDER == MSBFirst
         rowbytes = src->bits->width * sizeof(CARD32);
@@ -104,7 +103,6 @@ load_cursor(CursorPtr src, int screen)
 #endif
     }
     else
-#endif
     {
         fg_color = 0xFF00 | (src->foreRed >> 8);
         fg_color <<= 16;
diff --git a/include/cursorstr.h b/include/cursorstr.h
index 221cd70..3f306a4 100644
--- a/include/cursorstr.h
+++ b/include/cursorstr.h
@@ -64,9 +64,7 @@ typedef struct _CursorBits {
     unsigned short width, height, xhot, yhot;   /* metrics */
     int refcnt;                 /* can be shared */
     PrivateRec *devPrivates;    /* set by pScr->RealizeCursor */
-#ifdef ARGB_CURSOR
     CARD32 *argb;               /* full-color alpha blended */
-#endif
 } CursorBits, *CursorBitsPtr;
 
 #define CURSOR_BITS_SIZE (sizeof(CursorBits) + dixPrivatesSize(PRIVATE_CURSOR_BITS))
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 50f0dd2..d1da0fd 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -46,9 +46,7 @@ in this Software without prior written authorization from The Open Group.
 #include   "misprite.h"
 #include   "gcstruct.h"
 
-#ifdef ARGB_CURSOR
 #include   "picturestr.h"
-#endif
 
 #include "inputstr.h"
 
@@ -68,9 +66,7 @@ typedef struct {
     GCPtr pSourceGC, pMaskGC;
     GCPtr pSaveGC, pRestoreGC;
     PixmapPtr pSave;
-#ifdef ARGB_CURSOR
     PicturePtr pRootPicture;
-#endif
 } miDCBufferRec, *miDCBufferPtr;
 
 #define miGetDCDevice(dev, screen) \
@@ -86,9 +82,7 @@ typedef struct {
     CloseScreenProcPtr CloseScreen;
     PixmapPtr sourceBits;       /* source bits */
     PixmapPtr maskBits;         /* mask bits */
-#ifdef ARGB_CURSOR
     PicturePtr pPicture;
-#endif
     CursorPtr pCursor;
 } miDCScreenRec, *miDCScreenPtr;
 
@@ -133,11 +127,9 @@ miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBit
         (*pScreen->DestroyPixmap)(pScreenPriv->maskBits);
     pScreenPriv->maskBits = maskBits;
 
-#ifdef ARGB_CURSOR
     if (pScreenPriv->pPicture)
         FreePicture(pScreenPriv->pPicture, 0);
     pScreenPriv->pPicture = pPicture;
-#endif
 
     pScreenPriv->pCursor = pCursor;
 }
@@ -162,7 +154,6 @@ miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
     return TRUE;
 }
 
-#ifdef ARGB_CURSOR
 #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
 
 static PicturePtr
@@ -182,7 +173,6 @@ miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
     *ppPicture = pPicture;
     return pPicture;
 }
-#endif
 
 static Bool
 miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
@@ -195,8 +185,6 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
     if (pScreenPriv->pCursor == pCursor)
         return TRUE;
 
-#ifdef ARGB_CURSOR
-
     if (pCursor->bits->argb) {
         PixmapPtr pPixmap;
         PictFormatPtr pFormat;
@@ -233,7 +221,7 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
         miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture);
         return TRUE;
     }
-#endif
+
     sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
                                            pCursor->bits->height, 1, 0);
     if (!sourceBits)
@@ -373,7 +361,6 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
     pWin = pScreen->root;
     pBuffer = miGetDCDevice(pDev, pScreen);
 
-#ifdef ARGB_CURSOR
     if (pScreenPriv->pPicture) {
         if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
             return FALSE;
@@ -385,7 +372,6 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
                          x, y, pCursor->bits->width, pCursor->bits->height);
     }
     else
-#endif
     {
         miDCPutBits((DrawablePtr) pWin,
                     pBuffer->pSourceGC, pBuffer->pMaskGC,
@@ -486,9 +472,7 @@ miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
         if (!pBuffer->pRestoreGC)
             goto failure;
 
-#ifdef ARGB_CURSOR
         pBuffer->pRootPicture = NULL;
-#endif
 
         /* (re)allocated lazily depending on the cursor size */
         pBuffer->pSave = NULL;
@@ -525,11 +509,9 @@ miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
                 if (pBuffer->pRestoreGC)
                     FreeGC(pBuffer->pRestoreGC, (GContext) 0);
 
-#ifdef ARGB_CURSOR
                 /* If a pRootPicture was allocated for a root window, it
                  * is freed when that root window is destroyed, so don't
                  * free it again here. */
-#endif
 
                 if (pBuffer->pSave)
                     (*pScreen->DestroyPixmap) (pBuffer->pSave);
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index 94d24a8..5619aad 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -306,11 +306,9 @@ CopyCursorToImage(CursorPtr pCursor, CARD32 *image)
     int height = pCursor->bits->height;
     int npixels = width * height;
 
-#ifdef ARGB_CURSOR
     if (pCursor->bits->argb)
         memcpy(image, pCursor->bits->argb, npixels * sizeof(CARD32));
     else
-#endif
     {
         unsigned char *srcLine = pCursor->bits->source;
         unsigned char *mskLine = pCursor->bits->mask;


More information about the xorg-commit mailing list