[PATCH 07/36] xfree86: add DDX gpu screen support. (v3)

Dave Airlie airlied at gmail.com
Thu Jul 5 08:21:08 PDT 2012


From: Dave Airlie <airlied at redhat.com>

This just adds the structures and interfaces required for adding/deleteing
gpu screens at the DDX level. The platform probe can pass a new flag
to the driver, so they can call xf86AllocateScreen and pass back the new
gpu screen flag.

It also calls the gpu screens preinit and screeninit routines at
startup.

v2: fix delete screen use after free.

v3: split out pScrn into separate patch

Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 hw/xfree86/common/xf86.h        |    3 ++
 hw/xfree86/common/xf86Bus.c     |    4 ++
 hw/xfree86/common/xf86Globals.c |    2 +
 hw/xfree86/common/xf86Helper.c  |   98 ++++++++++++++++++++++++++++++---------
 hw/xfree86/common/xf86Init.c    |   42 +++++++++++++++++
 hw/xfree86/common/xf86Priv.h    |    2 +
 hw/xfree86/common/xf86str.h     |    5 +-
 7 files changed, 132 insertions(+), 24 deletions(-)

diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index 88a219c..6116985 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -465,4 +465,7 @@ extern _X_EXPORT ScreenPtr xf86ScrnToScreen(ScrnInfoPtr pScrn);
 
 #define XF86_SCRN_INTERFACE 1 /* define for drivers to use in api compat */
 
+/* flags passed to xf86 allocate screen */
+#define XF86_ALLOCATE_GPU_SCREEN 1
+
 #endif                          /* _XF86_H */
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index d0cfb2b..6de8409 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -189,6 +189,10 @@ xf86BusConfig(void)
         }
     }
 
+    /* bind GPU conf screen to protocol screen 0 */
+    for (i = 0; i < xf86NumGPUScreens; i++)
+        xf86GPUScreens[i]->confScreen = xf86Screens[0]->confScreen;
+
     /* If no screens left, return now.  */
     if (xf86NumScreens == 0) {
         xf86Msg(X_ERROR,
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 0071004..bb08917 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -51,6 +51,7 @@ DevPrivateKeyRec xf86CreateRootWindowKeyRec;
 DevPrivateKeyRec xf86ScreenKeyRec;
 
 ScrnInfoPtr *xf86Screens = NULL;        /* List of ScrnInfos */
+ScrnInfoPtr *xf86GPUScreens = NULL;        /* List of ScrnInfos */
 
 const unsigned char byte_reversed[256] = {
     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
@@ -153,6 +154,7 @@ int xf86NumDrivers = 0;
 InputDriverPtr *xf86InputDriverList = NULL;
 int xf86NumInputDrivers = 0;
 int xf86NumScreens = 0;
+int xf86NumGPUScreens = 0;
 
 const char *xf86VisualNames[] = {
     "StaticGray",
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 18f30b7..f681a85 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -169,15 +169,28 @@ xf86AllocateScreen(DriverPtr drv, int flags)
     int i;
     ScrnInfoPtr pScrn;
 
-    if (xf86Screens == NULL)
-        xf86NumScreens = 0;
-
-    i = xf86NumScreens++;
-    xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
-    xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
-    pScrn = xf86Screens[i];
-    pScrn->scrnIndex = i;      /* Changes when a screen is removed */
-    pScrn->origIndex = i;      /* This never changes */
+    if (flags & XF86_ALLOCATE_GPU_SCREEN) {
+        if (xf86GPUScreens == NULL)
+            xf86NumGPUScreens = 0;
+        i = xf86NumGPUScreens++;
+        xf86GPUScreens = xnfrealloc(xf86GPUScreens, xf86NumGPUScreens * sizeof(ScrnInfoPtr));
+        xf86GPUScreens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
+        pScrn = xf86GPUScreens[i];
+        pScrn->scrnIndex = i + GPU_SCREEN_OFFSET;      /* Changes when a screen is removed */
+        pScrn->is_gpu = TRUE;
+    } else {
+        if (xf86Screens == NULL)
+            xf86NumScreens = 0;
+
+        i = xf86NumScreens++;
+        xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
+        xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
+        pScrn = xf86Screens[i];
+
+        pScrn->scrnIndex = i;      /* Changes when a screen is removed */
+    }
+
+    pScrn->origIndex = pScrn->scrnIndex;      /* This never changes */
     pScrn->privates = xnfcalloc(sizeof(DevUnion), xf86ScrnInfoPrivateCount);
     /*
      * EnableDisableFBAccess now gets initialized in InitOutput()
@@ -203,10 +216,17 @@ xf86DeleteScreen(ScrnInfoPtr pScrn)
 {
     int i;
     int scrnIndex;
-
-    /* First check if the screen is valid */
-    if (xf86NumScreens == 0 || xf86Screens == NULL)
-        return;
+    Bool is_gpu = FALSE;
+    if (pScrn->is_gpu) {
+        /* First check if the screen is valid */
+        if (xf86NumGPUScreens == 0 || xf86GPUScreens == NULL)
+            return;
+        is_gpu = TRUE;
+    } else {
+        /* First check if the screen is valid */
+        if (xf86NumScreens == 0 || xf86Screens == NULL)
+            return;
+    }
 
     if (!pScrn)
         return;
@@ -238,12 +258,23 @@ xf86DeleteScreen(ScrnInfoPtr pScrn)
 
     /* Move the other entries down, updating their scrnIndex fields */
 
-    xf86NumScreens--;
+    if (is_gpu) {
+        xf86NumGPUScreens--;
+        scrnIndex -= GPU_SCREEN_OFFSET;
+        for (i = scrnIndex; i < xf86NumGPUScreens; i++) {
+            xf86GPUScreens[i] = xf86GPUScreens[i + 1];
+            xf86GPUScreens[i]->scrnIndex = i + GPU_SCREEN_OFFSET;
+            /* Also need to take care of the screen layout settings */
+        }
+    }
+    else {
+        xf86NumScreens--;
 
-    for (i = scrnIndex; i < xf86NumScreens; i++) {
-        xf86Screens[i] = xf86Screens[i + 1];
-        xf86Screens[i]->scrnIndex = i;
-        /* Also need to take care of the screen layout settings */
+        for (i = scrnIndex; i < xf86NumScreens; i++) {
+            xf86Screens[i] = xf86Screens[i + 1];
+            xf86Screens[i]->scrnIndex = i;
+            /* Also need to take care of the screen layout settings */
+        }
     }
 }
 
@@ -267,6 +298,14 @@ xf86AllocateScrnInfoPrivateIndex(void)
         memset(&nprivs[idx], 0, sizeof(DevUnion));
         pScr->privates = nprivs;
     }
+    for (i = 0; i < xf86NumGPUScreens; i++) {
+        pScr = xf86GPUScreens[i];
+        nprivs = xnfrealloc(pScr->privates,
+                            xf86ScrnInfoPrivateCount * sizeof(DevUnion));
+        /* Zero the new private */
+        memset(&nprivs[idx], 0, sizeof(DevUnion));
+        pScr->privates = nprivs;
+    }
     return idx;
 }
 
@@ -1059,6 +1098,11 @@ xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
         xf86Screens[scrnIndex]->name)
         LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
                           xf86Screens[scrnIndex]->name, scrnIndex);
+    else if (scrnIndex >= GPU_SCREEN_OFFSET &&
+             scrnIndex < GPU_SCREEN_OFFSET + xf86NumGPUScreens &&
+             xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name)
+        LogHdrMessageVerb(type, verb, format, args, "%s(G%d): ",
+                          xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name, scrnIndex - GPU_SCREEN_OFFSET);
     else
         LogVMessageVerb(type, verb, format, args);
 }
@@ -1834,13 +1878,23 @@ xf86MotionHistoryAllocate(InputInfoPtr pInfo)
 ScrnInfoPtr
 xf86ScreenToScrn(ScreenPtr pScreen)
 {
-    assert(pScreen->myNum < xf86NumScreens);
-    return xf86Screens[pScreen->myNum];
+    if (pScreen->isGPU) {
+        assert(pScreen->myNum - GPU_SCREEN_OFFSET < xf86NumGPUScreens);
+        return xf86GPUScreens[pScreen->myNum - GPU_SCREEN_OFFSET];
+    } else {
+        assert(pScreen->myNum < xf86NumScreens);
+        return xf86Screens[pScreen->myNum];
+    }
 }
 
 ScreenPtr
 xf86ScrnToScreen(ScrnInfoPtr pScrn)
 {
-    assert(pScrn->scrnIndex < screenInfo.numScreens);
-    return screenInfo.screens[pScrn->scrnIndex];
+    if (pScrn->is_gpu) {
+        assert(pScrn->scrnIndex - GPU_SCREEN_OFFSET < screenInfo.numGPUScreens);
+        return screenInfo.gpuscreens[pScrn->scrnIndex - GPU_SCREEN_OFFSET];
+    } else {
+        assert(pScrn->scrnIndex < screenInfo.numScreens);
+        return screenInfo.screens[pScrn->scrnIndex];
+    }
 }
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index ca6efd4..a60cf38 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -593,6 +593,18 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
             if (!xf86Screens[i]->configured)
                 xf86DeleteScreen(xf86Screens[i--]);
 
+        for (i = 0; i < xf86NumGPUScreens; i++) {
+            xf86VGAarbiterScrnInit(xf86GPUScreens[i]);
+            xf86VGAarbiterLock(xf86GPUScreens[i]);
+            if (xf86GPUScreens[i]->PreInit &&
+                xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0))
+                xf86GPUScreens[i]->configured = TRUE;
+            xf86VGAarbiterUnlock(xf86GPUScreens[i]);
+        }
+        for (i = 0; i < xf86NumGPUScreens; i++)
+            if (!xf86GPUScreens[i]->configured)
+                xf86DeleteScreen(xf86GPUScreens[i--]);
+
         /*
          * If no screens left, return now.
          */
@@ -818,6 +830,36 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
         !dixRegisterPrivateKey(&xf86CreateRootWindowKeyRec, PRIVATE_SCREEN, 0))
         FatalError("Cannot register DDX private keys");
 
+    for (i = 0; i < xf86NumGPUScreens; i++) {
+        ScrnInfoPtr pScrn = xf86GPUScreens[i];
+        xf86VGAarbiterLock(pScrn);
+
+        /*
+         * Almost everything uses these defaults, and many of those that
+         * don't, will wrap them.
+         */
+        pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
+#ifdef XFreeXDGA
+        pScrn->SetDGAMode = xf86SetDGAMode;
+#endif
+        pScrn->DPMSSet = NULL;
+        pScrn->LoadPalette = NULL;
+        pScrn->SetOverscan = NULL;
+        pScrn->DriverFunc = NULL;
+        pScrn->pScreen = NULL;
+        scr_index = AddGPUScreen(pScrn->ScreenInit, argc, argv);
+        xf86VGAarbiterUnlock(pScrn);
+        if (scr_index == i) {
+            dixSetPrivate(&screenInfo.gpuscreens[scr_index]->devPrivates,
+                          xf86ScreenKey, xf86GPUScreens[i]);
+            pScrn->pScreen = screenInfo.gpuscreens[scr_index];
+            /* The driver should set this, but make sure it is set anyway */
+            pScrn->vtSema = TRUE;
+        } else {
+            FatalError("AddScreen/ScreenInit failed for gpu driver %d %d\n", i, scr_index);
+        }
+    }
+
     for (i = 0; i < xf86NumScreens; i++) {
         xf86VGAarbiterLock(xf86Screens[i]);
         /*
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 42a3b30..c9f2e7e 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -95,6 +95,8 @@ extern _X_EXPORT Bool xorgHWAccess;
 
 extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
 
+extern ScrnInfoPtr *xf86GPUScreens;      /* List of pointers to ScrnInfoRecs */
+extern int xf86NumGPUScreens;
 #ifndef DEFAULT_VERBOSE
 #define DEFAULT_VERBOSE		0
 #endif
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index e12dcc4..6bd6a62 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/hw/xfree86/common/xf86str.h
@@ -332,9 +332,9 @@ typedef struct _DriverRec {
 
 /*
  * platform probe flags
- * no flags are defined yet - but drivers should fail to load if a flag they
- * don't understand is passed.
  */
+#define PLATFORM_PROBE_GPU_SCREEN 1
+
 /*
  *  AddDriver flags
  */
@@ -813,6 +813,7 @@ typedef struct _ScrnInfoRec {
      */
     funcPointer reservedFuncs[NUM_RESERVED_FUNCS];
 
+    Bool is_gpu;
 } ScrnInfoRec;
 
 typedef struct {
-- 
1.7.10.2



More information about the xorg-devel mailing list