1 /**************************************************************************
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.
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:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
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.
28 **************************************************************************/
32 * Jens Owen <jens@valinux.com>
33 * Rickard E. (Rik) Faith <faith@valinux.com>
34 * Jeremy Huddleston <jeremyhu@apple.com>
37 #ifdef HAVE_DIX_CONFIG_H
38 #include <dix-config.h>
45 #include <X11/Xproto.h>
48 #include <sys/types.h>
51 #include "dixstruct.h"
52 #include "extnsionst.h"
54 #include "colormapst.h"
55 #include "cursorstr.h"
56 #include "scrnintstr.h"
57 #include "windowstr.h"
59 #define _APPLEDRI_SERVER_
60 #include "appledristr.h"
63 #include "dristruct.h"
65 #include "mipointer.h"
67 #include "rootlessCommon.h"
72 #include <AvailabilityMacros.h>
74 static DevPrivateKeyRec DRIScreenPrivKeyRec
;
75 #define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
76 static DevPrivateKeyRec DRIWindowPrivKeyRec
;
77 #define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
78 static DevPrivateKeyRec DRIPixmapPrivKeyRec
;
79 #define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec)
80 static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec
;
81 #define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
83 static RESTYPE DRIDrawablePrivResType
;
85 static x_hash_table
*surface_hash
; /* maps surface ids -> drawablePrivs */
88 DRIFreePixmapImp(DrawablePtr pDrawable
);
91 DrawablePtr pDrawable
;
96 char shmPath
[PATH_MAX
];
97 int fd
; /* From shm_open (for now) */
98 size_t length
; /* length of buffer */
100 } DRIPixmapBuffer
, *DRIPixmapBufferPtr
;
103 DRIScreenInit(ScreenPtr pScreen
)
105 DRIScreenPrivPtr pDRIPriv
;
108 if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec
, PRIVATE_SCREEN
, 0))
110 if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec
, PRIVATE_WINDOW
, 0))
112 if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec
, PRIVATE_PIXMAP
, 0))
114 if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec
, PRIVATE_PIXMAP
, 0))
117 pDRIPriv
= (DRIScreenPrivPtr
)calloc(1, sizeof(DRIScreenPrivRec
));
119 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
123 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, pDRIPriv
);
124 pDRIPriv
->directRenderingSupport
= TRUE
;
125 pDRIPriv
->nrWindows
= 0;
127 /* Initialize drawable tables */
128 for (i
= 0; i
< DRI_MAX_DRAWABLES
; i
++) {
129 pDRIPriv
->DRIDrawables
[i
] = NULL
;
136 DRIFinishScreenInit(ScreenPtr pScreen
)
138 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
140 /* Wrap DRI support */
141 pDRIPriv
->wrap
.ValidateTree
= pScreen
->ValidateTree
;
142 pScreen
->ValidateTree
= DRIValidateTree
;
144 pDRIPriv
->wrap
.PostValidateTree
= pScreen
->PostValidateTree
;
145 pScreen
->PostValidateTree
= DRIPostValidateTree
;
147 pDRIPriv
->wrap
.WindowExposures
= pScreen
->WindowExposures
;
148 pScreen
->WindowExposures
= DRIWindowExposures
;
150 pDRIPriv
->wrap
.CopyWindow
= pScreen
->CopyWindow
;
151 pScreen
->CopyWindow
= DRICopyWindow
;
153 pDRIPriv
->wrap
.ClipNotify
= pScreen
->ClipNotify
;
154 pScreen
->ClipNotify
= DRIClipNotify
;
156 // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
158 return DRIWrapInit(pScreen
);
162 DRICloseScreen(ScreenPtr pScreen
)
164 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
166 if (pDRIPriv
&& pDRIPriv
->directRenderingSupport
) {
168 dixSetPrivate(&pScreen
->devPrivates
, DRIScreenPrivKey
, NULL
);
173 DRIExtensionInit(void)
175 DRIDrawablePrivResType
= CreateNewResourceType(DRIDrawablePrivDelete
,
178 return DRIDrawablePrivResType
!= 0;
185 * This stub routine is called when the X Server recycles, resources
186 * allocated by DRIExtensionInit need to be managed here.
188 * Currently this routine is a stub because all the interesting resources
189 * are managed via the screen init process.
194 DRIQueryDirectRenderingCapable(ScreenPtr pScreen
, Bool
* isCapable
)
196 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
199 *isCapable
= pDRIPriv
->directRenderingSupport
;
207 DRIAuthConnection(ScreenPtr pScreen
, unsigned int magic
)
210 /* FIXME: something? */
212 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
214 if (drmAuthMagic(pDRIPriv
->drmFD
, magic
)) return FALSE
;
220 DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv
, DrawablePtr pDraw
)
222 xp_window_changes wc
;
223 unsigned int flags
= 0;
225 if (pDRIDrawablePriv
->sid
== 0)
228 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
229 wc
.depth
= (pDraw
->bitsPerPixel
== 32 ? XP_DEPTH_ARGB8888
230 : pDraw
->bitsPerPixel
== 16 ? XP_DEPTH_RGB555
: XP_DEPTH_NIL
);
231 if (wc
.depth
!= XP_DEPTH_NIL
)
235 if (pDraw
->type
== DRAWABLE_WINDOW
) {
236 WindowPtr pWin
= (WindowPtr
)pDraw
;
237 WindowPtr pTopWin
= TopLevelParent(pWin
);
239 wc
.x
= pWin
->drawable
.x
- (pTopWin
->drawable
.x
- pTopWin
->borderWidth
);
240 wc
.y
= pWin
->drawable
.y
- (pTopWin
->drawable
.y
- pTopWin
->borderWidth
);
241 wc
.width
= pWin
->drawable
.width
+ 2 * pWin
->borderWidth
;
242 wc
.height
= pWin
->drawable
.height
+ 2 * pWin
->borderWidth
;
243 wc
.bit_gravity
= XP_GRAVITY_NONE
;
245 wc
.shape_nrects
= RegionNumRects(&pWin
->clipList
);
246 wc
.shape_rects
= RegionRects(&pWin
->clipList
);
247 wc
.shape_tx
= -(pTopWin
->drawable
.x
- pTopWin
->borderWidth
);
248 wc
.shape_ty
= -(pTopWin
->drawable
.y
- pTopWin
->borderWidth
);
250 flags
|= XP_BOUNDS
| XP_SHAPE
;
253 else if (pDraw
->type
== DRAWABLE_PIXMAP
) {
256 wc
.width
= pDraw
->width
;
257 wc
.height
= pDraw
->height
;
258 wc
.bit_gravity
= XP_GRAVITY_NONE
;
262 xp_configure_surface(pDRIDrawablePriv
->sid
, flags
, &wc
);
265 /* Return NULL if an error occurs. */
266 static DRIDrawablePrivPtr
267 CreateSurfaceForWindow(ScreenPtr pScreen
, WindowPtr pWin
,
268 xp_window_id
*widPtr
)
270 DRIDrawablePrivPtr pDRIDrawablePriv
;
271 xp_window_id wid
= 0;
275 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
277 if (pDRIDrawablePriv
== NULL
) {
279 xp_window_changes wc
;
281 /* allocate a DRI Window Private record */
282 if (!(pDRIDrawablePriv
= malloc(sizeof(*pDRIDrawablePriv
)))) {
286 pDRIDrawablePriv
->pDraw
= (DrawablePtr
)pWin
;
287 pDRIDrawablePriv
->pScreen
= pScreen
;
288 pDRIDrawablePriv
->refCount
= 0;
289 pDRIDrawablePriv
->drawableIndex
= -1;
290 pDRIDrawablePriv
->notifiers
= NULL
;
292 /* find the physical window */
293 wid
= x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin
, TRUE
));
296 free(pDRIDrawablePriv
);
300 /* allocate the physical surface */
301 err
= xp_create_surface(wid
, &pDRIDrawablePriv
->sid
);
303 if (err
!= Success
) {
304 free(pDRIDrawablePriv
);
308 /* Make it visible */
309 wc
.stack_mode
= XP_MAPPED_ABOVE
;
311 err
= xp_configure_surface(pDRIDrawablePriv
->sid
, XP_STACKING
, &wc
);
313 if (err
!= Success
) {
314 xp_destroy_surface(pDRIDrawablePriv
->sid
);
315 free(pDRIDrawablePriv
);
319 /* save private off of preallocated index */
320 dixSetPrivate(&pWin
->devPrivates
, DRIWindowPrivKey
,
326 return pDRIDrawablePriv
;
329 /* Return NULL if an error occurs. */
330 static DRIDrawablePrivPtr
331 CreateSurfaceForPixmap(ScreenPtr pScreen
, PixmapPtr pPix
)
333 DRIDrawablePrivPtr pDRIDrawablePriv
;
335 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix
);
337 if (pDRIDrawablePriv
== NULL
) {
340 /* allocate a DRI Window Private record */
341 if (!(pDRIDrawablePriv
= calloc(1, sizeof(*pDRIDrawablePriv
)))) {
345 pDRIDrawablePriv
->pDraw
= (DrawablePtr
)pPix
;
346 pDRIDrawablePriv
->pScreen
= pScreen
;
347 pDRIDrawablePriv
->refCount
= 0;
348 pDRIDrawablePriv
->drawableIndex
= -1;
349 pDRIDrawablePriv
->notifiers
= NULL
;
351 /* Passing a null window id to Xplugin in 10.3+ asks for
352 an accelerated offscreen surface. */
354 err
= xp_create_surface(0, &pDRIDrawablePriv
->sid
);
355 if (err
!= Success
) {
356 free(pDRIDrawablePriv
);
361 * The DRIUpdateSurface will be called to resize the surface
362 * after this function, if the export is successful.
365 /* save private off of preallocated index */
366 dixSetPrivate(&pPix
->devPrivates
, DRIPixmapPrivKey
,
370 return pDRIDrawablePriv
;
374 DRICreateSurface(ScreenPtr pScreen
, Drawable id
,
375 DrawablePtr pDrawable
, xp_client_id client_id
,
376 xp_surface_id
*surface_id
, unsigned int ret_key
[2],
377 void (*notify
)(void *arg
, void *data
), void *notify_data
)
379 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
380 xp_window_id wid
= 0;
381 DRIDrawablePrivPtr pDRIDrawablePriv
;
383 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
384 /* <rdar://problem/12338921>
385 * http://bugs.winehq.org/show_bug.cgi?id=31751
387 RootlessStopDrawing((WindowPtr
)pDrawable
, FALSE
);
389 pDRIDrawablePriv
= CreateSurfaceForWindow(pScreen
,
390 (WindowPtr
)pDrawable
, &wid
);
392 if (NULL
== pDRIDrawablePriv
)
393 return FALSE
; /*error*/
395 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
396 else if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
397 pDRIDrawablePriv
= CreateSurfaceForPixmap(pScreen
,
398 (PixmapPtr
)pDrawable
);
400 if (NULL
== pDRIDrawablePriv
)
401 return FALSE
; /*error*/
405 /* We handle GLXPbuffers in a different way (via CGL). */
409 /* Finish initialization of new surfaces */
410 if (pDRIDrawablePriv
->refCount
== 0) {
411 unsigned int key
[2] = { 0 };
414 /* try to give the client access to the surface */
415 if (client_id
!= 0) {
417 * Xplugin accepts a 0 wid if the surface id is offscreen, such
420 err
= xp_export_surface(wid
, pDRIDrawablePriv
->sid
,
422 if (err
!= Success
) {
423 xp_destroy_surface(pDRIDrawablePriv
->sid
);
424 free(pDRIDrawablePriv
);
427 * Now set the dix privates to NULL that were previously set.
428 * This prevents reusing an invalid pointer.
430 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
431 WindowPtr pWin
= (WindowPtr
)pDrawable
;
433 dixSetPrivate(&pWin
->devPrivates
, DRIWindowPrivKey
, NULL
);
435 else if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
436 PixmapPtr pPix
= (PixmapPtr
)pDrawable
;
438 dixSetPrivate(&pPix
->devPrivates
, DRIPixmapPrivKey
, NULL
);
445 pDRIDrawablePriv
->key
[0] = key
[0];
446 pDRIDrawablePriv
->key
[1] = key
[1];
448 ++pDRIPriv
->nrWindows
;
450 /* and stash it by surface id */
451 if (surface_hash
== NULL
)
452 surface_hash
= x_hash_table_new(NULL
, NULL
, NULL
, NULL
);
453 x_hash_table_insert(surface_hash
,
455 pDRIDrawablePriv
->sid
), pDRIDrawablePriv
);
457 /* track this in case this window is destroyed */
458 AddResource(id
, DRIDrawablePrivResType
, (pointer
)pDrawable
);
460 /* Initialize shape */
461 DRIUpdateSurface(pDRIDrawablePriv
, pDrawable
);
464 pDRIDrawablePriv
->refCount
++;
466 *surface_id
= pDRIDrawablePriv
->sid
;
468 if (ret_key
!= NULL
) {
469 ret_key
[0] = pDRIDrawablePriv
->key
[0];
470 ret_key
[1] = pDRIDrawablePriv
->key
[1];
473 if (notify
!= NULL
) {
474 pDRIDrawablePriv
->notifiers
= x_hook_add(pDRIDrawablePriv
->notifiers
,
475 notify
, notify_data
);
482 DRIDestroySurface(ScreenPtr pScreen
, Drawable id
, DrawablePtr pDrawable
,
483 void (*notify
)(void *, void *), void *notify_data
)
485 DRIDrawablePrivPtr pDRIDrawablePriv
;
487 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
488 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr
)pDrawable
);
490 else if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
491 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr
)pDrawable
);
497 if (pDRIDrawablePriv
!= NULL
) {
499 * This doesn't seem to be used, because notify is NULL in all callers.
502 if (notify
!= NULL
) {
503 pDRIDrawablePriv
->notifiers
= x_hook_remove(
504 pDRIDrawablePriv
->notifiers
,
505 notify
, notify_data
);
508 --pDRIDrawablePriv
->refCount
;
511 * Check if the drawable privates still have a reference to the
515 if (pDRIDrawablePriv
->refCount
<= 0) {
517 * This calls back to DRIDrawablePrivDelete which
518 * frees the private area and dispatches events, if needed.
520 FreeResourceByType(id
, DRIDrawablePrivResType
, FALSE
);
528 * The assumption is that this is called when the refCount of a surface
529 * drops to <= 0, or the window/pixmap is destroyed.
532 DRIDrawablePrivDelete(pointer pResource
, XID id
)
534 DrawablePtr pDrawable
= (DrawablePtr
)pResource
;
535 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pDrawable
->pScreen
);
536 DRIDrawablePrivPtr pDRIDrawablePriv
= NULL
;
537 WindowPtr pWin
= NULL
;
538 PixmapPtr pPix
= NULL
;
540 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
541 pWin
= (WindowPtr
)pDrawable
;
542 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
544 else if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
545 pPix
= (PixmapPtr
)pDrawable
;
546 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix
);
549 if (pDRIDrawablePriv
== NULL
) {
551 * We reuse __func__ and the resource type for the GLXPixmap code.
552 * Attempt to free a pixmap buffer associated with the resource
555 return DRIFreePixmapImp(pDrawable
);
558 if (pDRIDrawablePriv
->drawableIndex
!= -1) {
559 /* release drawable table entry */
560 pDRIPriv
->DRIDrawables
[pDRIDrawablePriv
->drawableIndex
] = NULL
;
563 if (pDRIDrawablePriv
->sid
!= 0) {
564 DRISurfaceNotify(pDRIDrawablePriv
->sid
,
565 AppleDRISurfaceNotifyDestroyed
);
568 if (pDRIDrawablePriv
->notifiers
!= NULL
)
569 x_hook_free(pDRIDrawablePriv
->notifiers
);
571 free(pDRIDrawablePriv
);
573 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
574 dixSetPrivate(&pWin
->devPrivates
, DRIWindowPrivKey
, NULL
);
576 else if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
577 dixSetPrivate(&pPix
->devPrivates
, DRIPixmapPrivKey
, NULL
);
580 --pDRIPriv
->nrWindows
;
586 DRIWindowExposures(WindowPtr pWin
, RegionPtr prgn
, RegionPtr bsreg
)
588 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
589 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
590 DRIDrawablePrivPtr pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
592 if (pDRIDrawablePriv
) {
593 /* FIXME: something? */
596 pScreen
->WindowExposures
= pDRIPriv
->wrap
.WindowExposures
;
598 (*pScreen
->WindowExposures
)(pWin
, prgn
, bsreg
);
600 pScreen
->WindowExposures
= DRIWindowExposures
;
604 DRICopyWindow(WindowPtr pWin
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
606 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
607 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
608 DRIDrawablePrivPtr pDRIDrawablePriv
;
610 if (pDRIPriv
->nrWindows
> 0) {
611 pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
);
612 if (pDRIDrawablePriv
!= NULL
) {
613 DRIUpdateSurface(pDRIDrawablePriv
, &pWin
->drawable
);
618 pScreen
->CopyWindow
= pDRIPriv
->wrap
.CopyWindow
;
620 /* call lower layers */
621 (*pScreen
->CopyWindow
)(pWin
, ptOldOrg
, prgnSrc
);
624 pScreen
->CopyWindow
= DRICopyWindow
;
628 DRIValidateTree(WindowPtr pParent
, WindowPtr pChild
, VTKind kind
)
630 ScreenPtr pScreen
= pParent
->drawable
.pScreen
;
631 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
635 pScreen
->ValidateTree
= pDRIPriv
->wrap
.ValidateTree
;
637 /* call lower layers */
638 returnValue
= (*pScreen
->ValidateTree
)(pParent
, pChild
, kind
);
641 pScreen
->ValidateTree
= DRIValidateTree
;
647 DRIPostValidateTree(WindowPtr pParent
, WindowPtr pChild
, VTKind kind
)
650 DRIScreenPrivPtr pDRIPriv
;
653 pScreen
= pParent
->drawable
.pScreen
;
656 pScreen
= pChild
->drawable
.pScreen
;
658 pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
660 if (pDRIPriv
->wrap
.PostValidateTree
) {
662 pScreen
->PostValidateTree
= pDRIPriv
->wrap
.PostValidateTree
;
664 /* call lower layers */
665 (*pScreen
->PostValidateTree
)(pParent
, pChild
, kind
);
668 pScreen
->PostValidateTree
= DRIPostValidateTree
;
673 DRIClipNotify(WindowPtr pWin
, int dx
, int dy
)
675 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
676 DRIScreenPrivPtr pDRIPriv
= DRI_SCREEN_PRIV(pScreen
);
677 DRIDrawablePrivPtr pDRIDrawablePriv
;
679 if ((pDRIDrawablePriv
= DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin
))) {
680 DRIUpdateSurface(pDRIDrawablePriv
, &pWin
->drawable
);
683 if (pDRIPriv
->wrap
.ClipNotify
) {
684 pScreen
->ClipNotify
= pDRIPriv
->wrap
.ClipNotify
;
686 (*pScreen
->ClipNotify
)(pWin
, dx
, dy
);
688 pScreen
->ClipNotify
= DRIClipNotify
;
692 /* This lets us get at the unwrapped functions so that they can correctly
693 * call the lower level functions, and choose whether they will be
694 * called at every level of recursion (eg in validatetree).
697 DRIGetWrappedFuncs(ScreenPtr pScreen
)
699 return &(DRI_SCREEN_PRIV(pScreen
)->wrap
);
703 DRIQueryVersion(int *majorVersion
,
707 *majorVersion
= APPLE_DRI_MAJOR_VERSION
;
708 *minorVersion
= APPLE_DRI_MINOR_VERSION
;
709 *patchVersion
= APPLE_DRI_PATCH_VERSION
;
713 * Note: this also cleans up the hash table in addition to notifying clients.
714 * The sid/surface-id should not be used after this, because it will be
718 DRISurfaceNotify(xp_surface_id id
, int kind
)
720 DRIDrawablePrivPtr pDRIDrawablePriv
= NULL
;
721 DRISurfaceNotifyArg arg
;
726 if (surface_hash
!= NULL
) {
727 pDRIDrawablePriv
= x_hash_table_lookup(surface_hash
,
728 x_cvt_uint_to_vptr(id
), NULL
);
731 if (pDRIDrawablePriv
== NULL
)
734 if (kind
== AppleDRISurfaceNotifyDestroyed
) {
735 x_hash_table_remove(surface_hash
, x_cvt_uint_to_vptr(id
));
738 x_hook_run(pDRIDrawablePriv
->notifiers
, &arg
);
740 if (kind
== AppleDRISurfaceNotifyDestroyed
) {
743 error
= xp_destroy_surface(pDRIDrawablePriv
->sid
);
746 ErrorF("%s: xp_destroy_surface failed: %d\n", __func__
, error
);
748 /* Guard against reuse, even though we are freeing after this. */
749 pDRIDrawablePriv
->sid
= 0;
751 FreeResourceByType(pDRIDrawablePriv
->pDraw
->id
,
752 DRIDrawablePrivResType
, FALSE
);
757 * This creates a shared memory buffer for use with GLXPixmaps
761 DRICreatePixmap(ScreenPtr pScreen
, Drawable id
,
762 DrawablePtr pDrawable
, char *path
,
765 DRIPixmapBufferPtr shared
;
768 if (pDrawable
->type
!= DRAWABLE_PIXMAP
)
771 pPix
= (PixmapPtr
)pDrawable
;
773 shared
= malloc(sizeof(*shared
));
774 if (NULL
== shared
) {
775 FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__
);
778 shared
->pDrawable
= pDrawable
;
779 shared
->refCount
= 1;
781 if (pDrawable
->bitsPerPixel
>= 24) {
782 shared
->bytesPerPixel
= 4;
784 else if (pDrawable
->bitsPerPixel
<= 16) {
785 shared
->bytesPerPixel
= 2;
788 shared
->width
= pDrawable
->width
;
789 shared
->height
= pDrawable
->height
;
791 if (-1 == snprintf(shared
->shmPath
, sizeof(shared
->shmPath
),
792 "%d_0x%lx", getpid(),
793 (unsigned long)id
)) {
794 FatalError("buffer overflow in %s\n", __func__
);
797 shared
->fd
= shm_open(shared
->shmPath
,
798 O_RDWR
| O_EXCL
| O_CREAT
,
799 S_IRUSR
| S_IWUSR
| S_IROTH
| S_IWOTH
);
801 if (-1 == shared
->fd
) {
806 shared
->length
= shared
->width
* shared
->height
* shared
->bytesPerPixel
;
808 if (-1 == ftruncate(shared
->fd
, shared
->length
)) {
809 ErrorF("failed to ftruncate (extend) file.");
810 shm_unlink(shared
->shmPath
);
816 shared
->buffer
= mmap(NULL
, shared
->length
,
817 PROT_READ
| PROT_WRITE
,
818 MAP_FILE
| MAP_SHARED
, shared
->fd
, 0);
820 if (MAP_FAILED
== shared
->buffer
) {
821 ErrorF("failed to mmap shared memory.");
822 shm_unlink(shared
->shmPath
);
828 strlcpy(path
, shared
->shmPath
, pathmax
);
830 dixSetPrivate(&pPix
->devPrivates
, DRIPixmapBufferPrivKey
, shared
);
832 AddResource(id
, DRIDrawablePrivResType
, (pointer
)pDrawable
);
838 DRIGetPixmapData(DrawablePtr pDrawable
, int *width
, int *height
,
839 int *pitch
, int *bpp
, void **ptr
)
842 DRIPixmapBufferPtr shared
;
844 if (pDrawable
->type
!= DRAWABLE_PIXMAP
)
847 pPix
= (PixmapPtr
)pDrawable
;
849 shared
= dixLookupPrivate(&pPix
->devPrivates
, DRIPixmapBufferPrivKey
);
854 assert(pDrawable
->width
== shared
->width
);
855 assert(pDrawable
->height
== shared
->height
);
857 *width
= shared
->width
;
858 *height
= shared
->height
;
859 *bpp
= shared
->bytesPerPixel
;
860 *pitch
= shared
->width
* shared
->bytesPerPixel
;
861 *ptr
= shared
->buffer
;
867 DRIFreePixmapImp(DrawablePtr pDrawable
)
869 DRIPixmapBufferPtr shared
;
872 if (pDrawable
->type
!= DRAWABLE_PIXMAP
)
875 pPix
= (PixmapPtr
)pDrawable
;
877 shared
= dixLookupPrivate(&pPix
->devPrivates
, DRIPixmapBufferPrivKey
);
883 munmap(shared
->buffer
, shared
->length
);
884 shm_unlink(shared
->shmPath
);
887 dixSetPrivate(&pPix
->devPrivates
, DRIPixmapBufferPrivKey
, (pointer
)NULL
);
893 DRIDestroyPixmap(DrawablePtr pDrawable
)
895 if (DRIFreePixmapImp(pDrawable
))
896 FreeResourceByType(pDrawable
->id
, DRIDrawablePrivResType
, FALSE
);