1706f2543Smrg/**************************************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4706f2543SmrgCopyright 2000 VA Linux Systems, Inc.
5706f2543SmrgCopyright (c) 2002, 2009 Apple Computer, Inc.
6706f2543SmrgAll Rights Reserved.
7706f2543Smrg
8706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a
9706f2543Smrgcopy of this software and associated documentation files (the
10706f2543Smrg"Software"), to deal in the Software without restriction, including
11706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish,
12706f2543Smrgdistribute, sub license, and/or sell copies of the Software, and to
13706f2543Smrgpermit persons to whom the Software is furnished to do so, subject to
14706f2543Smrgthe following conditions:
15706f2543Smrg
16706f2543SmrgThe above copyright notice and this permission notice (including the
17706f2543Smrgnext paragraph) shall be included in all copies or substantial portions
18706f2543Smrgof the Software.
19706f2543Smrg
20706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23706f2543SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24706f2543SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25706f2543SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26706f2543SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27706f2543Smrg
28706f2543Smrg**************************************************************************/
29706f2543Smrg
30706f2543Smrg/*
31706f2543Smrg * Authors:
32706f2543Smrg *   Jens Owen <jens@valinux.com>
33706f2543Smrg *   Rickard E. (Rik) Faith <faith@valinux.com>
34706f2543Smrg *
35706f2543Smrg */
36706f2543Smrg
37706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
38706f2543Smrg#include <dix-config.h>
39706f2543Smrg#endif
40706f2543Smrg
41706f2543Smrg#ifdef XFree86LOADER
42706f2543Smrg#include "xf86.h"
43706f2543Smrg#include "xf86_ansic.h"
44706f2543Smrg#else
45706f2543Smrg#include <sys/time.h>
46706f2543Smrg#include <unistd.h>
47706f2543Smrg#endif
48706f2543Smrg
49706f2543Smrg#include <X11/X.h>
50706f2543Smrg#include <X11/Xproto.h>
51706f2543Smrg#include <fcntl.h>
52706f2543Smrg#include <sys/mman.h>
53706f2543Smrg#include <sys/types.h>
54706f2543Smrg#include <sys/stat.h>
55706f2543Smrg#include "misc.h"
56706f2543Smrg#include "dixstruct.h"
57706f2543Smrg#include "extnsionst.h"
58706f2543Smrg#include "colormapst.h"
59706f2543Smrg#include "cursorstr.h"
60706f2543Smrg#include "scrnintstr.h"
61706f2543Smrg#include "windowstr.h"
62706f2543Smrg#include "servermd.h"
63706f2543Smrg#define _APPLEDRI_SERVER_
64706f2543Smrg#include "appledristr.h"
65706f2543Smrg#include "swaprep.h"
66706f2543Smrg#include "dri.h"
67706f2543Smrg#include "dristruct.h"
68706f2543Smrg#include "mi.h"
69706f2543Smrg#include "mipointer.h"
70706f2543Smrg#include "rootless.h"
71706f2543Smrg#include "x-hash.h"
72706f2543Smrg#include "x-hook.h"
73706f2543Smrg#include "driWrap.h"
74706f2543Smrg
75706f2543Smrg#include <AvailabilityMacros.h>
76706f2543Smrg
77706f2543Smrgstatic DevPrivateKeyRec DRIScreenPrivKeyRec;
78706f2543Smrg#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
79706f2543Smrgstatic DevPrivateKeyRec DRIWindowPrivKeyRec;
80706f2543Smrg#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
81706f2543Smrgstatic DevPrivateKeyRec DRIPixmapPrivKeyRec;
82706f2543Smrg#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec)
83706f2543Smrgstatic DevPrivateKeyRec DRIPixmapBufferPrivKeyRec;
84706f2543Smrg#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
85706f2543Smrg
86706f2543Smrgstatic RESTYPE DRIDrawablePrivResType;
87706f2543Smrg
88706f2543Smrgstatic x_hash_table *surface_hash;      /* maps surface ids -> drawablePrivs */
89706f2543Smrg
90706f2543Smrgstatic Bool DRIFreePixmapImp(DrawablePtr pDrawable);
91706f2543Smrg
92706f2543Smrgtypedef struct {
93706f2543Smrg    DrawablePtr pDrawable;
94706f2543Smrg    int refCount;
95706f2543Smrg    int bytesPerPixel;
96706f2543Smrg    int width;
97706f2543Smrg    int height;
98706f2543Smrg    char shmPath[PATH_MAX];
99706f2543Smrg    int fd; /* From shm_open (for now) */
100706f2543Smrg    size_t length; /* length of buffer */
101706f2543Smrg    void *buffer;
102706f2543Smrg} DRIPixmapBuffer, *DRIPixmapBufferPtr;
103706f2543Smrg
104706f2543SmrgBool
105706f2543SmrgDRIScreenInit(ScreenPtr pScreen)
106706f2543Smrg{
107706f2543Smrg    DRIScreenPrivPtr    pDRIPriv;
108706f2543Smrg    int                 i;
109706f2543Smrg
110706f2543Smrg    if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
111706f2543Smrg	return FALSE;
112706f2543Smrg    if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
113706f2543Smrg	return FALSE;
114706f2543Smrg    if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0))
115706f2543Smrg	return FALSE;
116706f2543Smrg    if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0))
117706f2543Smrg	return FALSE;
118706f2543Smrg
119706f2543Smrg    pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
120706f2543Smrg    if (!pDRIPriv) {
121706f2543Smrg	dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
122706f2543Smrg        return FALSE;
123706f2543Smrg    }
124706f2543Smrg
125706f2543Smrg    dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
126706f2543Smrg    pDRIPriv->directRenderingSupport = TRUE;
127706f2543Smrg    pDRIPriv->nrWindows = 0;
128706f2543Smrg
129706f2543Smrg    /* Initialize drawable tables */
130706f2543Smrg    for (i = 0; i < DRI_MAX_DRAWABLES; i++) {
131706f2543Smrg        pDRIPriv->DRIDrawables[i] = NULL;
132706f2543Smrg    }
133706f2543Smrg
134706f2543Smrg    return TRUE;
135706f2543Smrg}
136706f2543Smrg
137706f2543SmrgBool
138706f2543SmrgDRIFinishScreenInit(ScreenPtr pScreen)
139706f2543Smrg{
140706f2543Smrg    DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
141706f2543Smrg
142706f2543Smrg    /* Wrap DRI support */
143706f2543Smrg    pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
144706f2543Smrg    pScreen->ValidateTree = DRIValidateTree;
145706f2543Smrg
146706f2543Smrg    pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
147706f2543Smrg    pScreen->PostValidateTree = DRIPostValidateTree;
148706f2543Smrg
149706f2543Smrg    pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
150706f2543Smrg    pScreen->WindowExposures = DRIWindowExposures;
151706f2543Smrg
152706f2543Smrg    pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
153706f2543Smrg    pScreen->CopyWindow = DRICopyWindow;
154706f2543Smrg
155706f2543Smrg    pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
156706f2543Smrg    pScreen->ClipNotify = DRIClipNotify;
157706f2543Smrg
158706f2543Smrg    //    ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
159706f2543Smrg
160706f2543Smrg    return DRIWrapInit(pScreen);
161706f2543Smrg}
162706f2543Smrg
163706f2543Smrgvoid
164706f2543SmrgDRICloseScreen(ScreenPtr pScreen)
165706f2543Smrg{
166706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
167706f2543Smrg
168706f2543Smrg    if (pDRIPriv && pDRIPriv->directRenderingSupport) {
169706f2543Smrg        free(pDRIPriv);
170706f2543Smrg	dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
171706f2543Smrg    }
172706f2543Smrg}
173706f2543Smrg
174706f2543SmrgBool
175706f2543SmrgDRIExtensionInit(void)
176706f2543Smrg{
177706f2543Smrg    DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
178706f2543Smrg						   "DRIDrawable");
179706f2543Smrg
180706f2543Smrg    return DRIDrawablePrivResType != 0;
181706f2543Smrg}
182706f2543Smrg
183706f2543Smrgvoid
184706f2543SmrgDRIReset(void)
185706f2543Smrg{
186706f2543Smrg    /*
187706f2543Smrg     * This stub routine is called when the X Server recycles, resources
188706f2543Smrg     * allocated by DRIExtensionInit need to be managed here.
189706f2543Smrg     *
190706f2543Smrg     * Currently this routine is a stub because all the interesting resources
191706f2543Smrg     * are managed via the screen init process.
192706f2543Smrg     */
193706f2543Smrg}
194706f2543Smrg
195706f2543SmrgBool
196706f2543SmrgDRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
197706f2543Smrg{
198706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
199706f2543Smrg
200706f2543Smrg    if (pDRIPriv)
201706f2543Smrg        *isCapable = pDRIPriv->directRenderingSupport;
202706f2543Smrg    else
203706f2543Smrg        *isCapable = FALSE;
204706f2543Smrg
205706f2543Smrg    return TRUE;
206706f2543Smrg}
207706f2543Smrg
208706f2543SmrgBool
209706f2543SmrgDRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
210706f2543Smrg{
211706f2543Smrg#if 0
212706f2543Smrg    /* FIXME: something? */
213706f2543Smrg
214706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
215706f2543Smrg
216706f2543Smrg    if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
217706f2543Smrg#endif
218706f2543Smrg    return TRUE;
219706f2543Smrg}
220706f2543Smrg
221706f2543Smrgstatic void
222706f2543SmrgDRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
223706f2543Smrg{
224706f2543Smrg    xp_window_changes wc;
225706f2543Smrg    unsigned int flags = 0;
226706f2543Smrg
227706f2543Smrg    if (pDRIDrawablePriv->sid == 0)
228706f2543Smrg        return;
229706f2543Smrg
230706f2543Smrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
231706f2543Smrg    wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888
232706f2543Smrg                : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL);
233706f2543Smrg    if (wc.depth != XP_DEPTH_NIL)
234706f2543Smrg        flags |= XP_DEPTH;
235706f2543Smrg#endif
236706f2543Smrg
237706f2543Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
238706f2543Smrg        WindowPtr pWin = (WindowPtr) pDraw;
239706f2543Smrg        WindowPtr pTopWin = TopLevelParent(pWin);
240706f2543Smrg
241706f2543Smrg        wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth);
242706f2543Smrg        wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth);
243706f2543Smrg        wc.width = pWin->drawable.width + 2 * pWin->borderWidth;
244706f2543Smrg        wc.height = pWin->drawable.height + 2 * pWin->borderWidth;
245706f2543Smrg        wc.bit_gravity = XP_GRAVITY_NONE;
246706f2543Smrg
247706f2543Smrg        wc.shape_nrects = RegionNumRects(&pWin->clipList);
248706f2543Smrg        wc.shape_rects = RegionRects(&pWin->clipList);
249706f2543Smrg        wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth);
250706f2543Smrg        wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth);
251706f2543Smrg
252706f2543Smrg        flags |= XP_BOUNDS | XP_SHAPE;
253706f2543Smrg
254706f2543Smrg    } else if (pDraw->type == DRAWABLE_PIXMAP) {
255706f2543Smrg        wc.x = 0;
256706f2543Smrg        wc.y = 0;
257706f2543Smrg        wc.width = pDraw->width;
258706f2543Smrg        wc.height = pDraw->height;
259706f2543Smrg        wc.bit_gravity = XP_GRAVITY_NONE;
260706f2543Smrg        flags |= XP_BOUNDS;
261706f2543Smrg    }
262706f2543Smrg
263706f2543Smrg    xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc);
264706f2543Smrg}
265706f2543Smrg
266706f2543Smrg/* Return NULL if an error occurs. */
267706f2543Smrgstatic DRIDrawablePrivPtr
268706f2543SmrgCreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) {
269706f2543Smrg    DRIDrawablePrivPtr pDRIDrawablePriv;
270706f2543Smrg    xp_window_id wid = 0;
271706f2543Smrg
272706f2543Smrg    *widPtr = 0;
273706f2543Smrg
274706f2543Smrg    pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
275706f2543Smrg
276706f2543Smrg    if (pDRIDrawablePriv == NULL) {
277706f2543Smrg	xp_error err;
278706f2543Smrg	xp_window_changes wc;
279706f2543Smrg
280706f2543Smrg	/* allocate a DRI Window Private record */
281706f2543Smrg	if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) {
282706f2543Smrg	    return NULL;
283706f2543Smrg	}
284706f2543Smrg
285706f2543Smrg	pDRIDrawablePriv->pDraw = (DrawablePtr)pWin;
286706f2543Smrg	pDRIDrawablePriv->pScreen = pScreen;
287706f2543Smrg	pDRIDrawablePriv->refCount = 0;
288706f2543Smrg	pDRIDrawablePriv->drawableIndex = -1;
289706f2543Smrg	pDRIDrawablePriv->notifiers = NULL;
290706f2543Smrg
291706f2543Smrg	/* find the physical window */
292706f2543Smrg	wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE));
293706f2543Smrg
294706f2543Smrg	if (wid == 0) {
295706f2543Smrg	    free(pDRIDrawablePriv);
296706f2543Smrg	    return NULL;
297706f2543Smrg	}
298706f2543Smrg
299706f2543Smrg	/* allocate the physical surface */
300706f2543Smrg	err = xp_create_surface(wid, &pDRIDrawablePriv->sid);
301706f2543Smrg
302706f2543Smrg	if (err != Success) {
303706f2543Smrg	    free(pDRIDrawablePriv);
304706f2543Smrg	    return NULL;
305706f2543Smrg	}
306706f2543Smrg
307706f2543Smrg	/* Make it visible */
308706f2543Smrg	wc.stack_mode = XP_MAPPED_ABOVE;
309706f2543Smrg	wc.sibling = 0;
310706f2543Smrg	err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc);
311706f2543Smrg
312706f2543Smrg	if (err != Success) {
313706f2543Smrg	    xp_destroy_surface(pDRIDrawablePriv->sid);
314706f2543Smrg	    free(pDRIDrawablePriv);
315706f2543Smrg	    return NULL;
316706f2543Smrg	}
317706f2543Smrg
318706f2543Smrg	/* save private off of preallocated index */
319706f2543Smrg	dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
320706f2543Smrg		      pDRIDrawablePriv);
321706f2543Smrg    }
322706f2543Smrg
323706f2543Smrg    *widPtr = wid;
324706f2543Smrg
325706f2543Smrg    return pDRIDrawablePriv;
326706f2543Smrg}
327706f2543Smrg
328706f2543Smrg/* Return NULL if an error occurs. */
329706f2543Smrgstatic DRIDrawablePrivPtr
330706f2543SmrgCreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) {
331706f2543Smrg    DRIDrawablePrivPtr pDRIDrawablePriv;
332706f2543Smrg
333706f2543Smrg    pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
334706f2543Smrg
335706f2543Smrg    if (pDRIDrawablePriv == NULL) {
336706f2543Smrg	xp_error err;
337706f2543Smrg
338706f2543Smrg	/* allocate a DRI Window Private record */
339706f2543Smrg	if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) {
340706f2543Smrg	    return NULL;
341706f2543Smrg	}
342706f2543Smrg
343706f2543Smrg	pDRIDrawablePriv->pDraw = (DrawablePtr)pPix;
344706f2543Smrg	pDRIDrawablePriv->pScreen = pScreen;
345706f2543Smrg	pDRIDrawablePriv->refCount = 0;
346706f2543Smrg	pDRIDrawablePriv->drawableIndex = -1;
347706f2543Smrg	pDRIDrawablePriv->notifiers = NULL;
348706f2543Smrg
349706f2543Smrg	/* Passing a null window id to Xplugin in 10.3+ asks for
350706f2543Smrg	   an accelerated offscreen surface. */
351706f2543Smrg
352706f2543Smrg	err = xp_create_surface(0, &pDRIDrawablePriv->sid);
353706f2543Smrg	if (err != Success) {
354706f2543Smrg	    free(pDRIDrawablePriv);
355706f2543Smrg	    return NULL;
356706f2543Smrg	}
357706f2543Smrg
358706f2543Smrg	/*
359706f2543Smrg	 * The DRIUpdateSurface will be called to resize the surface
360706f2543Smrg	 * after this function, if the export is successful.
361706f2543Smrg	 */
362706f2543Smrg
363706f2543Smrg	/* save private off of preallocated index */
364706f2543Smrg	dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey,
365706f2543Smrg		      pDRIDrawablePriv);
366706f2543Smrg    }
367706f2543Smrg
368706f2543Smrg    return pDRIDrawablePriv;
369706f2543Smrg}
370706f2543Smrg
371706f2543Smrg
372706f2543SmrgBool
373706f2543SmrgDRICreateSurface(ScreenPtr pScreen, Drawable id,
374706f2543Smrg                 DrawablePtr pDrawable, xp_client_id client_id,
375706f2543Smrg                 xp_surface_id *surface_id, unsigned int ret_key[2],
376706f2543Smrg                 void (*notify) (void *arg, void *data), void *notify_data)
377706f2543Smrg{
378706f2543Smrg    DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
379706f2543Smrg    xp_window_id        wid = 0;
380706f2543Smrg    DRIDrawablePrivPtr  pDRIDrawablePriv;
381706f2543Smrg
382706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW) {
383706f2543Smrg	pDRIDrawablePriv = CreateSurfaceForWindow(pScreen,
384706f2543Smrg						  (WindowPtr)pDrawable, &wid);
385706f2543Smrg
386706f2543Smrg	if(NULL == pDRIDrawablePriv)
387706f2543Smrg	    return FALSE; /*error*/
388706f2543Smrg    }
389706f2543Smrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
390706f2543Smrg    else if (pDrawable->type == DRAWABLE_PIXMAP) {
391706f2543Smrg	pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen,
392706f2543Smrg						  (PixmapPtr)pDrawable);
393706f2543Smrg
394706f2543Smrg	if(NULL == pDRIDrawablePriv)
395706f2543Smrg	    return FALSE; /*error*/
396706f2543Smrg    }
397706f2543Smrg#endif
398706f2543Smrg    else {
399706f2543Smrg	/* We handle GLXPbuffers in a different way (via CGL). */
400706f2543Smrg        return FALSE;
401706f2543Smrg    }
402706f2543Smrg
403706f2543Smrg
404706f2543Smrg    /* Finish initialization of new surfaces */
405706f2543Smrg    if (pDRIDrawablePriv->refCount == 0) {
406706f2543Smrg        unsigned int key[2] = {0};
407706f2543Smrg        xp_error err;
408706f2543Smrg
409706f2543Smrg        /* try to give the client access to the surface */
410706f2543Smrg        if (client_id != 0) {
411706f2543Smrg	    /*
412706f2543Smrg	     * Xplugin accepts a 0 wid if the surface id is offscreen, such
413706f2543Smrg	     * as for a pixmap.
414706f2543Smrg	     */
415706f2543Smrg            err = xp_export_surface(wid, pDRIDrawablePriv->sid,
416706f2543Smrg                                    client_id, key);
417706f2543Smrg            if (err != Success) {
418706f2543Smrg                xp_destroy_surface(pDRIDrawablePriv->sid);
419706f2543Smrg                free(pDRIDrawablePriv);
420706f2543Smrg
421706f2543Smrg		/*
422706f2543Smrg		 * Now set the dix privates to NULL that were previously set.
423706f2543Smrg		 * This prevents reusing an invalid pointer.
424706f2543Smrg		 */
425706f2543Smrg		if(pDrawable->type == DRAWABLE_WINDOW) {
426706f2543Smrg		    WindowPtr pWin = (WindowPtr)pDrawable;
427706f2543Smrg
428706f2543Smrg		    dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
429706f2543Smrg		} else if(pDrawable->type == DRAWABLE_PIXMAP) {
430706f2543Smrg		    PixmapPtr pPix = (PixmapPtr)pDrawable;
431706f2543Smrg
432706f2543Smrg		    dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
433706f2543Smrg		}
434706f2543Smrg
435706f2543Smrg                return FALSE;
436706f2543Smrg            }
437706f2543Smrg        }
438706f2543Smrg
439706f2543Smrg        pDRIDrawablePriv->key[0] = key[0];
440706f2543Smrg        pDRIDrawablePriv->key[1] = key[1];
441706f2543Smrg
442706f2543Smrg        ++pDRIPriv->nrWindows;
443706f2543Smrg
444706f2543Smrg        /* and stash it by surface id */
445706f2543Smrg        if (surface_hash == NULL)
446706f2543Smrg            surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
447706f2543Smrg        x_hash_table_insert(surface_hash,
448706f2543Smrg                            x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv);
449706f2543Smrg
450706f2543Smrg        /* track this in case this window is destroyed */
451706f2543Smrg        AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
452706f2543Smrg
453706f2543Smrg        /* Initialize shape */
454706f2543Smrg        DRIUpdateSurface(pDRIDrawablePriv, pDrawable);
455706f2543Smrg    }
456706f2543Smrg
457706f2543Smrg    pDRIDrawablePriv->refCount++;
458706f2543Smrg
459706f2543Smrg    *surface_id = pDRIDrawablePriv->sid;
460706f2543Smrg
461706f2543Smrg    if (ret_key != NULL) {
462706f2543Smrg        ret_key[0] = pDRIDrawablePriv->key[0];
463706f2543Smrg        ret_key[1] = pDRIDrawablePriv->key[1];
464706f2543Smrg    }
465706f2543Smrg
466706f2543Smrg    if (notify != NULL) {
467706f2543Smrg        pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers,
468706f2543Smrg                                                 notify, notify_data);
469706f2543Smrg    }
470706f2543Smrg
471706f2543Smrg    return TRUE;
472706f2543Smrg}
473706f2543Smrg
474706f2543SmrgBool
475706f2543SmrgDRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
476706f2543Smrg                  void (*notify) (void *, void *), void *notify_data)
477706f2543Smrg{
478706f2543Smrg    DRIDrawablePrivPtr  pDRIDrawablePriv;
479706f2543Smrg
480706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW) {
481706f2543Smrg        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
482706f2543Smrg    } else if (pDrawable->type == DRAWABLE_PIXMAP) {
483706f2543Smrg        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
484706f2543Smrg    } else {
485706f2543Smrg        return FALSE;
486706f2543Smrg    }
487706f2543Smrg
488706f2543Smrg    if (pDRIDrawablePriv != NULL) {
489706f2543Smrg	/*
490706f2543Smrg	 * This doesn't seem to be used, because notify is NULL in all callers.
491706f2543Smrg	 */
492706f2543Smrg
493706f2543Smrg        if (notify != NULL) {
494706f2543Smrg            pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers,
495706f2543Smrg                                                        notify, notify_data);
496706f2543Smrg        }
497706f2543Smrg
498706f2543Smrg	--pDRIDrawablePriv->refCount;
499706f2543Smrg
500706f2543Smrg	/*
501706f2543Smrg	 * Check if the drawable privates still have a reference to the
502706f2543Smrg	 * surface.
503706f2543Smrg	 */
504706f2543Smrg
505706f2543Smrg        if (pDRIDrawablePriv->refCount <= 0) {
506706f2543Smrg            /*
507706f2543Smrg	     * This calls back to DRIDrawablePrivDelete which
508706f2543Smrg	     * frees the private area and dispatches events, if needed.
509706f2543Smrg	     */
510706f2543Smrg            FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
511706f2543Smrg        }
512706f2543Smrg    }
513706f2543Smrg
514706f2543Smrg    return TRUE;
515706f2543Smrg}
516706f2543Smrg
517706f2543Smrg/*
518706f2543Smrg * The assumption is that this is called when the refCount of a surface
519706f2543Smrg * drops to <= 0, or the window/pixmap is destroyed.
520706f2543Smrg */
521706f2543SmrgBool
522706f2543SmrgDRIDrawablePrivDelete(pointer pResource, XID id)
523706f2543Smrg{
524706f2543Smrg    DrawablePtr         pDrawable = (DrawablePtr)pResource;
525706f2543Smrg    DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
526706f2543Smrg    DRIDrawablePrivPtr  pDRIDrawablePriv = NULL;
527706f2543Smrg    WindowPtr           pWin = NULL;
528706f2543Smrg    PixmapPtr           pPix = NULL;
529706f2543Smrg
530706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW) {
531706f2543Smrg        pWin = (WindowPtr)pDrawable;
532706f2543Smrg        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
533706f2543Smrg    } else if (pDrawable->type == DRAWABLE_PIXMAP) {
534706f2543Smrg        pPix = (PixmapPtr)pDrawable;
535706f2543Smrg        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
536706f2543Smrg    }
537706f2543Smrg
538706f2543Smrg    if (pDRIDrawablePriv == NULL) {
539706f2543Smrg	/*
540706f2543Smrg	 * We reuse __func__ and the resource type for the GLXPixmap code.
541706f2543Smrg	 * Attempt to free a pixmap buffer associated with the resource
542706f2543Smrg	 * if possible.
543706f2543Smrg	 */
544706f2543Smrg	return DRIFreePixmapImp(pDrawable);
545706f2543Smrg    }
546706f2543Smrg
547706f2543Smrg    if (pDRIDrawablePriv->drawableIndex != -1) {
548706f2543Smrg        /* release drawable table entry */
549706f2543Smrg        pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
550706f2543Smrg    }
551706f2543Smrg
552706f2543Smrg    if (pDRIDrawablePriv->sid != 0) {
553706f2543Smrg	DRISurfaceNotify(pDRIDrawablePriv->sid, AppleDRISurfaceNotifyDestroyed);
554706f2543Smrg    }
555706f2543Smrg
556706f2543Smrg
557706f2543Smrg    if (pDRIDrawablePriv->notifiers != NULL)
558706f2543Smrg        x_hook_free(pDRIDrawablePriv->notifiers);
559706f2543Smrg
560706f2543Smrg    free(pDRIDrawablePriv);
561706f2543Smrg
562706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW) {
563706f2543Smrg	dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
564706f2543Smrg    } else if (pDrawable->type == DRAWABLE_PIXMAP) {
565706f2543Smrg	dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
566706f2543Smrg    }
567706f2543Smrg
568706f2543Smrg    --pDRIPriv->nrWindows;
569706f2543Smrg
570706f2543Smrg    return TRUE;
571706f2543Smrg}
572706f2543Smrg
573706f2543Smrgvoid
574706f2543SmrgDRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
575706f2543Smrg{
576706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
577706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
578706f2543Smrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
579706f2543Smrg
580706f2543Smrg    if (pDRIDrawablePriv) {
581706f2543Smrg        /* FIXME: something? */
582706f2543Smrg    }
583706f2543Smrg
584706f2543Smrg    pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
585706f2543Smrg
586706f2543Smrg    (*pScreen->WindowExposures)(pWin, prgn, bsreg);
587706f2543Smrg
588706f2543Smrg    pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
589706f2543Smrg    pScreen->WindowExposures = DRIWindowExposures;
590706f2543Smrg}
591706f2543Smrg
592706f2543Smrgvoid
593706f2543SmrgDRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
594706f2543Smrg{
595706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
596706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
597706f2543Smrg    DRIDrawablePrivPtr pDRIDrawablePriv;
598706f2543Smrg
599706f2543Smrg    if (pDRIPriv->nrWindows > 0) {
600706f2543Smrg       pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
601706f2543Smrg       if (pDRIDrawablePriv != NULL) {
602706f2543Smrg            DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
603706f2543Smrg       }
604706f2543Smrg    }
605706f2543Smrg
606706f2543Smrg    /* unwrap */
607706f2543Smrg    pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
608706f2543Smrg
609706f2543Smrg    /* call lower layers */
610706f2543Smrg    (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
611706f2543Smrg
612706f2543Smrg    /* rewrap */
613706f2543Smrg    pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
614706f2543Smrg    pScreen->CopyWindow = DRICopyWindow;
615706f2543Smrg}
616706f2543Smrg
617706f2543Smrgint
618706f2543SmrgDRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
619706f2543Smrg{
620706f2543Smrg    ScreenPtr pScreen = pParent->drawable.pScreen;
621706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
622706f2543Smrg    int returnValue;
623706f2543Smrg
624706f2543Smrg    /* unwrap */
625706f2543Smrg    pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
626706f2543Smrg
627706f2543Smrg    /* call lower layers */
628706f2543Smrg    returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
629706f2543Smrg
630706f2543Smrg    /* rewrap */
631706f2543Smrg    pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
632706f2543Smrg    pScreen->ValidateTree = DRIValidateTree;
633706f2543Smrg
634706f2543Smrg    return returnValue;
635706f2543Smrg}
636706f2543Smrg
637706f2543Smrgvoid
638706f2543SmrgDRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
639706f2543Smrg{
640706f2543Smrg    ScreenPtr pScreen;
641706f2543Smrg    DRIScreenPrivPtr pDRIPriv;
642706f2543Smrg
643706f2543Smrg    if (pParent) {
644706f2543Smrg        pScreen = pParent->drawable.pScreen;
645706f2543Smrg    } else {
646706f2543Smrg        pScreen = pChild->drawable.pScreen;
647706f2543Smrg    }
648706f2543Smrg    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
649706f2543Smrg
650706f2543Smrg    if (pDRIPriv->wrap.PostValidateTree) {
651706f2543Smrg        /* unwrap */
652706f2543Smrg        pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
653706f2543Smrg
654706f2543Smrg        /* call lower layers */
655706f2543Smrg        (*pScreen->PostValidateTree)(pParent, pChild, kind);
656706f2543Smrg
657706f2543Smrg        /* rewrap */
658706f2543Smrg        pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
659706f2543Smrg        pScreen->PostValidateTree = DRIPostValidateTree;
660706f2543Smrg    }
661706f2543Smrg}
662706f2543Smrg
663706f2543Smrgvoid
664706f2543SmrgDRIClipNotify(WindowPtr pWin, int dx, int dy)
665706f2543Smrg{
666706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
667706f2543Smrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
668706f2543Smrg    DRIDrawablePrivPtr  pDRIDrawablePriv;
669706f2543Smrg
670706f2543Smrg    if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
671706f2543Smrg        DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
672706f2543Smrg    }
673706f2543Smrg
674706f2543Smrg    if (pDRIPriv->wrap.ClipNotify) {
675706f2543Smrg        pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
676706f2543Smrg
677706f2543Smrg        (*pScreen->ClipNotify)(pWin, dx, dy);
678706f2543Smrg
679706f2543Smrg        pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
680706f2543Smrg        pScreen->ClipNotify = DRIClipNotify;
681706f2543Smrg    }
682706f2543Smrg}
683706f2543Smrg
684706f2543Smrg/* This lets us get at the unwrapped functions so that they can correctly
685706f2543Smrg * call the lower level functions, and choose whether they will be
686706f2543Smrg * called at every level of recursion (eg in validatetree).
687706f2543Smrg */
688706f2543SmrgDRIWrappedFuncsRec *
689706f2543SmrgDRIGetWrappedFuncs(ScreenPtr pScreen)
690706f2543Smrg{
691706f2543Smrg    return &(DRI_SCREEN_PRIV(pScreen)->wrap);
692706f2543Smrg}
693706f2543Smrg
694706f2543Smrgvoid
695706f2543SmrgDRIQueryVersion(int *majorVersion,
696706f2543Smrg                int *minorVersion,
697706f2543Smrg                int *patchVersion)
698706f2543Smrg{
699706f2543Smrg    *majorVersion = APPLE_DRI_MAJOR_VERSION;
700706f2543Smrg    *minorVersion = APPLE_DRI_MINOR_VERSION;
701706f2543Smrg    *patchVersion = APPLE_DRI_PATCH_VERSION;
702706f2543Smrg}
703706f2543Smrg
704706f2543Smrg/*
705706f2543Smrg * Note: this also cleans up the hash table in addition to notifying clients.
706706f2543Smrg * The sid/surface-id should not be used after this, because it will be
707706f2543Smrg * invalid.
708706f2543Smrg */
709706f2543Smrgvoid
710706f2543SmrgDRISurfaceNotify(xp_surface_id id, int kind)
711706f2543Smrg{
712706f2543Smrg    DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
713706f2543Smrg    DRISurfaceNotifyArg arg;
714706f2543Smrg
715706f2543Smrg    arg.id = id;
716706f2543Smrg    arg.kind = kind;
717706f2543Smrg
718706f2543Smrg    if (surface_hash != NULL)
719706f2543Smrg    {
720706f2543Smrg        pDRIDrawablePriv = x_hash_table_lookup(surface_hash,
721706f2543Smrg                                               x_cvt_uint_to_vptr(id), NULL);
722706f2543Smrg    }
723706f2543Smrg
724706f2543Smrg    if (pDRIDrawablePriv == NULL)
725706f2543Smrg        return;
726706f2543Smrg
727706f2543Smrg    if (kind == AppleDRISurfaceNotifyDestroyed)
728706f2543Smrg    {
729706f2543Smrg	x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id));
730706f2543Smrg    }
731706f2543Smrg
732706f2543Smrg    x_hook_run(pDRIDrawablePriv->notifiers, &arg);
733706f2543Smrg
734706f2543Smrg    if (kind == AppleDRISurfaceNotifyDestroyed)
735706f2543Smrg    {
736706f2543Smrg	xp_error error;
737706f2543Smrg
738706f2543Smrg	error = xp_destroy_surface(pDRIDrawablePriv->sid);
739706f2543Smrg
740706f2543Smrg	if(error)
741706f2543Smrg	    ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error);
742706f2543Smrg
743706f2543Smrg	/* Guard against reuse, even though we are freeing after this. */
744706f2543Smrg	pDRIDrawablePriv->sid = 0;
745706f2543Smrg
746706f2543Smrg        FreeResourceByType(pDRIDrawablePriv->pDraw->id,
747706f2543Smrg                           DRIDrawablePrivResType, FALSE);
748706f2543Smrg    }
749706f2543Smrg}
750706f2543Smrg
751706f2543Smrg/*
752706f2543Smrg * This creates a shared memory buffer for use with GLXPixmaps
753706f2543Smrg * and AppleSGLX.
754706f2543Smrg */
755706f2543SmrgBool DRICreatePixmap(ScreenPtr pScreen, Drawable id,
756706f2543Smrg		     DrawablePtr pDrawable, char *path,
757706f2543Smrg		     size_t pathmax)
758706f2543Smrg{
759706f2543Smrg    DRIPixmapBufferPtr shared;
760706f2543Smrg    PixmapPtr pPix;
761706f2543Smrg
762706f2543Smrg    if(pDrawable->type != DRAWABLE_PIXMAP)
763706f2543Smrg	return FALSE;
764706f2543Smrg
765706f2543Smrg    pPix = (PixmapPtr)pDrawable;
766706f2543Smrg
767706f2543Smrg    shared = malloc(sizeof(*shared));
768706f2543Smrg    if(NULL == shared) {
769706f2543Smrg        FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__);
770706f2543Smrg    }
771706f2543Smrg
772706f2543Smrg    shared->pDrawable = pDrawable;
773706f2543Smrg    shared->refCount = 1;
774706f2543Smrg
775706f2543Smrg    if(pDrawable->bitsPerPixel >= 24) {
776706f2543Smrg	shared->bytesPerPixel = 4;
777706f2543Smrg    } else if(pDrawable->bitsPerPixel <= 16) {
778706f2543Smrg	shared->bytesPerPixel = 2;
779706f2543Smrg    }
780706f2543Smrg
781706f2543Smrg    shared->width = pDrawable->width;
782706f2543Smrg    shared->height = pDrawable->height;
783706f2543Smrg
784706f2543Smrg    if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath),
785706f2543Smrg                      "%d_0x%lx", getpid(),
786706f2543Smrg                      (unsigned long)id)) {
787706f2543Smrg        FatalError("buffer overflow in %s\n", __func__);
788706f2543Smrg    }
789706f2543Smrg
790706f2543Smrg    shared->fd = shm_open(shared->shmPath,
791706f2543Smrg                          O_RDWR | O_EXCL | O_CREAT,
792706f2543Smrg                          S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
793706f2543Smrg
794706f2543Smrg    if(-1 == shared->fd) {
795706f2543Smrg	free(shared);
796706f2543Smrg        return FALSE;
797706f2543Smrg    }
798706f2543Smrg
799706f2543Smrg    shared->length = shared->width * shared->height * shared->bytesPerPixel;
800706f2543Smrg
801706f2543Smrg    if(-1 == ftruncate(shared->fd, shared->length)) {
802706f2543Smrg	ErrorF("failed to ftruncate (extend) file.");
803706f2543Smrg	shm_unlink(shared->shmPath);
804706f2543Smrg	close(shared->fd);
805706f2543Smrg	free(shared);
806706f2543Smrg	return FALSE;
807706f2543Smrg    }
808706f2543Smrg
809706f2543Smrg    shared->buffer = mmap(NULL, shared->length,
810706f2543Smrg                          PROT_READ | PROT_WRITE,
811706f2543Smrg                          MAP_FILE | MAP_SHARED, shared->fd, 0);
812706f2543Smrg
813706f2543Smrg    if(MAP_FAILED == shared->buffer) {
814706f2543Smrg	ErrorF("failed to mmap shared memory.");
815706f2543Smrg	shm_unlink(shared->shmPath);
816706f2543Smrg	close(shared->fd);
817706f2543Smrg	free(shared);
818706f2543Smrg	return FALSE;
819706f2543Smrg    }
820706f2543Smrg
821706f2543Smrg    strncpy(path, shared->shmPath, pathmax);
822706f2543Smrg    path[pathmax - 1] = '\0';
823706f2543Smrg
824706f2543Smrg    dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared);
825706f2543Smrg
826706f2543Smrg    AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
827706f2543Smrg
828706f2543Smrg    return TRUE;
829706f2543Smrg}
830706f2543Smrg
831706f2543Smrg
832706f2543SmrgBool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height,
833706f2543Smrg		      int *pitch, int *bpp, void **ptr) {
834706f2543Smrg    PixmapPtr pPix;
835706f2543Smrg    DRIPixmapBufferPtr shared;
836706f2543Smrg
837706f2543Smrg    if(pDrawable->type != DRAWABLE_PIXMAP)
838706f2543Smrg	return FALSE;
839706f2543Smrg
840706f2543Smrg    pPix = (PixmapPtr)pDrawable;
841706f2543Smrg
842706f2543Smrg    shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
843706f2543Smrg
844706f2543Smrg    if(NULL == shared)
845706f2543Smrg	return FALSE;
846706f2543Smrg
847706f2543Smrg    assert(pDrawable->width == shared->width);
848706f2543Smrg    assert(pDrawable->height == shared->height);
849706f2543Smrg
850706f2543Smrg    *width = shared->width;
851706f2543Smrg    *height = shared->height;
852706f2543Smrg    *bpp = shared->bytesPerPixel;
853706f2543Smrg    *pitch = shared->width * shared->bytesPerPixel;
854706f2543Smrg    *ptr = shared->buffer;
855706f2543Smrg
856706f2543Smrg    return TRUE;
857706f2543Smrg}
858706f2543Smrg
859706f2543Smrgstatic Bool
860706f2543SmrgDRIFreePixmapImp(DrawablePtr pDrawable) {
861706f2543Smrg    DRIPixmapBufferPtr shared;
862706f2543Smrg    PixmapPtr pPix;
863706f2543Smrg
864706f2543Smrg    if(pDrawable->type != DRAWABLE_PIXMAP)
865706f2543Smrg	return FALSE;
866706f2543Smrg
867706f2543Smrg    pPix = (PixmapPtr)pDrawable;
868706f2543Smrg
869706f2543Smrg    shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
870706f2543Smrg
871706f2543Smrg    if(NULL == shared)
872706f2543Smrg	return FALSE;
873706f2543Smrg
874706f2543Smrg    close(shared->fd);
875706f2543Smrg    munmap(shared->buffer, shared->length);
876706f2543Smrg    shm_unlink(shared->shmPath);
877706f2543Smrg    free(shared);
878706f2543Smrg
879706f2543Smrg    dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL);
880706f2543Smrg
881706f2543Smrg    return TRUE;
882706f2543Smrg}
883706f2543Smrg
884706f2543Smrgvoid
885706f2543SmrgDRIDestroyPixmap(DrawablePtr pDrawable) {
886706f2543Smrg    if(DRIFreePixmapImp(pDrawable))
887706f2543Smrg	FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE);
888706f2543Smrg
889706f2543Smrg}
890