From: Michel Dänzer <[email protected]>

If the PrepareAccess hook fails, use the DownloadFromScreen hook to retrieve
driver pixmap contents to a system RAM copy, perform software rendering on that
and copy the results back using the UploadToScreen hook. Use the classic
migration logic to minimize transfers (which as a bonus allows slightly
cleaning up some of the existing mixed pixmap code).

This enables things that weren't possible before with driver-allocated pixmap
storage: If some (or all) GPU pixmap storage can't be mapped directly by the
CPU, this can be handled between the PrepareAccess and
DownloadFrom/UploadToScreen hooks, e.g.:

* Radeon KMS on big endian machines can fail PrepareAccess if the pixmap
  requires byte-swapping and swap bytes in DownloadFrom/UploadToScreen.
* Environments where GPU and CPU don't have a shared address space at all.
  Here the driver PrepareAccess hook will always fail and leave all transfers
  between GPU / CPU storage to the Download/From/UploadToScreen hooks.

Drivers which can handle all pixmaps in the PrepareAccess hook should notice
little if any difference.
---
 exa/exa.c                   |  106 ++++++++++++++++++++++++++++++++++---------
 exa/exa_migration_classic.c |    6 +-
 exa/exa_migration_mixed.c   |   91 ++++---------------------------------
 exa/exa_mixed.c             |   87 ++++++++++++++---------------------
 exa/exa_priv.h              |    6 +++
 5 files changed, 138 insertions(+), 158 deletions(-)

diff --git a/exa/exa.c b/exa/exa.c
index 483e3b4..6a1029a 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -324,7 +324,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
 
     offscreen = exaPixmapIsOffscreen(pPixmap);
 
-    if (offscreen)
+    if (offscreen && pExaPixmap->fb_ptr)
        pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
     else
        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
@@ -333,18 +333,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     pExaScr->access[index].pixmap = pPixmap;
     pExaScr->access[index].count = 1;
 
-    if (!offscreen) {
-       /* Do we need to allocate our system buffer? */
-       if ((pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && 
(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
-           if (!pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) {
-               pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * 
pDrawable->height);
-               if (!pExaPixmap->sys_ptr)
-                   FatalError("EXA: malloc failed for size %d bytes\n", 
pExaPixmap->sys_pitch * pDrawable->height);
-               pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
-           }
-       }
+    if (!offscreen)
        return FALSE;
-    }
 
     exaWaitSync (pDrawable->pScreen);
 
@@ -360,7 +350,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     }
 
     if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
-       if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+       if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
+           !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
            FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
        exaMoveOutPixmap (pPixmap);
 
@@ -374,11 +365,12 @@ void
 exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
 {
     PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
-    ExaScreenPriv(pPixmap->drawable.pScreen);
+    ScreenPtr pScreen = pDrawable->pScreen;
+    ExaScreenPriv(pScreen);
+    ExaMigrationRec pixmaps[1];
+    Bool access_prepared;
 
     if (pExaScr->do_migration) {
-       ExaMigrationRec pixmaps[1];
-
        if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
            pixmaps[0].as_dst = TRUE;
            pixmaps[0].as_src = FALSE;
@@ -388,11 +380,73 @@ exaPrepareAccessReg(DrawablePtr pDrawable, int index, 
RegionPtr pReg)
        }
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = pReg;
+    }
 
+    if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
        exaDoMigration(pixmaps, 1, FALSE);
-    }
 
-    ExaDoPrepareAccess(pDrawable, index);
+    access_prepared = ExaDoPrepareAccess(pDrawable, index);
+
+    /* With mixed pixmaps, if we fail to get direct access to the driver 
pixmap,
+     * we use the DownloadFromScreen hook to retrieve contents to a copy in
+     * system memory, perform software rendering on that and move back the
+     * results with the UploadToScreen hook (see exaFinishAccess).
+     */
+    if (!access_prepared && (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+       (pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
+       Bool is_offscreen = exaPixmapIsOffscreen(pPixmap);
+       ExaPixmapPriv(pPixmap);
+
+       /* Do we need to allocate our system buffer? */
+       if (!pExaPixmap->sys_ptr) {
+           pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
+                                        pPixmap->drawable.height);
+           if (!pExaPixmap->sys_ptr)
+               FatalError("EXA: malloc failed for size %d bytes\n",
+                          pExaPixmap->sys_pitch * pPixmap->drawable.height);
+       }
+
+       if (!pExaPixmap->pDamage && (is_offscreen || 
!exaPixmapIsPinned(pPixmap))) {
+           Bool as_dst = pixmaps[0].as_dst;
+
+           /* Set up damage tracking */
+           pExaPixmap->pDamage = DamageCreate (NULL, NULL,
+                                               DamageReportNone, TRUE,
+                                               pScreen, pPixmap);
+
+           DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
+           /* This ensures that pending damage reflects the current operation. 
*/
+           /* This is used by exa to optimize migration. */
+           DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
+
+           if (is_offscreen) {
+               exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+                              pPixmap->drawable.height);
+
+               /* We don't know which region of the destination will be 
damaged,
+                * have to assume all of it
+                */
+               if (as_dst) {
+                   pixmaps[0].as_dst = FALSE;
+                   pixmaps[0].as_src = TRUE;
+                   pixmaps[0].pReg = NULL;
+               }
+               pPixmap->devKind = pExaPixmap->fb_pitch;
+               exaCopyDirtyToSys(pixmaps);
+           }
+
+           if (as_dst)
+               exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+                              pPixmap->drawable.height);
+       } else if (is_offscreen) {
+           pPixmap->devKind = pExaPixmap->fb_pitch;
+           exaCopyDirtyToSys(pixmaps);
+       }
+
+       pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+       pPixmap->devKind = pExaPixmap->sys_pitch;
+       pExaPixmap->offscreen = FALSE;
+    }
 }
 
 /**
@@ -419,6 +473,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
     ExaScreenPriv  (pScreen);
     PixmapPtr      pPixmap = exaGetDrawablePixmap (pDrawable);
     ExaPixmapPriv  (pPixmap);
+    Bool is_offscreen;
     int i;
 
     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
@@ -447,10 +502,19 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
     /* We always hide the devPrivate.ptr. */
     pPixmap->devPrivate.ptr = NULL;
 
-    if (pExaScr->info->FinishAccess == NULL)
-       return;
+    is_offscreen = exaPixmapIsOffscreen(pPixmap);
+
+    /* Move back results of software rendering on system memory copy of mixed
+     * driver pixmap (see exaPrepareAccessReg).
+     */
+    if (pExaPixmap->pDamage && is_offscreen &&
+       (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+       (pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
+       DamageRegionProcessPending(&pPixmap->drawable);
+       exaMoveInPixmap_mixed(pPixmap);
+    }
 
-    if (!exaPixmapIsOffscreen (pPixmap))
+    if (!is_offscreen || !pExaScr->info->FinishAccess)
        return;
 
     if (index >= EXA_PREPARE_AUX_DEST &&
diff --git a/exa/exa_migration_classic.c b/exa/exa_migration_classic.c
index d8e1e86..c58e0af 100644
--- a/exa/exa_migration_classic.c
+++ b/exa/exa_migration_classic.c
@@ -120,7 +120,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, 
RegionPtr pValidSrc,
     Bool need_sync = FALSE;
 
     /* Damaged bits are valid in current copy but invalid in other one */
-    if (exaPixmapIsOffscreen(pPixmap)) {
+    if (pExaPixmap->offscreen) {
        REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
                     damage);
        REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
@@ -263,7 +263,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, 
RegionPtr pValidSrc,
  * the framebuffer  memory copy to the system memory copy.  Both areas must be
  * allocated.
  */
-static void
+void
 exaCopyDirtyToSys (ExaMigrationPtr migrate)
 {
     PixmapPtr pPixmap = migrate->pPix;
@@ -281,7 +281,7 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate)
  * the system memory copy to the framebuffer memory copy.  Both areas must be
  * allocated.
  */
-static void
+void
 exaCopyDirtyToFb (ExaMigrationPtr migrate)
 {
     PixmapPtr pPixmap = migrate->pPix;
diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
index d1ee987..a71a5ad 100644
--- a/exa/exa_migration_mixed.c
+++ b/exa/exa_migration_mixed.c
@@ -31,55 +31,16 @@
 #include "exa_priv.h"
 #include "exa.h"
 
-static void
-exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch)
-{
-    ExaPixmapPriv(pPixmap);
-    RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
-    GCPtr pGC = GetScratchGC (pPixmap->drawable.depth,
-               pPixmap->drawable.pScreen);
-    int nbox, cpp = pPixmap->drawable.bitsPerPixel / 8;
-    DamagePtr backup = pExaPixmap->pDamage;
-    BoxPtr pbox;
-    CARD8 *src2;
-
-    /* We don't want damage optimisations. */
-    pExaPixmap->pDamage = NULL;
-    ValidateGC (&pPixmap->drawable, pGC);
-
-    pbox = REGION_RECTS(damage);
-    nbox = REGION_NUM_RECTS(damage);
-
-    while (nbox--) {
-       src2 = src + pbox->y1 * src_pitch + pbox->x1 * cpp;
-
-       ExaCheckPutImage(&pPixmap->drawable, pGC,
-           pPixmap->drawable.depth, pbox->x1, pbox->y1,
-           pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 0,
-           ZPixmap, (char*) src2);
-
-       pbox++;
-    }
-
-    FreeScratchGC (pGC);
-    pExaPixmap->pDamage = backup;
-}
-
 void
 exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
 {
     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPriv(pScreen);
     ExaPixmapPriv(pPixmap);
-    RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
-    void *sys_buffer = pExaPixmap->sys_ptr;
     int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
     int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
     int usage_hint = pPixmap->usage_hint;
-    int sys_pitch = pExaPixmap->sys_pitch;
-    int paddedWidth = sys_pitch;
-    int nbox;
-    BoxPtr pbox;
+    int paddedWidth = pExaPixmap->sys_pitch;
 
     /* Already done. */
     if (pExaPixmap->driverPriv)
@@ -105,50 +66,8 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
     if (!pExaPixmap->driverPriv)
        return;
 
-    pExaPixmap->offscreen = TRUE;
-    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
-    pExaPixmap->sys_pitch = pPixmap->devKind = 0;
-
-    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
     (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
                                paddedWidth, NULL);
-
-    /* scratch pixmaps */
-    if (!w || !h)
-       goto finish;
-
-    /* we do not malloc memory by default. */
-    if (!sys_buffer)
-       goto finish;
-
-    if (!pExaScr->info->UploadToScreen)
-       goto fallback;
-
-    pbox = REGION_RECTS(damage);
-    nbox = REGION_NUM_RECTS(damage);
-
-    while (nbox--) {
-       if (!pExaScr->info->UploadToScreen(pPixmap, pbox->x1, pbox->y1, 
pbox->x2 - pbox->x1,
-               pbox->y2 - pbox->y1, (char *) (sys_buffer) + pbox->y1 * 
sys_pitch + pbox->x1 * (bpp / 8), sys_pitch))
-           goto fallback;
-
-       pbox++;
-    }
-
-    goto finish;
-
-fallback:
-    exaUploadFallback(pPixmap, sys_buffer, sys_pitch);
-
-finish:
-    free(sys_buffer);
-
-    /* We no longer need this. */
-    if (pExaPixmap->pDamage) {
-       DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
-       DamageDestroy(pExaPixmap->pDamage);
-       pExaPixmap->pDamage = NULL;
-    }
 }
 
 void
@@ -175,8 +94,16 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, 
Bool can_accel)
     for (i = 0; i < npixmaps; i++) {
        PixmapPtr pPixmap = pixmaps[i].pPix;
        ExaPixmapPriv(pPixmap);
+
        if (!pExaPixmap->driverPriv)
            exaCreateDriverPixmap_mixed(pPixmap);
+
+       if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) {
+           pPixmap->devKind = pExaPixmap->fb_pitch;
+           exaCopyDirtyToFb(pixmaps + i);
+       }
+
+       pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
     }
 }
 
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index 6aa73f2..167ffa9 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -32,8 +32,6 @@
 #include "exa.h"
 
 /* This file holds the driver allocated pixmaps + better initial placement 
code.
- * A pinned pixmap implies one that is either driver based already or 
otherwise altered.
- * Proper care is taken to free the initially allocated buffer.
  */
 
 static _X_INLINE void*
@@ -46,9 +44,6 @@ ExaGetPixmapAddress(PixmapPtr p)
 
 /**
  * exaCreatePixmap() creates a new pixmap.
- *
- * Pixmaps are always marked as pinned, unless the pixmap can still be 
transfered to a
- * driver pixmaps.
  */
 PixmapPtr
 exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
@@ -85,7 +80,6 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int 
depth,
     pExaPixmap->sys_pitch = paddedWidth;
 
     pExaPixmap->area = NULL;
-    pExaPixmap->offscreen = FALSE;
     pExaPixmap->fb_ptr = NULL;
     pExaPixmap->pDamage = NULL;
 
@@ -93,36 +87,15 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int 
depth,
     exaSetAccelBlock(pExaScr, pExaPixmap,
        w, h, bpp);
 
-    /* Avoid freeing sys_ptr. */
-    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
-
     (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
                                    paddedWidth, NULL);
 
-    /* We want to be able to transfer the pixmap to driver memory later on. */
-    pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
     /* A scratch pixmap will become a driver pixmap right away. */
     if (!w || !h) {
        exaCreateDriverPixmap_mixed(pPixmap);
-    } else {
-       /* Set up damage tracking */
-       pExaPixmap->pDamage = DamageCreate (NULL, NULL,
-                                           DamageReportNone, TRUE,
-                                           pScreen, pPixmap);
-
-       if (pExaPixmap->pDamage == NULL) {
-           swap(pExaScr, pScreen, DestroyPixmap);
-           pScreen->DestroyPixmap (pPixmap);
-           swap(pExaScr, pScreen, DestroyPixmap);
-           return NULL;
-       }
-
-       DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
-       /* This ensures that pending damage reflects the current operation. */
-       /* This is used by exa to optimize migration. */
-       DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
-    }
+       pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
+    } else
+       pExaPixmap->offscreen = FALSE;
 
     return pPixmap;
 }
@@ -134,7 +107,7 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPrivPtr pExaScr;
     ExaPixmapPrivPtr pExaPixmap;
-    Bool ret;
+    Bool ret, is_offscreen;
 
     if (!pPixmap)
         return FALSE;
@@ -142,26 +115,23 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
     pExaScr = ExaGetScreenPriv(pScreen);
     pExaPixmap = ExaGetPixmapPriv(pPixmap);
 
-    if (pExaPixmap) {
-       if (!exaPixmapIsPinned(pPixmap)) {
-           free(pExaPixmap->sys_ptr);
-           pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
-           pExaPixmap->sys_pitch = pPixmap->devKind = 0;
-
-           /* We no longer need this. */
+    if (pPixData) {
+       if (pExaPixmap->driverPriv) {
            if (pExaPixmap->pDamage) {
                DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
                DamageDestroy(pExaPixmap->pDamage);
                pExaPixmap->pDamage = NULL;
            }
-       }
 
-        if (pPixData)
-            pExaPixmap->sys_ptr = pPixData;
+           pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+           pExaPixmap->driverPriv = NULL;
+       }
 
-        if (devKind > 0)
-            pExaPixmap->sys_pitch = devKind;
+       pExaPixmap->offscreen = FALSE;
+       pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+    }
 
+    if (pExaPixmap->driverPriv) {
         if (width > 0 && height > 0 && bitsPerPixel > 0) {
             exaSetFbPitch(pExaScr, pExaPixmap,
                           width, height, bitsPerPixel);
@@ -169,9 +139,15 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
             exaSetAccelBlock(pExaScr, pExaPixmap,
                              width, height, bitsPerPixel);
         }
+    }
 
-       /* Anything can happen, don't try to predict it all. */
-       pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+    is_offscreen = exaPixmapIsOffscreen(pPixmap);
+    if (is_offscreen) {
+       pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+       pPixmap->devKind = pExaPixmap->fb_pitch;
+    } else {
+       pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+       pPixmap->devKind = pExaPixmap->sys_pitch;
     }
 
     /* Only pass driver pixmaps to the driver. */
@@ -182,10 +158,6 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
         * If pPixmap->devPrivate.ptr is non-NULL, then we've got a 
non-offscreen pixmap.
         * We need to store the pointer, because PrepareAccess won't be called.
         */
-       if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
-           pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
-           pExaPixmap->sys_pitch = pPixmap->devKind;
-       }
        if (ret == TRUE)
            goto out;
     }
@@ -196,6 +168,13 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
     swap(pExaScr, pScreen, ModifyPixmapHeader);
 
 out:
+    if (is_offscreen) {
+       pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
+       pExaPixmap->fb_pitch = pPixmap->devKind;
+    } else {
+       pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+       pExaPixmap->sys_pitch = pPixmap->devKind;
+    }
     /* Always NULL this, we don't want lingering pointers. */
     pPixmap->devPrivate.ptr = NULL;
 
@@ -215,10 +194,14 @@ exaDestroyPixmap_mixed(PixmapPtr pPixmap)
 
        if (pExaPixmap->driverPriv)
            pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
-       else if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap))
-           free(pExaPixmap->sys_ptr);
        pExaPixmap->driverPriv = NULL;
-       pExaPixmap->sys_ptr = NULL;
+
+       if (pExaPixmap->pDamage) {
+           if (pExaPixmap->sys_ptr)
+               free(pExaPixmap->sys_ptr);
+           pExaPixmap->sys_ptr = NULL;
+           pExaPixmap->pDamage = NULL;
+       }
     }
 
     swap(pExaScr, pScreen, DestroyPixmap);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 869cf17..11a2e55 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -665,6 +665,12 @@ exaGlyphs (CARD8   op,
 
 /* exa_migration_classic.c */
 void
+exaCopyDirtyToSys (ExaMigrationPtr migrate);
+
+void
+exaCopyDirtyToFb (ExaMigrationPtr migrate);
+
+void
 exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
 
 void
-- 
1.6.4.3

_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to