xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

exa.c (35040B)


      1 /*
      2  * Copyright © 2001 Keith Packard
      3  *
      4  * Partly based on code that is Copyright © The XFree86 Project Inc.
      5  *
      6  * Permission to use, copy, modify, distribute, and sell this software and its
      7  * documentation for any purpose is hereby granted without fee, provided that
      8  * the above copyright notice appear in all copies and that both that
      9  * copyright notice and this permission notice appear in supporting
     10  * documentation, and that the name of Keith Packard not be used in
     11  * advertising or publicity pertaining to distribution of the software without
     12  * specific, written prior permission.  Keith Packard makes no
     13  * representations about the suitability of this software for any purpose.  It
     14  * is provided "as is" without express or implied warranty.
     15  *
     16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     22  * PERFORMANCE OF THIS SOFTWARE.
     23  */
     24 
     25 /** @file
     26  * This file covers the initialization and teardown of EXA, and has various
     27  * functions not responsible for performing rendering, pixmap migration, or
     28  * memory management.
     29  */
     30 
     31 #ifdef HAVE_DIX_CONFIG_H
     32 #include <dix-config.h>
     33 #endif
     34 
     35 #include <stdlib.h>
     36 
     37 #include "exa_priv.h"
     38 #include "exa.h"
     39 
     40 DevPrivateKeyRec exaScreenPrivateKeyRec;
     41 
     42 #ifdef MITSHM
     43 static ShmFuncs exaShmFuncs = { NULL, NULL };
     44 #endif
     45 
     46 /**
     47  * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
     48  * the beginning of the given pixmap.
     49  *
     50  * Note that drivers are free to, and often do, munge this offset as necessary
     51  * for handing to the hardware -- for example, translating it into a different
     52  * aperture.  This function may need to be extended in the future if we grow
     53  * support for having multiple card-accessible offscreen, such as an AGP memory
     54  * pool alongside the framebuffer pool.
     55  */
     56 unsigned long
     57 exaGetPixmapOffset(PixmapPtr pPix)
     58 {
     59     ExaScreenPriv(pPix->drawable.pScreen);
     60     ExaPixmapPriv(pPix);
     61 
     62     return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
     63 }
     64 
     65 void *
     66 exaGetPixmapDriverPrivate(PixmapPtr pPix)
     67 {
     68     ExaPixmapPriv(pPix);
     69 
     70     return pExaPixmap->driverPriv;
     71 }
     72 
     73 /**
     74  * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
     75  *
     76  * This is a helper to make driver code more obvious, due to the rather obscure
     77  * naming of the pitch field in the pixmap.
     78  */
     79 unsigned long
     80 exaGetPixmapPitch(PixmapPtr pPix)
     81 {
     82     return pPix->devKind;
     83 }
     84 
     85 /**
     86  * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
     87  * memory. Only valid when the pixmap is currently in framebuffer.
     88  */
     89 unsigned long
     90 exaGetPixmapSize(PixmapPtr pPix)
     91 {
     92     ExaPixmapPrivPtr pExaPixmap;
     93 
     94     pExaPixmap = ExaGetPixmapPriv(pPix);
     95     if (pExaPixmap != NULL)
     96         return pExaPixmap->fb_size;
     97     return 0;
     98 }
     99 
    100 /**
    101  * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
    102  *
    103  * @param pDrawable the drawable being requested.
    104  *
    105  * This function returns the backing pixmap for a drawable, whether it is a
    106  * redirected window, unredirected window, or already a pixmap.  Note that
    107  * coordinate translation is needed when drawing to the backing pixmap of a
    108  * redirected window, and the translation coordinates are provided by calling
    109  * exaGetOffscreenPixmap() on the drawable.
    110  */
    111 PixmapPtr
    112 exaGetDrawablePixmap(DrawablePtr pDrawable)
    113 {
    114     if (pDrawable->type == DRAWABLE_WINDOW)
    115         return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
    116     else
    117         return (PixmapPtr) pDrawable;
    118 }
    119 
    120 /**
    121  * Sets the offsets to add to coordinates to make them address the same bits in
    122  * the backing drawable. These coordinates are nonzero only for redirected
    123  * windows.
    124  */
    125 void
    126 exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp)
    127 {
    128 #ifdef COMPOSITE
    129     if (pDrawable->type == DRAWABLE_WINDOW) {
    130         *xp = -pPixmap->screen_x;
    131         *yp = -pPixmap->screen_y;
    132         return;
    133     }
    134 #endif
    135 
    136     *xp = 0;
    137     *yp = 0;
    138 }
    139 
    140 /**
    141  * exaPixmapDirty() marks a pixmap as dirty, allowing for
    142  * optimizations in pixmap migration when no changes have occurred.
    143  */
    144 void
    145 exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2)
    146 {
    147     BoxRec box;
    148     RegionRec region;
    149 
    150     box.x1 = max(x1, 0);
    151     box.y1 = max(y1, 0);
    152     box.x2 = min(x2, pPix->drawable.width);
    153     box.y2 = min(y2, pPix->drawable.height);
    154 
    155     if (box.x1 >= box.x2 || box.y1 >= box.y2)
    156         return;
    157 
    158     RegionInit(&region, &box, 1);
    159     DamageDamageRegion(&pPix->drawable, &region);
    160     RegionUninit(&region);
    161 }
    162 
    163 static int
    164 exaLog2(int val)
    165 {
    166     int bits;
    167 
    168     if (val <= 0)
    169         return 0;
    170     for (bits = 0; val != 0; bits++)
    171         val >>= 1;
    172     return bits - 1;
    173 }
    174 
    175 void
    176 exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
    177                  int w, int h, int bpp)
    178 {
    179     pExaPixmap->accel_blocked = 0;
    180 
    181     if (pExaScr->info->maxPitchPixels) {
    182         int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
    183 
    184         if (pExaPixmap->fb_pitch > max_pitch)
    185             pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
    186     }
    187 
    188     if (pExaScr->info->maxPitchBytes &&
    189         pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes)
    190         pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
    191 
    192     if (w > pExaScr->info->maxX)
    193         pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH;
    194 
    195     if (h > pExaScr->info->maxY)
    196         pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
    197 }
    198 
    199 void
    200 exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
    201               int w, int h, int bpp)
    202 {
    203     if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
    204         pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
    205     else
    206         pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
    207 
    208     pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
    209                                      pExaScr->info->pixmapPitchAlign);
    210 }
    211 
    212 /**
    213  * Returns TRUE if the pixmap is not movable.  This is the case where it's a
    214  * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
    215  * some X Server internal component (the score says it's pinned).
    216  */
    217 Bool
    218 exaPixmapIsPinned(PixmapPtr pPix)
    219 {
    220     ExaPixmapPriv(pPix);
    221 
    222     if (pExaPixmap == NULL)
    223         EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
    224 
    225     return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
    226 }
    227 
    228 /**
    229  * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
    230  * memory, meaning that acceleration could probably be done to it, and that it
    231  * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
    232  * with the CPU.
    233  *
    234  * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
    235  * deal with moving pixmaps in and out of system memory), EXA will give drivers
    236  * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE.
    237  *
    238  * @return TRUE if the given drawable is in framebuffer memory.
    239  */
    240 Bool
    241 exaPixmapHasGpuCopy(PixmapPtr pPixmap)
    242 {
    243     ScreenPtr pScreen = pPixmap->drawable.pScreen;
    244 
    245     ExaScreenPriv(pScreen);
    246 
    247     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
    248         return FALSE;
    249 
    250     return (*pExaScr->pixmap_has_gpu_copy) (pPixmap);
    251 }
    252 
    253 /**
    254  * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
    255  */
    256 Bool
    257 exaDrawableIsOffscreen(DrawablePtr pDrawable)
    258 {
    259     return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable));
    260 }
    261 
    262 /**
    263  * Returns the pixmap which backs a drawable, and the offsets to add to
    264  * coordinates to make them address the same bits in the backing drawable.
    265  */
    266 PixmapPtr
    267 exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp)
    268 {
    269     PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
    270 
    271     exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp);
    272 
    273     if (exaPixmapHasGpuCopy(pPixmap))
    274         return pPixmap;
    275     else
    276         return NULL;
    277 }
    278 
    279 /**
    280  * Returns TRUE if the pixmap GPU copy is being accessed.
    281  */
    282 Bool
    283 ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
    284 {
    285     ScreenPtr pScreen = pPixmap->drawable.pScreen;
    286 
    287     ExaScreenPriv(pScreen);
    288     ExaPixmapPriv(pPixmap);
    289     Bool has_gpu_copy, ret;
    290     int i;
    291 
    292     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
    293         return FALSE;
    294 
    295     if (pExaPixmap == NULL)
    296         EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
    297 
    298     /* Handle repeated / nested calls. */
    299     for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
    300         if (pExaScr->access[i].pixmap == pPixmap) {
    301             pExaScr->access[i].count++;
    302             return pExaScr->access[i].retval;
    303         }
    304     }
    305 
    306     /* If slot for this index is taken, find an empty slot */
    307     if (pExaScr->access[index].pixmap) {
    308         for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--)
    309             if (!pExaScr->access[index].pixmap)
    310                 break;
    311     }
    312 
    313     /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
    314     if (pPixmap->devPrivate.ptr != NULL) {
    315         EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap->devPrivate.ptr));
    316     }
    317 
    318     has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    319 
    320     if (has_gpu_copy && pExaPixmap->fb_ptr) {
    321         pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
    322         ret = TRUE;
    323     }
    324     else {
    325         pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
    326         ret = FALSE;
    327     }
    328 
    329     /* Store so we can handle repeated / nested calls. */
    330     pExaScr->access[index].pixmap = pPixmap;
    331     pExaScr->access[index].count = 1;
    332 
    333     if (!has_gpu_copy)
    334         goto out;
    335 
    336     exaWaitSync(pScreen);
    337 
    338     if (pExaScr->info->PrepareAccess == NULL)
    339         goto out;
    340 
    341     if (index >= EXA_PREPARE_AUX_DEST &&
    342         !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
    343         if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
    344             FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
    345         exaMoveOutPixmap(pPixmap);
    346         ret = FALSE;
    347         goto out;
    348     }
    349 
    350     if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
    351         if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
    352             !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
    353             FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
    354         exaMoveOutPixmap(pPixmap);
    355         ret = FALSE;
    356         goto out;
    357     }
    358 
    359     ret = TRUE;
    360 
    361  out:
    362     pExaScr->access[index].retval = ret;
    363     return ret;
    364 }
    365 
    366 /**
    367  * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
    368  *
    369  * It deals with waiting for synchronization with the card, determining if
    370  * PrepareAccess() is necessary, and working around PrepareAccess() failure.
    371  */
    372 void
    373 exaPrepareAccess(DrawablePtr pDrawable, int index)
    374 {
    375     PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
    376 
    377     ExaScreenPriv(pDrawable->pScreen);
    378 
    379     if (pExaScr->prepare_access_reg)
    380         pExaScr->prepare_access_reg(pPixmap, index, NULL);
    381     else
    382         (void) ExaDoPrepareAccess(pPixmap, index);
    383 }
    384 
    385 /**
    386  * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
    387  *
    388  * It deals with calling the driver's FinishAccess() only if necessary.
    389  */
    390 void
    391 exaFinishAccess(DrawablePtr pDrawable, int index)
    392 {
    393     ScreenPtr pScreen = pDrawable->pScreen;
    394 
    395     ExaScreenPriv(pScreen);
    396     PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
    397 
    398     ExaPixmapPriv(pPixmap);
    399     int i;
    400 
    401     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
    402         return;
    403 
    404     if (pExaPixmap == NULL)
    405         EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
    406 
    407     /* Handle repeated / nested calls. */
    408     for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
    409         if (pExaScr->access[i].pixmap == pPixmap) {
    410             if (--pExaScr->access[i].count > 0)
    411                 return;
    412             break;
    413         }
    414     }
    415 
    416     /* Catch unbalanced Prepare/FinishAccess calls. */
    417     if (i == EXA_NUM_PREPARE_INDICES)
    418         EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap),);
    419 
    420     pExaScr->access[i].pixmap = NULL;
    421 
    422     /* We always hide the devPrivate.ptr. */
    423     pPixmap->devPrivate.ptr = NULL;
    424 
    425     /* Only call FinishAccess if PrepareAccess was called and succeeded. */
    426     if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval)
    427         return;
    428 
    429     if (i >= EXA_PREPARE_AUX_DEST &&
    430         !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
    431         ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
    432                "unsupported index EXA_PREPARE_AUX*\n");
    433         return;
    434     }
    435 
    436     (*pExaScr->info->FinishAccess) (pPixmap, i);
    437 }
    438 
    439 /**
    440  * Helper for things common to all schemes when a pixmap is destroyed
    441  */
    442 void
    443 exaDestroyPixmap(PixmapPtr pPixmap)
    444 {
    445     ExaScreenPriv(pPixmap->drawable.pScreen);
    446     int i;
    447 
    448     /* Finish access if it was prepared (e.g. pixmap created during
    449      * software fallback)
    450      */
    451     for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
    452         if (pExaScr->access[i].pixmap == pPixmap) {
    453             exaFinishAccess(&pPixmap->drawable, i);
    454             pExaScr->access[i].pixmap = NULL;
    455             break;
    456         }
    457     }
    458 }
    459 
    460 /**
    461  * Here begins EXA's GC code.
    462  * Do not ever access the fb/mi layer directly.
    463  */
    464 
    465 static void
    466  exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
    467 
    468 static void
    469  exaDestroyGC(GCPtr pGC);
    470 
    471 static void
    472  exaChangeGC(GCPtr pGC, unsigned long mask);
    473 
    474 static void
    475  exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
    476 
    477 static void
    478  exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects);
    479 
    480 static void
    481  exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
    482 
    483 static void
    484  exaDestroyClip(GCPtr pGC);
    485 
    486 const GCFuncs exaGCFuncs = {
    487     exaValidateGC,
    488     exaChangeGC,
    489     exaCopyGC,
    490     exaDestroyGC,
    491     exaChangeClip,
    492     exaDestroyClip,
    493     exaCopyClip
    494 };
    495 
    496 static void
    497 exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
    498 {
    499     /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
    500      * Do a few smart things so fbValidateGC can do its work.
    501      */
    502 
    503     ScreenPtr pScreen = pDrawable->pScreen;
    504 
    505     ExaScreenPriv(pScreen);
    506     ExaGCPriv(pGC);
    507     PixmapPtr pTile = NULL;
    508 
    509     /* Either of these conditions is enough to trigger access to a tile pixmap.
    510      * With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid
    511      * tile pixmap pointer.
    512      */
    513     if (pGC->fillStyle == FillTiled ||
    514         ((changes & GCTile) && !pGC->tileIsPixel)) {
    515         pTile = pGC->tile.pixmap;
    516     }
    517 
    518     if (pGC->stipple)
    519         exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
    520     if (pTile)
    521         exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
    522 
    523     /* Calls to Create/DestroyPixmap have to be identified as special. */
    524     pExaScr->fallback_counter++;
    525     swap(pExaGC, pGC, funcs);
    526     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
    527     swap(pExaGC, pGC, funcs);
    528     pExaScr->fallback_counter--;
    529 
    530     if (pTile)
    531         exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
    532     if (pGC->stipple)
    533         exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
    534 }
    535 
    536 /* Is exaPrepareAccessGC() needed? */
    537 static void
    538 exaDestroyGC(GCPtr pGC)
    539 {
    540     ExaGCPriv(pGC);
    541     swap(pExaGC, pGC, funcs);
    542     (*pGC->funcs->DestroyGC) (pGC);
    543     swap(pExaGC, pGC, funcs);
    544 }
    545 
    546 static void
    547 exaChangeGC(GCPtr pGC, unsigned long mask)
    548 {
    549     ExaGCPriv(pGC);
    550     swap(pExaGC, pGC, funcs);
    551     (*pGC->funcs->ChangeGC) (pGC, mask);
    552     swap(pExaGC, pGC, funcs);
    553 }
    554 
    555 static void
    556 exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
    557 {
    558     ExaGCPriv(pGCDst);
    559     swap(pExaGC, pGCDst, funcs);
    560     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
    561     swap(pExaGC, pGCDst, funcs);
    562 }
    563 
    564 static void
    565 exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
    566 {
    567     ExaGCPriv(pGC);
    568     swap(pExaGC, pGC, funcs);
    569     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
    570     swap(pExaGC, pGC, funcs);
    571 }
    572 
    573 static void
    574 exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
    575 {
    576     ExaGCPriv(pGCDst);
    577     swap(pExaGC, pGCDst, funcs);
    578     (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc);
    579     swap(pExaGC, pGCDst, funcs);
    580 }
    581 
    582 static void
    583 exaDestroyClip(GCPtr pGC)
    584 {
    585     ExaGCPriv(pGC);
    586     swap(pExaGC, pGC, funcs);
    587     (*pGC->funcs->DestroyClip) (pGC);
    588     swap(pExaGC, pGC, funcs);
    589 }
    590 
    591 /**
    592  * exaCreateGC makes a new GC and hooks up its funcs handler, so that
    593  * exaValidateGC() will get called.
    594  */
    595 static int
    596 exaCreateGC(GCPtr pGC)
    597 {
    598     ScreenPtr pScreen = pGC->pScreen;
    599 
    600     ExaScreenPriv(pScreen);
    601     ExaGCPriv(pGC);
    602     Bool ret;
    603 
    604     swap(pExaScr, pScreen, CreateGC);
    605     if ((ret = (*pScreen->CreateGC) (pGC))) {
    606         wrap(pExaGC, pGC, funcs, &exaGCFuncs);
    607         wrap(pExaGC, pGC, ops, &exaOps);
    608     }
    609     swap(pExaScr, pScreen, CreateGC);
    610 
    611     return ret;
    612 }
    613 
    614 static Bool
    615 exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
    616 {
    617     Bool ret;
    618     ScreenPtr pScreen = pWin->drawable.pScreen;
    619 
    620     ExaScreenPriv(pScreen);
    621 
    622     if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
    623         exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
    624 
    625     if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
    626         exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
    627 
    628     pExaScr->fallback_counter++;
    629     swap(pExaScr, pScreen, ChangeWindowAttributes);
    630     ret = pScreen->ChangeWindowAttributes(pWin, mask);
    631     swap(pExaScr, pScreen, ChangeWindowAttributes);
    632     pExaScr->fallback_counter--;
    633 
    634     if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
    635         exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
    636     if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
    637         exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
    638 
    639     return ret;
    640 }
    641 
    642 static RegionPtr
    643 exaBitmapToRegion(PixmapPtr pPix)
    644 {
    645     RegionPtr ret;
    646     ScreenPtr pScreen = pPix->drawable.pScreen;
    647 
    648     ExaScreenPriv(pScreen);
    649 
    650     exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC);
    651     swap(pExaScr, pScreen, BitmapToRegion);
    652     ret = (*pScreen->BitmapToRegion) (pPix);
    653     swap(pExaScr, pScreen, BitmapToRegion);
    654     exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC);
    655 
    656     return ret;
    657 }
    658 
    659 static Bool
    660 exaCreateScreenResources(ScreenPtr pScreen)
    661 {
    662     ExaScreenPriv(pScreen);
    663     PixmapPtr pScreenPixmap;
    664     Bool b;
    665 
    666     swap(pExaScr, pScreen, CreateScreenResources);
    667     b = pScreen->CreateScreenResources(pScreen);
    668     swap(pExaScr, pScreen, CreateScreenResources);
    669 
    670     if (!b)
    671         return FALSE;
    672 
    673     pScreenPixmap = pScreen->GetScreenPixmap(pScreen);
    674 
    675     if (pScreenPixmap) {
    676         ExaPixmapPriv(pScreenPixmap);
    677 
    678         exaSetAccelBlock(pExaScr, pExaPixmap,
    679                          pScreenPixmap->drawable.width,
    680                          pScreenPixmap->drawable.height,
    681                          pScreenPixmap->drawable.bitsPerPixel);
    682     }
    683 
    684     return TRUE;
    685 }
    686 
    687 static void
    688 ExaBlockHandler(ScreenPtr pScreen, void *pTimeout)
    689 {
    690     ExaScreenPriv(pScreen);
    691 
    692     /* Move any deferred results from a software fallback to the driver pixmap */
    693     if (pExaScr->deferred_mixed_pixmap)
    694         exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
    695 
    696     unwrap(pExaScr, pScreen, BlockHandler);
    697     (*pScreen->BlockHandler) (pScreen, pTimeout);
    698     wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
    699 
    700     /* The rest only applies to classic EXA */
    701     if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
    702         return;
    703 
    704     /* Try and keep the offscreen memory area tidy every now and then (at most
    705      * once per second) when the server has been idle for at least 100ms.
    706      */
    707     if (pExaScr->numOffscreenAvailable > 1) {
    708         CARD32 now = GetTimeInMillis();
    709 
    710         pExaScr->nextDefragment = now +
    711             max(100, (INT32) (pExaScr->lastDefragment + 1000 - now));
    712         AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
    713     }
    714 }
    715 
    716 static void
    717 ExaWakeupHandler(ScreenPtr pScreen, int result)
    718 {
    719     ExaScreenPriv(pScreen);
    720 
    721     unwrap(pExaScr, pScreen, WakeupHandler);
    722     (*pScreen->WakeupHandler) (pScreen, result);
    723     wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
    724 
    725     if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
    726         CARD32 now = GetTimeInMillis();
    727 
    728         if ((int) (now - pExaScr->nextDefragment) > 0) {
    729             ExaOffscreenDefragment(pScreen);
    730             pExaScr->lastDefragment = now;
    731         }
    732     }
    733 }
    734 
    735 /**
    736  * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
    737  * screen private, before calling down to the next CloseSccreen.
    738  */
    739 static Bool
    740 exaCloseScreen(ScreenPtr pScreen)
    741 {
    742     ExaScreenPriv(pScreen);
    743     PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
    744 
    745     if (ps->Glyphs == exaGlyphs)
    746         exaGlyphsFini(pScreen);
    747 
    748     if (pScreen->BlockHandler == ExaBlockHandler)
    749         unwrap(pExaScr, pScreen, BlockHandler);
    750     if (pScreen->WakeupHandler == ExaWakeupHandler)
    751         unwrap(pExaScr, pScreen, WakeupHandler);
    752     unwrap(pExaScr, pScreen, CreateGC);
    753     unwrap(pExaScr, pScreen, CloseScreen);
    754     unwrap(pExaScr, pScreen, GetImage);
    755     unwrap(pExaScr, pScreen, GetSpans);
    756     if (pExaScr->SavedCreatePixmap)
    757         unwrap(pExaScr, pScreen, CreatePixmap);
    758     if (pExaScr->SavedDestroyPixmap)
    759         unwrap(pExaScr, pScreen, DestroyPixmap);
    760     if (pExaScr->SavedModifyPixmapHeader)
    761         unwrap(pExaScr, pScreen, ModifyPixmapHeader);
    762     unwrap(pExaScr, pScreen, CopyWindow);
    763     unwrap(pExaScr, pScreen, ChangeWindowAttributes);
    764     unwrap(pExaScr, pScreen, BitmapToRegion);
    765     unwrap(pExaScr, pScreen, CreateScreenResources);
    766     if (pExaScr->SavedSharePixmapBacking)
    767         unwrap(pExaScr, pScreen, SharePixmapBacking);
    768     if (pExaScr->SavedSetSharedPixmapBacking)
    769         unwrap(pExaScr, pScreen, SetSharedPixmapBacking);
    770     unwrap(pExaScr, ps, Composite);
    771     if (pExaScr->SavedGlyphs)
    772         unwrap(pExaScr, ps, Glyphs);
    773     unwrap(pExaScr, ps, Trapezoids);
    774     unwrap(pExaScr, ps, Triangles);
    775     unwrap(pExaScr, ps, AddTraps);
    776 
    777     free(pExaScr);
    778 
    779     return (*pScreen->CloseScreen) (pScreen);
    780 }
    781 
    782 /**
    783  * This function allocates a driver structure for EXA drivers to fill in.  By
    784  * having EXA allocate the structure, the driver structure can be extended
    785  * without breaking ABI between EXA and the drivers.  The driver's
    786  * responsibility is to check beforehand that the EXA module has a matching
    787  * major number and sufficient minor.  Drivers are responsible for freeing the
    788  * driver structure using free().
    789  *
    790  * @return a newly allocated, zero-filled driver structure
    791  */
    792 ExaDriverPtr
    793 exaDriverAlloc(void)
    794 {
    795     return calloc(1, sizeof(ExaDriverRec));
    796 }
    797 
    798 /**
    799  * @param pScreen screen being initialized
    800  * @param pScreenInfo EXA driver record
    801  *
    802  * exaDriverInit sets up EXA given a driver record filled in by the driver.
    803  * pScreenInfo should have been allocated by exaDriverAlloc().  See the
    804  * comments in _ExaDriver for what must be filled in and what is optional.
    805  *
    806  * @return TRUE if EXA was successfully initialized.
    807  */
    808 Bool
    809 exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo)
    810 {
    811     ExaScreenPrivPtr pExaScr;
    812     PictureScreenPtr ps;
    813 
    814     if (!pScreenInfo)
    815         return FALSE;
    816 
    817     if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
    818         pScreenInfo->exa_minor > EXA_VERSION_MINOR) {
    819         LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements "
    820                    "(%d.%d) are incompatible with EXA version (%d.%d)\n",
    821                    pScreen->myNum,
    822                    pScreenInfo->exa_major, pScreenInfo->exa_minor,
    823                    EXA_VERSION_MAJOR, EXA_VERSION_MINOR);
    824         return FALSE;
    825     }
    826 
    827     if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) {
    828         if (!pScreenInfo->memoryBase) {
    829             LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase "
    830                        "must be non-zero\n", pScreen->myNum);
    831             return FALSE;
    832         }
    833 
    834         if (!pScreenInfo->memorySize) {
    835             LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
    836                        "non-zero\n", pScreen->myNum);
    837             return FALSE;
    838         }
    839 
    840         if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
    841             LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must "
    842                        "be <= ExaDriverRec::memorySize\n", pScreen->myNum);
    843             return FALSE;
    844         }
    845     }
    846 
    847     if (!pScreenInfo->PrepareSolid) {
    848         LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
    849                    "non-NULL\n", pScreen->myNum);
    850         return FALSE;
    851     }
    852 
    853     if (!pScreenInfo->PrepareCopy) {
    854         LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
    855                    "non-NULL\n", pScreen->myNum);
    856         return FALSE;
    857     }
    858 
    859     if (!pScreenInfo->WaitMarker) {
    860         LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
    861                    "non-NULL\n", pScreen->myNum);
    862         return FALSE;
    863     }
    864 
    865     /* If the driver doesn't set any max pitch values, we'll just assume
    866      * that there's a limitation by pixels, and that it's the same as
    867      * maxX.
    868      *
    869      * We want maxPitchPixels or maxPitchBytes to be set so we can check
    870      * pixmaps against the max pitch in exaCreatePixmap() -- it matters
    871      * whether a pixmap is rejected because of its pitch or
    872      * because of its width.
    873      */
    874     if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) {
    875         pScreenInfo->maxPitchPixels = pScreenInfo->maxX;
    876     }
    877 
    878     ps = GetPictureScreenIfSet(pScreen);
    879 
    880     if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) {
    881         LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n",
    882                    pScreen->myNum);
    883         return FALSE;
    884     }
    885 
    886     pExaScr = calloc(sizeof(ExaScreenPrivRec), 1);
    887     if (!pExaScr) {
    888         LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
    889                    pScreen->myNum);
    890         return FALSE;
    891     }
    892 
    893     pExaScr->info = pScreenInfo;
    894 
    895     dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr);
    896 
    897     pExaScr->migration = ExaMigrationAlways;
    898 
    899     exaDDXDriverInit(pScreen);
    900 
    901     if (!dixRegisterScreenSpecificPrivateKey
    902         (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) {
    903         LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n",
    904                    pScreen->myNum);
    905         return FALSE;
    906     }
    907 
    908     /*
    909      * Replace various fb screen functions
    910      */
    911     if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
    912         (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) ||
    913          (pExaScr->info->flags & EXA_MIXED_PIXMAPS)))
    914         wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
    915     if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
    916         !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
    917         wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
    918     wrap(pExaScr, pScreen, CreateGC, exaCreateGC);
    919     wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen);
    920     wrap(pExaScr, pScreen, GetImage, exaGetImage);
    921     wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans);
    922     wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow);
    923     wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes);
    924     wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion);
    925     wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources);
    926 
    927     if (ps) {
    928         wrap(pExaScr, ps, Composite, exaComposite);
    929         if (pScreenInfo->PrepareComposite) {
    930             wrap(pExaScr, ps, Glyphs, exaGlyphs);
    931         }
    932         else {
    933             wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs);
    934         }
    935         wrap(pExaScr, ps, Trapezoids, exaTrapezoids);
    936         wrap(pExaScr, ps, Triangles, exaTriangles);
    937         wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps);
    938     }
    939 
    940 #ifdef MITSHM
    941     /*
    942      * Don't allow shared pixmaps.
    943      */
    944     ShmRegisterFuncs(pScreen, &exaShmFuncs);
    945 #endif
    946     /*
    947      * Hookup offscreen pixmaps
    948      */
    949     if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) {
    950         if (!dixRegisterScreenSpecificPrivateKey
    951             (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP,
    952              sizeof(ExaPixmapPrivRec))) {
    953             LogMessage(X_WARNING,
    954                        "EXA(%d): Failed to allocate pixmap private\n",
    955                        pScreen->myNum);
    956             return FALSE;
    957         }
    958         if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) {
    959             if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) {
    960                 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed);
    961                 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed);
    962                 wrap(pExaScr, pScreen, ModifyPixmapHeader,
    963                      exaModifyPixmapHeader_mixed);
    964                 wrap(pExaScr, pScreen, SharePixmapBacking, exaSharePixmapBacking_mixed);
    965                 wrap(pExaScr, pScreen, SetSharedPixmapBacking, exaSetSharedPixmapBacking_mixed);
    966 
    967                 pExaScr->do_migration = exaDoMigration_mixed;
    968                 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed;
    969                 pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
    970                 pExaScr->do_move_out_pixmap = NULL;
    971                 pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
    972             }
    973             else {
    974                 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
    975                 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
    976                 wrap(pExaScr, pScreen, ModifyPixmapHeader,
    977                      exaModifyPixmapHeader_driver);
    978                 pExaScr->do_migration = NULL;
    979                 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver;
    980                 pExaScr->do_move_in_pixmap = NULL;
    981                 pExaScr->do_move_out_pixmap = NULL;
    982                 pExaScr->prepare_access_reg = NULL;
    983             }
    984         }
    985         else {
    986             wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
    987             wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
    988             wrap(pExaScr, pScreen, ModifyPixmapHeader,
    989                  exaModifyPixmapHeader_classic);
    990             pExaScr->do_migration = exaDoMigration_classic;
    991             pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic;
    992             pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
    993             pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
    994             pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
    995         }
    996         if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
    997             LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
    998                        pScreen->myNum,
    999                        pExaScr->info->memorySize -
   1000                        pExaScr->info->offScreenBase);
   1001         }
   1002         else {
   1003             LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n",
   1004                        pScreen->myNum);
   1005 
   1006         }
   1007     }
   1008     else
   1009         LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
   1010 
   1011     if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
   1012         DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
   1013                     pExaScr->info->memorySize));
   1014         if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
   1015             if (!exaOffscreenInit(pScreen)) {
   1016                 LogMessage(X_WARNING,
   1017                            "EXA(%d): Offscreen pixmap setup failed\n",
   1018                            pScreen->myNum);
   1019                 return FALSE;
   1020             }
   1021         }
   1022     }
   1023 
   1024     if (ps->Glyphs == exaGlyphs)
   1025         exaGlyphsInit(pScreen);
   1026 
   1027     LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
   1028                " operations:\n", pScreen->myNum);
   1029     assert(pScreenInfo->PrepareSolid != NULL);
   1030     LogMessage(X_INFO, "        Solid\n");
   1031     assert(pScreenInfo->PrepareCopy != NULL);
   1032     LogMessage(X_INFO, "        Copy\n");
   1033     if (pScreenInfo->PrepareComposite != NULL) {
   1034         LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
   1035     }
   1036     if (pScreenInfo->UploadToScreen != NULL) {
   1037         LogMessage(X_INFO, "        UploadToScreen\n");
   1038     }
   1039     if (pScreenInfo->DownloadFromScreen != NULL) {
   1040         LogMessage(X_INFO, "        DownloadFromScreen\n");
   1041     }
   1042 
   1043     return TRUE;
   1044 }
   1045 
   1046 /**
   1047  * exaDriverFini tears down EXA on a given screen.
   1048  *
   1049  * @param pScreen screen being torn down.
   1050  */
   1051 void
   1052 exaDriverFini(ScreenPtr pScreen)
   1053 {
   1054     /*right now does nothing */
   1055 }
   1056 
   1057 /**
   1058  * exaMarkSync() should be called after any asynchronous drawing by the hardware.
   1059  *
   1060  * @param pScreen screen which drawing occurred on
   1061  *
   1062  * exaMarkSync() sets a flag to indicate that some asynchronous drawing has
   1063  * happened and a WaitSync() will be necessary before relying on the contents of
   1064  * offscreen memory from the CPU's perspective.  It also calls an optional
   1065  * driver MarkSync() callback, the return value of which may be used to do partial
   1066  * synchronization with the hardware in the future.
   1067  */
   1068 void
   1069 exaMarkSync(ScreenPtr pScreen)
   1070 {
   1071     ExaScreenPriv(pScreen);
   1072 
   1073     pExaScr->info->needsSync = TRUE;
   1074     if (pExaScr->info->MarkSync != NULL) {
   1075         pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen);
   1076     }
   1077 }
   1078 
   1079 /**
   1080  * exaWaitSync() ensures that all drawing has been completed.
   1081  *
   1082  * @param pScreen screen being synchronized.
   1083  *
   1084  * Calls down into the driver to ensure that all previous drawing has completed.
   1085  * It should always be called before relying on the framebuffer contents
   1086  * reflecting previous drawing, from a CPU perspective.
   1087  */
   1088 void
   1089 exaWaitSync(ScreenPtr pScreen)
   1090 {
   1091     ExaScreenPriv(pScreen);
   1092 
   1093     if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
   1094         (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker);
   1095         pExaScr->info->needsSync = FALSE;
   1096     }
   1097 }
   1098 
   1099 /**
   1100  * Performs migration of the pixmaps according to the operation information
   1101  * provided in pixmaps and can_accel and the migration scheme chosen in the
   1102  * config file.
   1103  */
   1104 void
   1105 exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
   1106 {
   1107     ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
   1108 
   1109     ExaScreenPriv(pScreen);
   1110 
   1111     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
   1112         return;
   1113 
   1114     if (pExaScr->do_migration)
   1115         (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel);
   1116 }
   1117 
   1118 void
   1119 exaMoveInPixmap(PixmapPtr pPixmap)
   1120 {
   1121     ScreenPtr pScreen = pPixmap->drawable.pScreen;
   1122 
   1123     ExaScreenPriv(pScreen);
   1124 
   1125     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
   1126         return;
   1127 
   1128     if (pExaScr->do_move_in_pixmap)
   1129         (*pExaScr->do_move_in_pixmap) (pPixmap);
   1130 }
   1131 
   1132 void
   1133 exaMoveOutPixmap(PixmapPtr pPixmap)
   1134 {
   1135     ScreenPtr pScreen = pPixmap->drawable.pScreen;
   1136 
   1137     ExaScreenPriv(pScreen);
   1138 
   1139     if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
   1140         return;
   1141 
   1142     if (pExaScr->do_move_out_pixmap)
   1143         (*pExaScr->do_move_out_pixmap) (pPixmap);
   1144 }