[PATCH 05/36] dix: introduce gpu screens. (v4)

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


From: Dave Airlie <airlied at redhat.com>

This patch introduces gpu screens into screenInfo. It adds interfaces
for adding and removing gpu screens, along with adding private fixup,
block handler support, and scratch pixmap init.

GPU screens have a myNum that is offset by GPU_SCREEN_OFFSET (256),
this is used for logging etc.

RemoveGPUScreen isn't used until "xfree86: add platform bus hotplug support".

v2: no glyph pictures for GPU screens for now.
v3: introduce MAXGPUSCREENS, fix return value check
v4: fixup myNum when renumbering screens (ajax)

Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 dix/dispatch.c       |   76 +++++++++++++++++++++++++++++++++-
 dix/dixutils.c       |    6 +++
 dix/main.c           |   15 +++++++
 dix/privates.c       |  111 ++++++++++++++++++++++++++++----------------------
 include/misc.h       |    4 ++
 include/screenint.h  |    9 ++++
 include/scrnintstr.h |    4 ++
 render/glyph.c       |    2 +
 8 files changed, 177 insertions(+), 50 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 39d791d..d229667 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3724,7 +3724,7 @@ with its screen number, a pointer to its ScreenRec, argc, and argv.
 
 */
 
-static int init_screen(ScreenPtr pScreen, int i)
+static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
 {
     int scanlinepad, format, depth, bitsPerPixel, j, k;
 
@@ -3734,6 +3734,10 @@ static int init_screen(ScreenPtr pScreen, int i)
         return -1;
     }
     pScreen->myNum = i;
+    if (gpu) {
+        pScreen->myNum += GPU_SCREEN_OFFSET;
+        pScreen->isGPU = TRUE;
+    }
     pScreen->totalPixmapSize = 0;       /* computed in CreateScratchPixmapForScreen */
     pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
     pScreen->CreateScreenResources = 0;
@@ -3790,7 +3794,7 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
     if (!pScreen)
         return -1;
 
-    ret = init_screen(pScreen, i);
+    ret = init_screen(pScreen, i, FALSE);
     if (ret != 0) {
         free(pScreen);
         return ret;
@@ -3820,3 +3824,71 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
 
     return i;
 }
+
+int
+AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+                              int /*argc */ ,
+                              char **      /*argv */
+                              ),
+             int argc, char **argv)
+{
+    int i;
+    ScreenPtr pScreen;
+    Bool ret;
+
+    i = screenInfo.numGPUScreens;
+    if (i == MAXGPUSCREENS)
+        return -1;
+
+    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
+    if (!pScreen)
+        return -1;
+
+    ret = init_screen(pScreen, i, TRUE);
+    if (ret != 0) {
+        free(pScreen);
+        return ret;
+    }
+
+    /* This is where screen specific stuff gets initialized.  Load the
+       screen structure, call the hardware, whatever.
+       This is also where the default colormap should be allocated and
+       also pixel values for blackPixel, whitePixel, and the cursor
+       Note that InitScreen is NOT allowed to modify argc, argv, or
+       any of the strings pointed to by argv.  They may be passed to
+       multiple screens.
+     */
+    screenInfo.gpuscreens[i] = pScreen;
+    screenInfo.numGPUScreens++;
+    if (!(*pfnInit) (pScreen, argc, argv)) {
+        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+        free(pScreen);
+        screenInfo.numGPUScreens--;
+        return -1;
+    }
+
+    update_desktop_dimensions();
+
+    dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
+                                0);
+
+    return i;
+}
+
+void
+RemoveGPUScreen(ScreenPtr pScreen)
+{
+    int idx, j;
+    if (!pScreen->isGPU)
+        return;
+
+    idx = pScreen->myNum - GPU_SCREEN_OFFSET;
+    for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
+        screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
+        screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
+    }
+    screenInfo.numGPUScreens--;
+
+    free(pScreen);
+
+}
diff --git a/dix/dixutils.c b/dix/dixutils.c
index b249a81..3f24629 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -386,6 +386,9 @@ BlockHandler(pointer pTimeout, pointer pReadmask)
     for (i = 0; i < screenInfo.numScreens; i++)
         (*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i],
                                                 pTimeout, pReadmask);
+    for (i = 0; i < screenInfo.numGPUScreens; i++)
+        (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i],
+                                                   pTimeout, pReadmask);
     for (i = 0; i < numHandlers; i++)
         if (!handlers[i].deleted)
             (*handlers[i].BlockHandler) (handlers[i].blockData,
@@ -422,6 +425,9 @@ WakeupHandler(int result, pointer pReadmask)
     for (i = 0; i < screenInfo.numScreens; i++)
         (*screenInfo.screens[i]->WakeupHandler) (screenInfo.screens[i],
                                                  result, pReadmask);
+    for (i = 0; i < screenInfo.numGPUScreens; i++)
+        (*screenInfo.gpuscreens[i]->WakeupHandler) (screenInfo.gpuscreens[i],
+                                                    result, pReadmask);
     if (handlerDeleted) {
         for (i = 0; i < numHandlers;)
             if (handlers[i].deleted) {
diff --git a/dix/main.c b/dix/main.c
index 9524189..42f517d 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -207,6 +207,12 @@ main(int argc, char *argv[], char *envp[])
             FatalError("no screens found");
         InitExtensions(argc, argv);
 
+        for (i = 0; i < screenInfo.numGPUScreens; i++) {
+            ScreenPtr pScreen = screenInfo.gpuscreens[i];
+            if (!CreateScratchPixmapsForScreen(pScreen))
+                FatalError("failed to create scratch pixmaps");
+        }
+
         for (i = 0; i < screenInfo.numScreens; i++) {
             ScreenPtr pScreen = screenInfo.screens[i];
 
@@ -336,6 +342,15 @@ main(int argc, char *argv[], char *envp[])
             screenInfo.numScreens = i;
         }
 
+        for (i = screenInfo.numGPUScreens - 1; i >= 0; i--) {
+            ScreenPtr pScreen = screenInfo.gpuscreens[i];
+            FreeScratchPixmapsForScreen(pScreen);
+            (*pScreen->CloseScreen) (pScreen);
+            dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+            free(pScreen);
+            screenInfo.numGPUScreens = i;
+        }
+
         ReleaseClientIds(serverClient);
         dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT);
         serverClient->devPrivates = NULL;
diff --git a/dix/privates.c b/dix/privates.c
index 2b8af27..004eb0e 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -154,66 +154,81 @@ dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
 }
 
 static Bool
-fixupScreens(FixupFunc fixup, unsigned bytes)
+fixOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
 {
-    int s;
+    intptr_t        dist;
+    char            *old;
+    char            *new;
+    DevPrivateKey   *keyp, key;
+    DevPrivateType  type;
+    int             size;
+
+    old = (char *) pScreen->devPrivates;
+    size = global_keys[PRIVATE_SCREEN].offset;
+    if (!fixup (&pScreen->devPrivates, size,bytes))
+        return FALSE;
 
-    for (s = 0; s < screenInfo.numScreens; s++) {
-        ScreenPtr       pScreen = screenInfo.screens[s];
-        intptr_t        dist;
-        char            *old;
-        char            *new;
-        DevPrivateKey   *keyp, key;
-        DevPrivateType  type;
-        int             size;
-
-        old = (char *) pScreen->devPrivates;
-        size = global_keys[PRIVATE_SCREEN].offset;
-        if (!fixup (&pScreen->devPrivates, size,bytes))
-            return FALSE;
+    /* Screen privates can contain screen-specific private keys
+     * for other types. When they move, the linked list we use to
+     * track them gets scrambled. Fix that by computing the change
+     * in the location of each private adjusting our linked list
+     * pointers to match
+     */
 
-        /* Screen privates can contain screen-specific private keys
-         * for other types. When they move, the linked list we use to
-         * track them gets scrambled. Fix that by computing the change
-         * in the location of each private adjusting our linked list
-         * pointers to match
-         */
+    new = (char *) pScreen->devPrivates;
 
-        new = (char *) pScreen->devPrivates;
+    /* Moving means everyone shifts up in the privates by 'bytes' amount,
+     * realloc means the base pointer moves
+     */
+    if (fixup == dixMovePrivates)
+        new += bytes;
 
-        /* Moving means everyone shifts up in the privates by 'bytes' amount,
-         * realloc means the base pointer moves
-         */
-        if (fixup == dixMovePrivates)
-            new += bytes;
+    dist = new - old;
 
-        dist = new - old;
+    if (dist) {
+        for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
 
-        if (dist) {
-            for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
+            /* Walk the privates list, being careful as the
+             * pointers are scrambled before we patch them.
+             */
+            for (keyp = &pScreen->screenSpecificPrivates[type].key;
+                 (key = *keyp) != NULL;
+                 keyp = &key->next)
+            {
 
-                /* Walk the privates list, being careful as the
-                 * pointers are scrambled before we patch them.
+                /* Only mangle things if the private structure
+                 * is contained within the allocation. Privates
+                 * stored elsewhere will be left alone
                  */
-                for (keyp = &pScreen->screenSpecificPrivates[type].key;
-                     (key = *keyp) != NULL;
-                     keyp = &key->next)
+                if (old <= (char *) key && (char *) key < old + size)
                 {
+                    /* Compute new location of key */
+                    key = (DevPrivateKey) ((char *) key + dist);
 
-                    /* Only mangle things if the private structure
-                     * is contained within the allocation. Privates
-                     * stored elsewhere will be left alone
-                     */
-                    if (old <= (char *) key && (char *) key < old + size)
-                    {
-                        /* Compute new location of key */
-                        key = (DevPrivateKey) ((char *) key + dist);
-
-                        /* Patch the list */
-                        *keyp = key;
-                    }
+                    /* Patch the list */
+                    *keyp = key;
                 }
-        }
+            }
+    }
+    return TRUE;
+}
+
+static Bool
+fixupScreens(FixupFunc fixup, unsigned bytes)
+{
+    int s;
+    Bool ret;
+
+    for (s = 0; s < screenInfo.numScreens; s++) {
+        ret = fixOneScreen(screenInfo.screens[s], fixup, bytes);
+        if (ret == FALSE)
+            return ret;
+    }
+
+    for (s = 0; s < screenInfo.numGPUScreens; s++) {
+        ret = fixOneScreen(screenInfo.gpuscreens[s], fixup, bytes);
+        if (ret == FALSE)
+            return ret;
     }
     return TRUE;
 }
diff --git a/include/misc.h b/include/misc.h
index fea74b8..22fb013 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -83,10 +83,14 @@ OF THIS SOFTWARE.
 #ifndef MAXSCREENS
 #define MAXSCREENS	16
 #endif
+#ifndef MAXGPUSCREENS
+#define MAXGPUSCREENS	16
+#endif
 #define MAXCLIENTS	256
 #define MAXEXTENSIONS   128
 #define MAXFORMATS	8
 #define MAXDEVICES	40      /* input devices */
+#define GPU_SCREEN_OFFSET 256
 
 /* 128 event opcodes for core + extension events, excluding GE */
 #define MAXEVENTS       128
diff --git a/include/screenint.h b/include/screenint.h
index 6b0cc70..8205f63 100644
--- a/include/screenint.h
+++ b/include/screenint.h
@@ -62,6 +62,15 @@ extern _X_EXPORT int AddScreen(Bool (* /*pfnInit */ )(
                                int /*argc */ ,
                                char ** /*argv */ );
 
+
+extern _X_EXPORT int AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+                                                   int /*argc */ ,
+                                                   char **      /*argv */
+                                                   ),
+                                  int argc, char **argv);
+
+extern _X_EXPORT void RemoveGPUScreen(ScreenPtr pScreen);
+
 typedef struct _ColormapRec *ColormapPtr;
 
 #endif                          /* SCREENINT_H */
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 7af2bf5..bcac475 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -477,6 +477,8 @@ typedef struct _Screen {
      * malicious users to steal framebuffer's content if that would be the
      * default */
     Bool canDoBGNoneRoot;
+
+    Bool isGPU;
 } ScreenRec;
 
 static inline RegionPtr
@@ -494,6 +496,8 @@ typedef struct _ScreenInfo {
      PixmapFormatRec formats[MAXFORMATS];
     int numScreens;
     ScreenPtr screens[MAXSCREENS];
+    int numGPUScreens;
+    ScreenPtr gpuscreens[MAXGPUSCREENS];
     int x;                      /* origin */
     int y;                      /* origin */
     int width;                  /* total width of all screens together */
diff --git a/render/glyph.c b/render/glyph.c
index acb573f..c121e64 100644
--- a/render/glyph.c
+++ b/render/glyph.c
@@ -687,6 +687,8 @@ miGlyphs(CARD8 op,
 
 PicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen)
 {
+    if (pScreen->isGPU)
+        return NULL;
     return GlyphPicture(glyph)[pScreen->myNum];
 }
 
-- 
1.7.10.2



More information about the xorg-devel mailing list