xserver

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

dri.c (23459B)


      1 /**************************************************************************
      2 
      3    Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
      4    Copyright 2000 VA Linux Systems, Inc.
      5    Copyright (c) 2002-2012 Apple Computer, Inc.
      6    All Rights Reserved.
      7 
      8    Permission is hereby granted, free of charge, to any person obtaining a
      9    copy of this software and associated documentation files (the
     10    "Software"), to deal in the Software without restriction, including
     11    without limitation the rights to use, copy, modify, merge, publish,
     12    distribute, sub license, and/or sell copies of the Software, and to
     13    permit persons to whom the Software is furnished to do so, subject to
     14    the following conditions:
     15 
     16    The above copyright notice and this permission notice (including the
     17    next paragraph) shall be included in all copies or substantial portions
     18    of the Software.
     19 
     20    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     21    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     23    IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     24    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     25    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     26    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     27 
     28 **************************************************************************/
     29 
     30 /*
     31  * Authors:
     32  *   Jens Owen <jens@valinux.com>
     33  *   Rickard E. (Rik) Faith <faith@valinux.com>
     34  *   Jeremy Huddleston <jeremyhu@apple.com>
     35  */
     36 
     37 #ifdef HAVE_DIX_CONFIG_H
     38 #include <dix-config.h>
     39 #endif
     40 
     41 #include <sys/time.h>
     42 #include <unistd.h>
     43 
     44 #include <X11/X.h>
     45 #include <X11/Xproto.h>
     46 #include <fcntl.h>
     47 #include <sys/mman.h>
     48 #include <sys/types.h>
     49 #include <sys/stat.h>
     50 #include "misc.h"
     51 #include "dixstruct.h"
     52 #include "extnsionst.h"
     53 #include "extinit.h"
     54 #include "colormapst.h"
     55 #include "cursorstr.h"
     56 #include "scrnintstr.h"
     57 #include "windowstr.h"
     58 #include "servermd.h"
     59 #define _APPLEDRI_SERVER_
     60 #include "appledristr.h"
     61 #include "swaprep.h"
     62 #include "dri.h"
     63 #include "dristruct.h"
     64 #include "mi.h"
     65 #include "mipointer.h"
     66 #include "rootless.h"
     67 #include "rootlessCommon.h"
     68 #include "x-hash.h"
     69 #include "x-hook.h"
     70 #include "driWrap.h"
     71 
     72 static DevPrivateKeyRec DRIScreenPrivKeyRec;
     73 #define DRIScreenPrivKey       (&DRIScreenPrivKeyRec)
     74 static DevPrivateKeyRec DRIWindowPrivKeyRec;
     75 #define DRIWindowPrivKey       (&DRIWindowPrivKeyRec)
     76 static DevPrivateKeyRec DRIPixmapPrivKeyRec;
     77 #define DRIPixmapPrivKey       (&DRIPixmapPrivKeyRec)
     78 static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec;
     79 #define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
     80 
     81 static RESTYPE DRIDrawablePrivResType;
     82 
     83 static x_hash_table *surface_hash;      /* maps surface ids -> drawablePrivs */
     84 
     85 static Bool
     86 DRIFreePixmapImp(DrawablePtr pDrawable);
     87 
     88 typedef struct {
     89     DrawablePtr pDrawable;
     90     int refCount;
     91     int bytesPerPixel;
     92     int width;
     93     int height;
     94     char shmPath[PATH_MAX];
     95     int fd; /* From shm_open (for now) */
     96     size_t length; /* length of buffer */
     97     void *buffer;
     98 } DRIPixmapBuffer, *DRIPixmapBufferPtr;
     99 
    100 Bool
    101 DRIScreenInit(ScreenPtr pScreen)
    102 {
    103     DRIScreenPrivPtr pDRIPriv;
    104     int i;
    105 
    106     if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
    107         return FALSE;
    108     if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
    109         return FALSE;
    110     if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0))
    111         return FALSE;
    112     if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0))
    113         return FALSE;
    114 
    115     pDRIPriv = (DRIScreenPrivPtr)calloc(1, sizeof(DRIScreenPrivRec));
    116     if (!pDRIPriv) {
    117         dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
    118         return FALSE;
    119     }
    120 
    121     dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
    122     pDRIPriv->directRenderingSupport = TRUE;
    123     pDRIPriv->nrWindows = 0;
    124 
    125     /* Initialize drawable tables */
    126     for (i = 0; i < DRI_MAX_DRAWABLES; i++) {
    127         pDRIPriv->DRIDrawables[i] = NULL;
    128     }
    129 
    130     return TRUE;
    131 }
    132 
    133 Bool
    134 DRIFinishScreenInit(ScreenPtr pScreen)
    135 {
    136     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    137 
    138     /* Wrap DRI support */
    139     pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
    140     pScreen->CopyWindow = DRICopyWindow;
    141 
    142     pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
    143     pScreen->ClipNotify = DRIClipNotify;
    144 
    145     //    ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
    146 
    147     return DRIWrapInit(pScreen);
    148 }
    149 
    150 void
    151 DRICloseScreen(ScreenPtr pScreen)
    152 {
    153     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    154 
    155     if (pDRIPriv && pDRIPriv->directRenderingSupport) {
    156         free(pDRIPriv);
    157         dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
    158     }
    159 }
    160 
    161 Bool
    162 DRIExtensionInit(void)
    163 {
    164     DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
    165                                                    "DRIDrawable");
    166 
    167     return DRIDrawablePrivResType != 0;
    168 }
    169 
    170 void
    171 DRIReset(void)
    172 {
    173     /*
    174      * This stub routine is called when the X Server recycles, resources
    175      * allocated by DRIExtensionInit need to be managed here.
    176      *
    177      * Currently this routine is a stub because all the interesting resources
    178      * are managed via the screen init process.
    179      */
    180 }
    181 
    182 Bool
    183 DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
    184 {
    185     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    186 
    187     if (pDRIPriv)
    188         *isCapable = pDRIPriv->directRenderingSupport;
    189     else
    190         *isCapable = FALSE;
    191 
    192     return TRUE;
    193 }
    194 
    195 Bool
    196 DRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
    197 {
    198 #if 0
    199     /* FIXME: something? */
    200 
    201     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    202 
    203     if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
    204 #endif
    205     return TRUE;
    206 }
    207 
    208 static void
    209 DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
    210 {
    211     xp_window_changes wc;
    212     unsigned int flags = 0;
    213 
    214     if (pDRIDrawablePriv->sid == 0)
    215         return;
    216 
    217     wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888
    218                 : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL);
    219     if (wc.depth != XP_DEPTH_NIL)
    220         flags |= XP_DEPTH;
    221 
    222     if (pDraw->type == DRAWABLE_WINDOW) {
    223         WindowPtr pWin = (WindowPtr)pDraw;
    224         WindowPtr pTopWin = TopLevelParent(pWin);
    225 
    226         wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth);
    227         wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth);
    228         wc.width = pWin->drawable.width + 2 * pWin->borderWidth;
    229         wc.height = pWin->drawable.height + 2 * pWin->borderWidth;
    230         wc.bit_gravity = XP_GRAVITY_NONE;
    231 
    232         wc.shape_nrects = RegionNumRects(&pWin->clipList);
    233         wc.shape_rects = RegionRects(&pWin->clipList);
    234         wc.shape_tx = -(pTopWin->drawable.x - pTopWin->borderWidth);
    235         wc.shape_ty = -(pTopWin->drawable.y - pTopWin->borderWidth);
    236 
    237         flags |= XP_BOUNDS | XP_SHAPE;
    238 
    239     }
    240     else if (pDraw->type == DRAWABLE_PIXMAP) {
    241         wc.x = 0;
    242         wc.y = 0;
    243         wc.width = pDraw->width;
    244         wc.height = pDraw->height;
    245         wc.bit_gravity = XP_GRAVITY_NONE;
    246         flags |= XP_BOUNDS;
    247     }
    248 
    249     xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc);
    250 }
    251 
    252 /* Return NULL if an error occurs. */
    253 static DRIDrawablePrivPtr
    254 CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin,
    255                        xp_window_id *widPtr)
    256 {
    257     DRIDrawablePrivPtr pDRIDrawablePriv;
    258     xp_window_id wid = 0;
    259 
    260     *widPtr = 0;
    261 
    262     pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
    263 
    264     if (pDRIDrawablePriv == NULL) {
    265         xp_error err;
    266         xp_window_changes wc;
    267 
    268         /* allocate a DRI Window Private record */
    269         if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) {
    270             return NULL;
    271         }
    272 
    273         pDRIDrawablePriv->pDraw = (DrawablePtr)pWin;
    274         pDRIDrawablePriv->pScreen = pScreen;
    275         pDRIDrawablePriv->refCount = 0;
    276         pDRIDrawablePriv->drawableIndex = -1;
    277         pDRIDrawablePriv->notifiers = NULL;
    278 
    279         /* find the physical window */
    280         wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE));
    281 
    282         if (wid == 0) {
    283             free(pDRIDrawablePriv);
    284             return NULL;
    285         }
    286 
    287         /* allocate the physical surface */
    288         err = xp_create_surface(wid, &pDRIDrawablePriv->sid);
    289 
    290         if (err != Success) {
    291             free(pDRIDrawablePriv);
    292             return NULL;
    293         }
    294 
    295         /* Make it visible */
    296         wc.stack_mode = XP_MAPPED_ABOVE;
    297         wc.sibling = 0;
    298         err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc);
    299 
    300         if (err != Success) {
    301             xp_destroy_surface(pDRIDrawablePriv->sid);
    302             free(pDRIDrawablePriv);
    303             return NULL;
    304         }
    305 
    306         /* save private off of preallocated index */
    307         dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
    308                       pDRIDrawablePriv);
    309     }
    310 
    311     *widPtr = wid;
    312 
    313     return pDRIDrawablePriv;
    314 }
    315 
    316 /* Return NULL if an error occurs. */
    317 static DRIDrawablePrivPtr
    318 CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix)
    319 {
    320     DRIDrawablePrivPtr pDRIDrawablePriv;
    321 
    322     pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
    323 
    324     if (pDRIDrawablePriv == NULL) {
    325         xp_error err;
    326 
    327         /* allocate a DRI Window Private record */
    328         if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) {
    329             return NULL;
    330         }
    331 
    332         pDRIDrawablePriv->pDraw = (DrawablePtr)pPix;
    333         pDRIDrawablePriv->pScreen = pScreen;
    334         pDRIDrawablePriv->refCount = 0;
    335         pDRIDrawablePriv->drawableIndex = -1;
    336         pDRIDrawablePriv->notifiers = NULL;
    337 
    338         /* Passing a null window id to Xplugin in 10.3+ asks for
    339            an accelerated offscreen surface. */
    340 
    341         err = xp_create_surface(0, &pDRIDrawablePriv->sid);
    342         if (err != Success) {
    343             free(pDRIDrawablePriv);
    344             return NULL;
    345         }
    346 
    347         /*
    348          * The DRIUpdateSurface will be called to resize the surface
    349          * after this function, if the export is successful.
    350          */
    351 
    352         /* save private off of preallocated index */
    353         dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey,
    354                       pDRIDrawablePriv);
    355     }
    356 
    357     return pDRIDrawablePriv;
    358 }
    359 
    360 Bool
    361 DRICreateSurface(ScreenPtr pScreen, Drawable id,
    362                  DrawablePtr pDrawable, xp_client_id client_id,
    363                  xp_surface_id *surface_id, unsigned int ret_key[2],
    364                  void (*notify)(void *arg, void *data), void *notify_data)
    365 {
    366     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    367     xp_window_id wid = 0;
    368     DRIDrawablePrivPtr pDRIDrawablePriv;
    369 
    370     if (pDrawable->type == DRAWABLE_WINDOW) {
    371         /* <rdar://problem/12338921>
    372          * http://bugs.winehq.org/show_bug.cgi?id=31751
    373          */
    374         RootlessStopDrawing((WindowPtr)pDrawable, FALSE);
    375 
    376         pDRIDrawablePriv = CreateSurfaceForWindow(pScreen,
    377                                                   (WindowPtr)pDrawable, &wid);
    378 
    379         if (NULL == pDRIDrawablePriv)
    380             return FALSE;  /*error*/
    381     } else if (pDrawable->type == DRAWABLE_PIXMAP) {
    382         pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen,
    383                                                   (PixmapPtr)pDrawable);
    384 
    385         if (NULL == pDRIDrawablePriv)
    386             return FALSE;  /*error*/
    387     } else {
    388         /* We handle GLXPbuffers in a different way (via CGL). */
    389         return FALSE;
    390     }
    391 
    392     /* Finish initialization of new surfaces */
    393     if (pDRIDrawablePriv->refCount == 0) {
    394         unsigned int key[2] = { 0 };
    395         xp_error err;
    396 
    397         /* try to give the client access to the surface */
    398         if (client_id != 0) {
    399             /*
    400              * Xplugin accepts a 0 wid if the surface id is offscreen, such
    401              * as for a pixmap.
    402              */
    403             err = xp_export_surface(wid, pDRIDrawablePriv->sid,
    404                                     client_id, key);
    405             if (err != Success) {
    406                 xp_destroy_surface(pDRIDrawablePriv->sid);
    407                 free(pDRIDrawablePriv);
    408 
    409                 /*
    410                  * Now set the dix privates to NULL that were previously set.
    411                  * This prevents reusing an invalid pointer.
    412                  */
    413                 if (pDrawable->type == DRAWABLE_WINDOW) {
    414                     WindowPtr pWin = (WindowPtr)pDrawable;
    415 
    416                     dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
    417                 }
    418                 else if (pDrawable->type == DRAWABLE_PIXMAP) {
    419                     PixmapPtr pPix = (PixmapPtr)pDrawable;
    420 
    421                     dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
    422                 }
    423 
    424                 return FALSE;
    425             }
    426         }
    427 
    428         pDRIDrawablePriv->key[0] = key[0];
    429         pDRIDrawablePriv->key[1] = key[1];
    430 
    431         ++pDRIPriv->nrWindows;
    432 
    433         /* and stash it by surface id */
    434         if (surface_hash == NULL)
    435             surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
    436         x_hash_table_insert(surface_hash,
    437                             x_cvt_uint_to_vptr(
    438                                 pDRIDrawablePriv->sid), pDRIDrawablePriv);
    439 
    440         /* track this in case this window is destroyed */
    441         AddResource(id, DRIDrawablePrivResType, (void *)pDrawable);
    442 
    443         /* Initialize shape */
    444         DRIUpdateSurface(pDRIDrawablePriv, pDrawable);
    445     }
    446 
    447     pDRIDrawablePriv->refCount++;
    448 
    449     *surface_id = pDRIDrawablePriv->sid;
    450 
    451     if (ret_key != NULL) {
    452         ret_key[0] = pDRIDrawablePriv->key[0];
    453         ret_key[1] = pDRIDrawablePriv->key[1];
    454     }
    455 
    456     if (notify != NULL) {
    457         pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers,
    458                                                  notify, notify_data);
    459     }
    460 
    461     return TRUE;
    462 }
    463 
    464 Bool
    465 DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
    466                   void (*notify)(void *, void *), void *notify_data)
    467 {
    468     DRIDrawablePrivPtr pDRIDrawablePriv;
    469 
    470     if (pDrawable->type == DRAWABLE_WINDOW) {
    471         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
    472     }
    473     else if (pDrawable->type == DRAWABLE_PIXMAP) {
    474         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
    475     }
    476     else {
    477         return FALSE;
    478     }
    479 
    480     if (pDRIDrawablePriv != NULL) {
    481         /*
    482          * This doesn't seem to be used, because notify is NULL in all callers.
    483          */
    484 
    485         if (notify != NULL) {
    486             pDRIDrawablePriv->notifiers = x_hook_remove(
    487                 pDRIDrawablePriv->notifiers,
    488                 notify, notify_data);
    489         }
    490 
    491         --pDRIDrawablePriv->refCount;
    492 
    493         /*
    494          * Check if the drawable privates still have a reference to the
    495          * surface.
    496          */
    497 
    498         if (pDRIDrawablePriv->refCount <= 0) {
    499             /*
    500              * This calls back to DRIDrawablePrivDelete which
    501              * frees the private area and dispatches events, if needed.
    502              */
    503             FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
    504         }
    505     }
    506 
    507     return TRUE;
    508 }
    509 
    510 /*
    511  * The assumption is that this is called when the refCount of a surface
    512  * drops to <= 0, or the window/pixmap is destroyed.
    513  */
    514 Bool
    515 DRIDrawablePrivDelete(void *pResource, XID id)
    516 {
    517     DrawablePtr pDrawable = (DrawablePtr)pResource;
    518     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
    519     DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
    520     WindowPtr pWin = NULL;
    521     PixmapPtr pPix = NULL;
    522 
    523     if (pDrawable->type == DRAWABLE_WINDOW) {
    524         pWin = (WindowPtr)pDrawable;
    525         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
    526     }
    527     else if (pDrawable->type == DRAWABLE_PIXMAP) {
    528         pPix = (PixmapPtr)pDrawable;
    529         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
    530     }
    531 
    532     if (pDRIDrawablePriv == NULL) {
    533         /*
    534          * We reuse __func__ and the resource type for the GLXPixmap code.
    535          * Attempt to free a pixmap buffer associated with the resource
    536          * if possible.
    537          */
    538         return DRIFreePixmapImp(pDrawable);
    539     }
    540 
    541     if (pDRIDrawablePriv->drawableIndex != -1) {
    542         /* release drawable table entry */
    543         pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
    544     }
    545 
    546     if (pDRIDrawablePriv->sid != 0) {
    547         DRISurfaceNotify(pDRIDrawablePriv->sid,
    548                          AppleDRISurfaceNotifyDestroyed);
    549     }
    550 
    551     if (pDRIDrawablePriv->notifiers != NULL)
    552         x_hook_free(pDRIDrawablePriv->notifiers);
    553 
    554     free(pDRIDrawablePriv);
    555 
    556     if (pDrawable->type == DRAWABLE_WINDOW) {
    557         dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
    558     }
    559     else if (pDrawable->type == DRAWABLE_PIXMAP) {
    560         dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
    561     }
    562 
    563     --pDRIPriv->nrWindows;
    564 
    565     return TRUE;
    566 }
    567 
    568 void
    569 DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    570 {
    571     ScreenPtr pScreen = pWin->drawable.pScreen;
    572     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    573     DRIDrawablePrivPtr pDRIDrawablePriv;
    574 
    575     if (pDRIPriv->nrWindows > 0) {
    576         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
    577         if (pDRIDrawablePriv != NULL) {
    578             DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
    579         }
    580     }
    581 
    582     /* unwrap */
    583     pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
    584 
    585     /* call lower layers */
    586     (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
    587 
    588     /* rewrap */
    589     pScreen->CopyWindow = DRICopyWindow;
    590 }
    591 
    592 void
    593 DRIClipNotify(WindowPtr pWin, int dx, int dy)
    594 {
    595     ScreenPtr pScreen = pWin->drawable.pScreen;
    596     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
    597     DRIDrawablePrivPtr pDRIDrawablePriv;
    598 
    599     if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
    600         DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
    601     }
    602 
    603     if (pDRIPriv->wrap.ClipNotify) {
    604         pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
    605 
    606         (*pScreen->ClipNotify)(pWin, dx, dy);
    607 
    608         pScreen->ClipNotify = DRIClipNotify;
    609     }
    610 }
    611 
    612 /* This lets us get at the unwrapped functions so that they can correctly
    613  * call the lower level functions, and choose whether they will be
    614  * called at every level of recursion (eg in validatetree).
    615  */
    616 DRIWrappedFuncsRec *
    617 DRIGetWrappedFuncs(ScreenPtr pScreen)
    618 {
    619     return &(DRI_SCREEN_PRIV(pScreen)->wrap);
    620 }
    621 
    622 void
    623 DRIQueryVersion(int *majorVersion,
    624                 int *minorVersion,
    625                 int *patchVersion)
    626 {
    627     *majorVersion = APPLE_DRI_MAJOR_VERSION;
    628     *minorVersion = APPLE_DRI_MINOR_VERSION;
    629     *patchVersion = APPLE_DRI_PATCH_VERSION;
    630 }
    631 
    632 /*
    633  * Note: this also cleans up the hash table in addition to notifying clients.
    634  * The sid/surface-id should not be used after this, because it will be
    635  * invalid.
    636  */
    637 void
    638 DRISurfaceNotify(xp_surface_id id, int kind)
    639 {
    640     DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
    641     DRISurfaceNotifyArg arg;
    642 
    643     arg.id = id;
    644     arg.kind = kind;
    645 
    646     if (surface_hash != NULL) {
    647         pDRIDrawablePriv = x_hash_table_lookup(surface_hash,
    648                                                x_cvt_uint_to_vptr(id), NULL);
    649     }
    650 
    651     if (pDRIDrawablePriv == NULL)
    652         return;
    653 
    654     if (kind == AppleDRISurfaceNotifyDestroyed) {
    655         x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id));
    656     }
    657 
    658     x_hook_run(pDRIDrawablePriv->notifiers, &arg);
    659 
    660     if (kind == AppleDRISurfaceNotifyDestroyed) {
    661         xp_error error;
    662 
    663         error = xp_destroy_surface(pDRIDrawablePriv->sid);
    664 
    665         if (error)
    666             ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error);
    667 
    668         /* Guard against reuse, even though we are freeing after this. */
    669         pDRIDrawablePriv->sid = 0;
    670 
    671         FreeResourceByType(pDRIDrawablePriv->pDraw->id,
    672                            DRIDrawablePrivResType, FALSE);
    673     }
    674 }
    675 
    676 /*
    677  * This creates a shared memory buffer for use with GLXPixmaps
    678  * and AppleSGLX.
    679  */
    680 Bool
    681 DRICreatePixmap(ScreenPtr pScreen, Drawable id,
    682                 DrawablePtr pDrawable, char *path,
    683                 size_t pathmax)
    684 {
    685     DRIPixmapBufferPtr shared;
    686     PixmapPtr pPix;
    687 
    688     if (pDrawable->type != DRAWABLE_PIXMAP)
    689         return FALSE;
    690 
    691     pPix = (PixmapPtr)pDrawable;
    692 
    693     shared = malloc(sizeof(*shared));
    694     if (NULL == shared) {
    695         FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__);
    696     }
    697 
    698     shared->pDrawable = pDrawable;
    699     shared->refCount = 1;
    700 
    701     if (pDrawable->bitsPerPixel >= 24) {
    702         shared->bytesPerPixel = 4;
    703     }
    704     else if (pDrawable->bitsPerPixel <= 16) {
    705         shared->bytesPerPixel = 2;
    706     }
    707 
    708     shared->width = pDrawable->width;
    709     shared->height = pDrawable->height;
    710 
    711     if (-1 == snprintf(shared->shmPath, sizeof(shared->shmPath),
    712                        "%d_0x%lx", getpid(),
    713                        (unsigned long)id)) {
    714         FatalError("buffer overflow in %s\n", __func__);
    715     }
    716 
    717     shared->fd = shm_open(shared->shmPath,
    718                           O_RDWR | O_EXCL | O_CREAT,
    719                           S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
    720 
    721     if (-1 == shared->fd) {
    722         free(shared);
    723         return FALSE;
    724     }
    725 
    726     shared->length = shared->width * shared->height * shared->bytesPerPixel;
    727 
    728     if (-1 == ftruncate(shared->fd, shared->length)) {
    729         ErrorF("failed to ftruncate (extend) file.");
    730         shm_unlink(shared->shmPath);
    731         close(shared->fd);
    732         free(shared);
    733         return FALSE;
    734     }
    735 
    736     shared->buffer = mmap(NULL, shared->length,
    737                           PROT_READ | PROT_WRITE,
    738                           MAP_FILE | MAP_SHARED, shared->fd, 0);
    739 
    740     if (MAP_FAILED == shared->buffer) {
    741         ErrorF("failed to mmap shared memory.");
    742         shm_unlink(shared->shmPath);
    743         close(shared->fd);
    744         free(shared);
    745         return FALSE;
    746     }
    747 
    748     strlcpy(path, shared->shmPath, pathmax);
    749 
    750     dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared);
    751 
    752     AddResource(id, DRIDrawablePrivResType, (void *)pDrawable);
    753 
    754     return TRUE;
    755 }
    756 
    757 Bool
    758 DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height,
    759                  int *pitch, int *bpp, void **ptr)
    760 {
    761     PixmapPtr pPix;
    762     DRIPixmapBufferPtr shared;
    763 
    764     if (pDrawable->type != DRAWABLE_PIXMAP)
    765         return FALSE;
    766 
    767     pPix = (PixmapPtr)pDrawable;
    768 
    769     shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
    770 
    771     if (NULL == shared)
    772         return FALSE;
    773 
    774     assert(pDrawable->width == shared->width);
    775     assert(pDrawable->height == shared->height);
    776 
    777     *width = shared->width;
    778     *height = shared->height;
    779     *bpp = shared->bytesPerPixel;
    780     *pitch = shared->width * shared->bytesPerPixel;
    781     *ptr = shared->buffer;
    782 
    783     return TRUE;
    784 }
    785 
    786 static Bool
    787 DRIFreePixmapImp(DrawablePtr pDrawable)
    788 {
    789     DRIPixmapBufferPtr shared;
    790     PixmapPtr pPix;
    791 
    792     if (pDrawable->type != DRAWABLE_PIXMAP)
    793         return FALSE;
    794 
    795     pPix = (PixmapPtr)pDrawable;
    796 
    797     shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
    798 
    799     if (NULL == shared)
    800         return FALSE;
    801 
    802     close(shared->fd);
    803     munmap(shared->buffer, shared->length);
    804     shm_unlink(shared->shmPath);
    805     free(shared);
    806 
    807     dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (void *)NULL);
    808 
    809     return TRUE;
    810 }
    811 
    812 void
    813 DRIDestroyPixmap(DrawablePtr pDrawable)
    814 {
    815     if (DRIFreePixmapImp(pDrawable))
    816         FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE);
    817 
    818 }