xserver: Branch 'master' - 3 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Aug 17 18:53:30 PDT 2015


 hw/xfree86/drivers/modesetting/driver.c          |  193 ++++++++++++++---------
 hw/xfree86/drivers/modesetting/driver.h          |   35 ++--
 hw/xfree86/drivers/modesetting/drmmode_display.c |   97 +++++++++--
 hw/xfree86/drivers/modesetting/drmmode_display.h |    5 
 hw/xfree86/drivers/modesetting/modesetting.man   |   18 ++
 hw/xfree86/drivers/modesetting/vblank.c          |   23 +-
 6 files changed, 269 insertions(+), 102 deletions(-)

New commits:
commit 7ecdfbf0af3547295b245efa754123db65cabb43
Merge: bca4f4b a0b4f30
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 17 18:53:25 2015 -0700

    Merge remote-tracking branch 'airlied/modesetting-zaphod'

commit a0b4f30b1f584d2957c9c99e430da5740d2d4ab2
Author: Mario Kleiner <mario.kleiner.de at gmail.com>
Date:   Wed Aug 5 00:08:40 2015 +0200

    modesetting: Add more missing options to man page.
    
    Descriptions for Options PageFlip and SWCursor.
    
    Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/modesetting.man b/hw/xfree86/drivers/modesetting/modesetting.man
index e13a4e2..a42da1c 100644
--- a/hw/xfree86/drivers/modesetting/modesetting.man
+++ b/hw/xfree86/drivers/modesetting/modesetting.man
@@ -41,6 +41,10 @@ The following driver
 .B Options
 are supported:
 .TP
+.BI "Option \*qSWcursor\*q \*q" boolean \*q
+Selects software cursor.  The default is
+.B off.
+.TP
 .BI "Option \*qkmsdev\*q \*q" string \*q
 The framebuffer device to use. Default: /dev/dri/card0.
 .TP
@@ -50,6 +54,10 @@ Enable or disable use of the shadow framebuffer layer.  Default: on.
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 One of \*qglamor\*q or \*qnone\*q.  Default: glamor
 .TP
+.BI "Option \*qPageFlip\*q \*q" boolean \*q
+Enable DRI3 page flipping.  The default is
+.B on.
+.TP
 .BI "Option \*qZaphodHeads\*q \*q" string \*q
 Specify the RandR output(s) to use with zaphod mode for a particular driver
 instance.  If you use this option you must use this option for all instances
commit 19e1dc8f6ea6d7ff5ba4a5caa0e2f40a47879408
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Jul 22 03:56:13 2015 +0100

    modesetting: add zaphod support (v3)
    
    This adds zaphod and ZaphodHeads support
    to the the in-server modesetting driver.
    
    this is based on a request from Mario,
    and on the current radeon driver, along
    with some patches from Mario to bring things
    up to the state of the art in Zaphod.
    
    v2: fixup vblank fd registring.
    v3: squash Mario's fixes.
      modesetting: Allow/Fix use of multiple ZaphodHead outputs per x-screen.
      modesetting: Take shift in crtc positions for ZaphodHeads configs into account.
      modesetting: Add ZaphodHeads description to man page.
    small cleanups (airlied).
    
    Reviewed-and-tested-by: Mario Kleiner <mario.kleiner.de at gmail.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
    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 324b8bd..80abcdf 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -118,24 +118,17 @@ static SymTabRec Chipsets[] = {
     {-1, NULL}
 };
 
-typedef enum {
-    OPTION_SW_CURSOR,
-    OPTION_DEVICE_PATH,
-    OPTION_SHADOW_FB,
-    OPTION_ACCEL_METHOD,
-    OPTION_PAGEFLIP,
-} modesettingOpts;
-
 static const OptionInfoRec Options[] = {
     {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
     {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},
+    {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
     {-1, NULL, OPTV_NONE, {0}, FALSE}
 };
 
-int modesettingEntityIndex = -1;
+int ms_entity_index = -1;
 
 static MODULESETUPPROTO(Setup);
 
@@ -187,6 +180,15 @@ Identify(int flags)
                       Chipsets);
 }
 
+modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn)
+{
+    DevUnion     *pPriv;
+    modesettingPtr ms = modesettingPTR(scrn);
+    pPriv = xf86GetEntityPrivate(ms->pEnt->index,
+                                 ms_entity_index);
+    return pPriv->ptr;
+}
+
 static int
 open_hw(const char *dev)
 {
@@ -374,12 +376,40 @@ ms_platform_probe(DriverPtr driver,
 
     if (probe_hw(path, dev)) {
         scrn = xf86AllocateScreen(driver, scr_flags);
+        if (xf86IsEntitySharable(entity_num))
+            xf86SetEntityShared(entity_num);
         xf86AddEntityToScreen(scrn, entity_num);
 
         ms_setup_scrn_hooks(scrn);
 
         xf86DrvMsg(scrn->scrnIndex, X_INFO,
                    "using drv %s\n", path ? path : "default device");
+
+        {
+            DevUnion *pPriv;
+            EntityInfoPtr pEnt;
+            modesettingEntPtr pMSEnt;
+
+            xf86SetEntitySharable(entity_num);
+
+            if (ms_entity_index == -1)
+                ms_entity_index = xf86AllocateEntityPrivateIndex();
+
+            pEnt = xf86GetEntityInfo(entity_num);
+            pPriv = xf86GetEntityPrivate(pEnt->index,
+                                         ms_entity_index);
+
+            xf86SetEntityInstanceForScreen(scrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
+
+            if (!pPriv->ptr) {
+                pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1);
+                pMSEnt = pPriv->ptr;
+            } else {
+                pMSEnt = pPriv->ptr;
+            }
+            pMSEnt->platform_dev = dev;
+        }
+
     }
 
     return scrn != NULL;
@@ -596,19 +626,25 @@ FreeRec(ScrnInfoPtr pScrn)
     pScrn->driverPrivate = NULL;
 
     if (ms->fd > 0) {
+        modesettingEntPtr ms_ent;
         int ret;
 
-        if (ms->pEnt->location.type == BUS_PCI)
-            ret = drmClose(ms->fd);
-        else
+        ms_ent = ms_ent_priv(pScrn);
+        ms_ent->fd_ref--;
+        if (!ms_ent->fd_ref) {
+            if (ms->pEnt->location.type == BUS_PCI)
+                ret = drmClose(ms->fd);
+            else
 #ifdef XF86_PDEV_SERVER_FD
-        if (!(ms->pEnt->location.type == BUS_PLATFORM &&
-                  (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
+                if (!(ms->pEnt->location.type == BUS_PLATFORM &&
+                      (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)))
 #endif
-            ret = close(ms->fd);
-        (void) ret;
+                    ret = close(ms->fd);
+            (void) ret;
+            ms_ent->fd = 0;
+        }
     }
-    free(ms->Options);
+    free(ms->drmmode.Options);
     free(ms);
 
 }
@@ -617,7 +653,7 @@ static void
 try_enable_glamor(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
-    const char *accel_method_str = xf86GetOptValString(ms->Options,
+    const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options,
                                                        OPTION_ACCEL_METHOD);
     Bool do_glamor = (!accel_method_str ||
                       strcmp(accel_method_str, "glamor") == 0);
@@ -659,60 +695,26 @@ try_enable_glamor(ScrnInfoPtr pScrn)
 #endif
 
 static Bool
-PreInit(ScrnInfoPtr pScrn, int flags)
+ms_get_drm_master_fd(ScrnInfoPtr pScrn)
 {
-    modesettingPtr ms;
-    rgb defaultWeight = { 0, 0, 0 };
     EntityInfoPtr pEnt;
-    EntPtr msEnt = NULL;
+    modesettingPtr ms;
+    modesettingEntPtr ms_ent;
     char *BusID = NULL;
-    const char *devicename;
-    uint64_t value = 0;
-    int ret;
-    int bppflags;
-    int defaultdepth, defaultbpp;
-
-    if (pScrn->numEntities != 1)
-        return FALSE;
-
-    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
-
-    if (flags & PROBE_DETECT) {
-        return FALSE;
-    }
-
-    /* Allocate driverPrivate */
-    if (!GetRec(pScrn))
-        return FALSE;
 
     ms = modesettingPTR(pScrn);
-    ms->SaveGeneration = -1;
-    ms->pEnt = pEnt;
-
-    pScrn->displayWidth = 640;  /* default it */
+    ms_ent = ms_ent_priv(pScrn);
 
-    /* Allocate an entity private if necessary */
-    if (xf86IsEntityShared(pScrn->entityList[0])) {
-        msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
-                                     modesettingEntityIndex)->ptr;
-        ms->entityPrivate = msEnt;
-    }
-    else
-        ms->entityPrivate = NULL;
+    pEnt = ms->pEnt;
 
-    if (xf86IsEntityShared(pScrn->entityList[0])) {
-        if (xf86IsPrimInitDone(pScrn->entityList[0])) {
-            /* do something */
-        }
-        else {
-            xf86SetPrimInitDone(pScrn->entityList[0]);
-        }
+    if (ms_ent->fd) {
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                   " reusing fd for second head\n");
+        ms->fd = ms_ent->fd;
+        ms_ent->fd_ref++;
+        return TRUE;
     }
 
-    pScrn->monitor = pScrn->confScreen->monitor;
-    pScrn->progClock = TRUE;
-    pScrn->rgbBits = 8;
-
 #if XSERVER_PLATFORM_BUS
     if (pEnt->location.type == BUS_PLATFORM) {
 #ifdef XF86_PDEV_SERVER_FD
@@ -749,12 +751,61 @@ PreInit(ScrnInfoPtr pScrn, int flags)
         ms->fd = drmOpen(NULL, BusID);
     }
     else {
+        const char *devicename;
         devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev");
         ms->fd = open_hw(devicename);
     }
     if (ms->fd < 0)
         return FALSE;
 
+    ms_ent->fd = ms->fd;
+    ms_ent->fd_ref = 1;
+    return TRUE;
+}
+
+static Bool
+PreInit(ScrnInfoPtr pScrn, int flags)
+{
+    modesettingPtr ms;
+    rgb defaultWeight = { 0, 0, 0 };
+    EntityInfoPtr pEnt;
+    uint64_t value = 0;
+    int ret;
+    int bppflags;
+    int defaultdepth, defaultbpp;
+
+    if (pScrn->numEntities != 1)
+        return FALSE;
+
+    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+    if (flags & PROBE_DETECT) {
+        return FALSE;
+    }
+
+    /* Allocate driverPrivate */
+    if (!GetRec(pScrn))
+        return FALSE;
+
+    ms = modesettingPTR(pScrn);
+    ms->SaveGeneration = -1;
+    ms->pEnt = pEnt;
+    ms->drmmode.is_secondary = FALSE;
+    pScrn->displayWidth = 640;  /* default it */
+
+    if (xf86IsEntityShared(pScrn->entityList[0])) {
+        if (xf86IsPrimInitDone(pScrn->entityList[0]))
+            ms->drmmode.is_secondary = TRUE;
+        else
+            xf86SetPrimInitDone(pScrn->entityList[0]);
+    }
+
+    pScrn->monitor = pScrn->confScreen->monitor;
+    pScrn->progClock = TRUE;
+    pScrn->rgbBits = 8;
+
+    if (!ms_get_drm_master_fd(pScrn))
+        return FALSE;
     ms->drmmode.fd = ms->fd;
 
     pScrn->capabilities = 0;
@@ -794,17 +845,17 @@ PreInit(ScrnInfoPtr pScrn, int flags)
 
     /* Process the options */
     xf86CollectOptions(pScrn, NULL);
-    if (!(ms->Options = malloc(sizeof(Options))))
+    if (!(ms->drmmode.Options = malloc(sizeof(Options))))
         return FALSE;
-    memcpy(ms->Options, Options, sizeof(Options));
-    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
+    memcpy(ms->drmmode.Options, Options, sizeof(Options));
+    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options);
 
     if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
         return FALSE;
     if (!xf86SetDefaultVisual(pScrn, -1))
         return FALSE;
 
-    if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
+    if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) {
         ms->drmmode.sw_cursor = TRUE;
     }
 
@@ -823,7 +874,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
 
     if (ms->drmmode.glamor) {
         ms->drmmode.pageflip =
-            xf86ReturnOptValBool(ms->Options, OPTION_PAGEFLIP, TRUE);
+            xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
     } else {
         Bool prefer_shadow = TRUE;
 
@@ -832,7 +883,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
             prefer_shadow = !!value;
         }
 
-        ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->Options,
+        ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->drmmode.Options,
                                                          OPTION_SHADOW_FB,
                                                          prefer_shadow);
 
@@ -1277,6 +1328,10 @@ CloseScreen(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     modesettingPtr ms = modesettingPTR(pScrn);
+    modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
+
+    /* Clear mask of assigned crtc's in this generation */
+    ms_ent->assigned_crtcs = 0;
 
 #ifdef GLAMOR
     if (ms->drmmode.glamor) {
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 9ae4966..14137c1 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -43,13 +43,28 @@
 
 #include "drmmode_display.h"
 #define DRV_ERROR(msg)	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
-
-typedef struct {
-    int lastInstance;
-    int refCount;
-    ScrnInfoPtr pScrn_1;
-    ScrnInfoPtr pScrn_2;
-} EntRec, *EntPtr;
+#define MS_LOGLEVEL_DEBUG 4
+
+typedef enum {
+    OPTION_SW_CURSOR,
+    OPTION_DEVICE_PATH,
+    OPTION_SHADOW_FB,
+    OPTION_ACCEL_METHOD,
+    OPTION_PAGEFLIP,
+    OPTION_ZAPHOD_HEADS,
+} modesettingOpts;
+
+typedef struct
+{
+    int fd;
+    int fd_ref;
+    unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */
+    int fd_wakeup_ref;
+    unsigned int assigned_crtcs;
+#ifdef XSERVER_PLATFORM_BUS
+    struct xf86_platform_device *platform_dev;
+#endif
+} modesettingEntRec, *modesettingEntPtr;
 
 typedef void (*ms_drm_handler_proc)(uint64_t frame,
                                     uint64_t usec,
@@ -74,8 +89,6 @@ struct ms_drm_queue {
 typedef struct _modesettingRec {
     int fd;
 
-    EntPtr entityPrivate;
-
     int Chipset;
     EntityInfoPtr pEnt;
 #if XSERVER_LIBPCIACCESS
@@ -88,9 +101,6 @@ typedef struct _modesettingRec {
     Bool noAccel;
     CloseScreenProcPtr CloseScreen;
 
-    /* Broken-out options. */
-    OptionInfoPtr Options;
-
     unsigned int SaveGeneration;
 
     CreateScreenResourcesProcPtr createScreenResources;
@@ -114,6 +124,7 @@ typedef struct _modesettingRec {
 } modesettingRec, *modesettingPtr;
 
 #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
+modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn);
 
 uint32_t ms_drm_queue_alloc(xf86CrtcPtr crtc,
                             void *data,
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 6a13660..4d8892f 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -52,6 +52,39 @@
 
 static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
 
+static Bool
+drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name)
+{
+    int i = 0;
+    char s1[20];
+
+    do {
+        switch(*s) {
+        case ',':
+            s1[i] = '\0';
+            i = 0;
+            if (strcmp(s1, output_name) == 0)
+                return TRUE;
+            break;
+        case ' ':
+        case '\t':
+        case '\n':
+        case '\r':
+            break;
+        default:
+            s1[i] = *s;
+            i++;
+            break;
+        }
+    } while(*s++);
+
+    s1[i] = '\0';
+    if (strcmp(s1, output_name) == 0)
+        return TRUE;
+
+    return FALSE;
+}
+
 int
 drmmode_bo_destroy(drmmode_ptr drmmode, drmmode_bo *bo)
 {
@@ -788,15 +821,16 @@ drmmode_crtc_vblank_pipe(int crtc_id)
         return 0;
 }
 
-static void
+static unsigned int
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
 {
     xf86CrtcPtr crtc;
     drmmode_crtc_private_ptr drmmode_crtc;
+    modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
 
     crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
     if (crtc == NULL)
-        return;
+        return 0;
 
     drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
     drmmode_crtc->mode_crtc =
@@ -804,6 +838,13 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
     drmmode_crtc->drmmode = drmmode;
     drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num);
     crtc->driver_private = drmmode_crtc;
+
+    /* Mark num'th crtc as in use on this device. */
+    ms_ent->assigned_crtcs |= (1 << num);
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
+                   "Allocated crtc nr. %d to this screen.\n", num);
+
+    return 1;
 }
 
 static xf86OutputStatus
@@ -1345,8 +1386,8 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
         snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
 }
 
-static void
-drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic)
+static unsigned int
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic, int crtcshift)
 {
     xf86OutputPtr output;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -1357,11 +1398,11 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
     char name[32];
     int i;
     drmModePropertyBlobPtr path_blob = NULL;
-
+    const char *s;
     koutput =
         drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
     if (!koutput)
-        return;
+        return 0;
 
     for (i = 0; i < koutput->count_props; i++) {
         props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
@@ -1392,7 +1433,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
             drmmode_output = output->driver_private;
             drmmode_output->output_id = mode_res->connectors[num];
             drmmode_output->mode_output = koutput;
-            return;
+            return 1;
         }
     }
 
@@ -1408,6 +1449,18 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
         }
     }
 
+    if (xf86IsEntityShared(pScrn->entityList[0])) {
+        if ((s = xf86GetOptValString(drmmode->Options, OPTION_ZAPHOD_HEADS))) {
+            if (!drmmode_zaphod_string_matches(pScrn, s, name))
+                goto out_free_encoders;
+        } else {
+            if (!drmmode->is_secondary && (num != 0))
+                goto out_free_encoders;
+            else if (drmmode->is_secondary && (num != 1))
+                goto out_free_encoders;
+        }
+    }
+
     output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
     if (!output) {
         goto out_free_encoders;
@@ -1433,7 +1486,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 
     output->possible_crtcs = 0x7f;
     for (i = 0; i < koutput->count_encoders; i++) {
-        output->possible_crtcs &= kencoders[i]->possible_crtcs;
+        output->possible_crtcs &= kencoders[i]->possible_crtcs >> crtcshift;
     }
     /* work out the possible clones later */
     output->possible_clones = 0;
@@ -1452,7 +1505,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 
     if (dynamic)
         output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
-    return;
+    return 1;
+
  out_free_encoders:
     if (kencoders) {
         for (i = 0; i < koutput->count_encoders; i++)
@@ -1461,6 +1515,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
     }
     drmModeFreeConnector(koutput);
 
+    return 0;
 }
 
 static uint32_t
@@ -1682,10 +1737,13 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 Bool
 drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 {
+    modesettingEntPtr ms_ent = ms_ent_priv(pScrn);
     int i;
     int ret;
     uint64_t value = 0;
+    unsigned int crtcs_needed = 0;
     drmModeResPtr mode_res;
+    int crtcshift;
 
     /* check for dumb capability */
     ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value);
@@ -1703,15 +1761,26 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
     if (!mode_res)
         return FALSE;
 
+    crtcshift = ffs(ms_ent->assigned_crtcs ^ 0xffffffff) - 1;
+    for (i = 0; i < mode_res->count_connectors; i++)
+        crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE,
+                                            crtcshift);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
+                   "Up to %d crtcs needed for screen.\n", crtcs_needed);
+
     xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width,
                          mode_res->max_height);
     for (i = 0; i < mode_res->count_crtcs; i++)
         if (!xf86IsEntityShared(pScrn->entityList[0]) ||
-            pScrn->confScreen->device->screen == i)
-            drmmode_crtc_init(pScrn, drmmode, mode_res, i);
+            (crtcs_needed && !(ms_ent->assigned_crtcs & (1 << i))))
+            crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
 
-    for (i = 0; i < mode_res->count_connectors; i++)
-        drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE);
+    /* All ZaphodHeads outputs provided with matching crtcs? */
+    if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                   "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
+                   crtcs_needed);
 
     /* workout clones */
     drmmode_clones_init(pScrn, drmmode, mode_res);
@@ -1941,7 +2010,7 @@ drmmode_handle_uevents(int fd, void *closure)
             continue;
 
         changed = TRUE;
-        drmmode_output_init(scrn, drmmode, mode_res, i, 1);
+        drmmode_output_init(scrn, drmmode, mode_res, i, TRUE, 0);
     }
 
     if (changed) {
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index fe363c5..fca68a6 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -60,6 +60,9 @@ typedef struct {
     drmmode_bo front_bo;
     Bool sw_cursor;
 
+    /* Broken-out options. */
+    OptionInfoPtr Options;
+
     Bool glamor;
     Bool shadow_enable;
     /** Is Option "PageFlip" enabled? */
@@ -82,6 +85,8 @@ typedef struct {
     DevPrivateKeyRec pixmapPrivateKeyRec;
 
     Bool reverse_prime_offload_mode;
+
+    Bool is_secondary;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
diff --git a/hw/xfree86/drivers/modesetting/modesetting.man b/hw/xfree86/drivers/modesetting/modesetting.man
index 9cb27d7..e13a4e2 100644
--- a/hw/xfree86/drivers/modesetting/modesetting.man
+++ b/hw/xfree86/drivers/modesetting/modesetting.man
@@ -50,6 +50,16 @@ Enable or disable use of the shadow framebuffer layer.  Default: on.
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 One of \*qglamor\*q or \*qnone\*q.  Default: glamor
 .TP
+.BI "Option \*qZaphodHeads\*q \*q" string \*q
+Specify the RandR output(s) to use with zaphod mode for a particular driver
+instance.  If you use this option you must use this option for all instances
+of the driver.
+.br
+For example:
+.B
+Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q
+will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
+.TP
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__),
 X(__miscmansuffix__)
diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c
index 0b7bf9d..77e0848 100644
--- a/hw/xfree86/drivers/modesetting/vblank.c
+++ b/hw/xfree86/drivers/modesetting/vblank.c
@@ -381,7 +381,7 @@ ms_vblank_screen_init(ScreenPtr screen)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     modesettingPtr ms = modesettingPTR(scrn);
-
+    modesettingEntPtr ms_ent = ms_ent_priv(scrn);
     xorg_list_init(&ms_drm_queue);
 
     ms->event_context.version = DRM_EVENT_CONTEXT_VERSION;
@@ -392,9 +392,14 @@ ms_vblank_screen_init(ScreenPtr screen)
      * feedback on every server generation, so perform the
      * registration within ScreenInit and not PreInit.
      */
-    AddGeneralSocket(ms->fd);
-    RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
-                                   ms_drm_wakeup_handler, screen);
+    if (ms_ent->fd_wakeup_registered != serverGeneration) {
+        AddGeneralSocket(ms->fd);
+        RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+                                       ms_drm_wakeup_handler, screen);
+        ms_ent->fd_wakeup_registered = serverGeneration;
+        ms_ent->fd_wakeup_ref = 1;
+    } else
+        ms_ent->fd_wakeup_ref++;
 
     return TRUE;
 }
@@ -404,10 +409,14 @@ ms_vblank_close_screen(ScreenPtr screen)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     modesettingPtr ms = modesettingPTR(scrn);
+    modesettingEntPtr ms_ent = ms_ent_priv(scrn);
 
     ms_drm_abort_scrn(scrn);
 
-    RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
-                                 ms_drm_wakeup_handler, screen);
-    RemoveGeneralSocket(ms->fd);
+    if (ms_ent->fd_wakeup_registered == serverGeneration &&
+        !--ms_ent->fd_wakeup_ref) {
+        RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+                                     ms_drm_wakeup_handler, screen);
+        RemoveGeneralSocket(ms->fd);
+    }
 }


More information about the xorg-commit mailing list