Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xquartz / xpr / dri.c
CommitLineData
a09e091a
JB
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#include <AvailabilityMacros.h>
73
74static DevPrivateKeyRec DRIScreenPrivKeyRec;
75#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
76static DevPrivateKeyRec DRIWindowPrivKeyRec;
77#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
78static DevPrivateKeyRec DRIPixmapPrivKeyRec;
79#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec)
80static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec;
81#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
82
83static RESTYPE DRIDrawablePrivResType;
84
85static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */
86
87static Bool
88DRIFreePixmapImp(DrawablePtr pDrawable);
89
90typedef struct {
91 DrawablePtr pDrawable;
92 int refCount;
93 int bytesPerPixel;
94 int width;
95 int height;
96 char shmPath[PATH_MAX];
97 int fd; /* From shm_open (for now) */
98 size_t length; /* length of buffer */
99 void *buffer;
100} DRIPixmapBuffer, *DRIPixmapBufferPtr;
101
102Bool
103DRIScreenInit(ScreenPtr pScreen)
104{
105 DRIScreenPrivPtr pDRIPriv;
106 int i;
107
108 if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
109 return FALSE;
110 if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
111 return FALSE;
112 if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0))
113 return FALSE;
114 if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0))
115 return FALSE;
116
117 pDRIPriv = (DRIScreenPrivPtr)calloc(1, sizeof(DRIScreenPrivRec));
118 if (!pDRIPriv) {
119 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
120 return FALSE;
121 }
122
123 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
124 pDRIPriv->directRenderingSupport = TRUE;
125 pDRIPriv->nrWindows = 0;
126
127 /* Initialize drawable tables */
128 for (i = 0; i < DRI_MAX_DRAWABLES; i++) {
129 pDRIPriv->DRIDrawables[i] = NULL;
130 }
131
132 return TRUE;
133}
134
135Bool
136DRIFinishScreenInit(ScreenPtr pScreen)
137{
138 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
139
140 /* Wrap DRI support */
141 pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
142 pScreen->ValidateTree = DRIValidateTree;
143
144 pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
145 pScreen->PostValidateTree = DRIPostValidateTree;
146
147 pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
148 pScreen->WindowExposures = DRIWindowExposures;
149
150 pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
151 pScreen->CopyWindow = DRICopyWindow;
152
153 pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
154 pScreen->ClipNotify = DRIClipNotify;
155
156 // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
157
158 return DRIWrapInit(pScreen);
159}
160
161void
162DRICloseScreen(ScreenPtr pScreen)
163{
164 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
165
166 if (pDRIPriv && pDRIPriv->directRenderingSupport) {
167 free(pDRIPriv);
168 dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
169 }
170}
171
172Bool
173DRIExtensionInit(void)
174{
175 DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
176 "DRIDrawable");
177
178 return DRIDrawablePrivResType != 0;
179}
180
181void
182DRIReset(void)
183{
184 /*
185 * This stub routine is called when the X Server recycles, resources
186 * allocated by DRIExtensionInit need to be managed here.
187 *
188 * Currently this routine is a stub because all the interesting resources
189 * are managed via the screen init process.
190 */
191}
192
193Bool
194DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
195{
196 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
197
198 if (pDRIPriv)
199 *isCapable = pDRIPriv->directRenderingSupport;
200 else
201 *isCapable = FALSE;
202
203 return TRUE;
204}
205
206Bool
207DRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
208{
209#if 0
210 /* FIXME: something? */
211
212 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
213
214 if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
215#endif
216 return TRUE;
217}
218
219static void
220DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
221{
222 xp_window_changes wc;
223 unsigned int flags = 0;
224
225 if (pDRIDrawablePriv->sid == 0)
226 return;
227
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)
232 flags |= XP_DEPTH;
233#endif
234
235 if (pDraw->type == DRAWABLE_WINDOW) {
236 WindowPtr pWin = (WindowPtr)pDraw;
237 WindowPtr pTopWin = TopLevelParent(pWin);
238
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;
244
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);
249
250 flags |= XP_BOUNDS | XP_SHAPE;
251
252 }
253 else if (pDraw->type == DRAWABLE_PIXMAP) {
254 wc.x = 0;
255 wc.y = 0;
256 wc.width = pDraw->width;
257 wc.height = pDraw->height;
258 wc.bit_gravity = XP_GRAVITY_NONE;
259 flags |= XP_BOUNDS;
260 }
261
262 xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc);
263}
264
265/* Return NULL if an error occurs. */
266static DRIDrawablePrivPtr
267CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin,
268 xp_window_id *widPtr)
269{
270 DRIDrawablePrivPtr pDRIDrawablePriv;
271 xp_window_id wid = 0;
272
273 *widPtr = 0;
274
275 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
276
277 if (pDRIDrawablePriv == NULL) {
278 xp_error err;
279 xp_window_changes wc;
280
281 /* allocate a DRI Window Private record */
282 if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) {
283 return NULL;
284 }
285
286 pDRIDrawablePriv->pDraw = (DrawablePtr)pWin;
287 pDRIDrawablePriv->pScreen = pScreen;
288 pDRIDrawablePriv->refCount = 0;
289 pDRIDrawablePriv->drawableIndex = -1;
290 pDRIDrawablePriv->notifiers = NULL;
291
292 /* find the physical window */
293 wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE));
294
295 if (wid == 0) {
296 free(pDRIDrawablePriv);
297 return NULL;
298 }
299
300 /* allocate the physical surface */
301 err = xp_create_surface(wid, &pDRIDrawablePriv->sid);
302
303 if (err != Success) {
304 free(pDRIDrawablePriv);
305 return NULL;
306 }
307
308 /* Make it visible */
309 wc.stack_mode = XP_MAPPED_ABOVE;
310 wc.sibling = 0;
311 err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc);
312
313 if (err != Success) {
314 xp_destroy_surface(pDRIDrawablePriv->sid);
315 free(pDRIDrawablePriv);
316 return NULL;
317 }
318
319 /* save private off of preallocated index */
320 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
321 pDRIDrawablePriv);
322 }
323
324 *widPtr = wid;
325
326 return pDRIDrawablePriv;
327}
328
329/* Return NULL if an error occurs. */
330static DRIDrawablePrivPtr
331CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix)
332{
333 DRIDrawablePrivPtr pDRIDrawablePriv;
334
335 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
336
337 if (pDRIDrawablePriv == NULL) {
338 xp_error err;
339
340 /* allocate a DRI Window Private record */
341 if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) {
342 return NULL;
343 }
344
345 pDRIDrawablePriv->pDraw = (DrawablePtr)pPix;
346 pDRIDrawablePriv->pScreen = pScreen;
347 pDRIDrawablePriv->refCount = 0;
348 pDRIDrawablePriv->drawableIndex = -1;
349 pDRIDrawablePriv->notifiers = NULL;
350
351 /* Passing a null window id to Xplugin in 10.3+ asks for
352 an accelerated offscreen surface. */
353
354 err = xp_create_surface(0, &pDRIDrawablePriv->sid);
355 if (err != Success) {
356 free(pDRIDrawablePriv);
357 return NULL;
358 }
359
360 /*
361 * The DRIUpdateSurface will be called to resize the surface
362 * after this function, if the export is successful.
363 */
364
365 /* save private off of preallocated index */
366 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey,
367 pDRIDrawablePriv);
368 }
369
370 return pDRIDrawablePriv;
371}
372
373Bool
374DRICreateSurface(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)
378{
379 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
380 xp_window_id wid = 0;
381 DRIDrawablePrivPtr pDRIDrawablePriv;
382
383 if (pDrawable->type == DRAWABLE_WINDOW) {
384 /* <rdar://problem/12338921>
385 * http://bugs.winehq.org/show_bug.cgi?id=31751
386 */
387 RootlessStopDrawing((WindowPtr)pDrawable, FALSE);
388
389 pDRIDrawablePriv = CreateSurfaceForWindow(pScreen,
390 (WindowPtr)pDrawable, &wid);
391
392 if (NULL == pDRIDrawablePriv)
393 return FALSE; /*error*/
394 }
395#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
396 else if (pDrawable->type == DRAWABLE_PIXMAP) {
397 pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen,
398 (PixmapPtr)pDrawable);
399
400 if (NULL == pDRIDrawablePriv)
401 return FALSE; /*error*/
402 }
403#endif
404 else {
405 /* We handle GLXPbuffers in a different way (via CGL). */
406 return FALSE;
407 }
408
409 /* Finish initialization of new surfaces */
410 if (pDRIDrawablePriv->refCount == 0) {
411 unsigned int key[2] = { 0 };
412 xp_error err;
413
414 /* try to give the client access to the surface */
415 if (client_id != 0) {
416 /*
417 * Xplugin accepts a 0 wid if the surface id is offscreen, such
418 * as for a pixmap.
419 */
420 err = xp_export_surface(wid, pDRIDrawablePriv->sid,
421 client_id, key);
422 if (err != Success) {
423 xp_destroy_surface(pDRIDrawablePriv->sid);
424 free(pDRIDrawablePriv);
425
426 /*
427 * Now set the dix privates to NULL that were previously set.
428 * This prevents reusing an invalid pointer.
429 */
430 if (pDrawable->type == DRAWABLE_WINDOW) {
431 WindowPtr pWin = (WindowPtr)pDrawable;
432
433 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
434 }
435 else if (pDrawable->type == DRAWABLE_PIXMAP) {
436 PixmapPtr pPix = (PixmapPtr)pDrawable;
437
438 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
439 }
440
441 return FALSE;
442 }
443 }
444
445 pDRIDrawablePriv->key[0] = key[0];
446 pDRIDrawablePriv->key[1] = key[1];
447
448 ++pDRIPriv->nrWindows;
449
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,
454 x_cvt_uint_to_vptr(
455 pDRIDrawablePriv->sid), pDRIDrawablePriv);
456
457 /* track this in case this window is destroyed */
458 AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
459
460 /* Initialize shape */
461 DRIUpdateSurface(pDRIDrawablePriv, pDrawable);
462 }
463
464 pDRIDrawablePriv->refCount++;
465
466 *surface_id = pDRIDrawablePriv->sid;
467
468 if (ret_key != NULL) {
469 ret_key[0] = pDRIDrawablePriv->key[0];
470 ret_key[1] = pDRIDrawablePriv->key[1];
471 }
472
473 if (notify != NULL) {
474 pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers,
475 notify, notify_data);
476 }
477
478 return TRUE;
479}
480
481Bool
482DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
483 void (*notify)(void *, void *), void *notify_data)
484{
485 DRIDrawablePrivPtr pDRIDrawablePriv;
486
487 if (pDrawable->type == DRAWABLE_WINDOW) {
488 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
489 }
490 else if (pDrawable->type == DRAWABLE_PIXMAP) {
491 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
492 }
493 else {
494 return FALSE;
495 }
496
497 if (pDRIDrawablePriv != NULL) {
498 /*
499 * This doesn't seem to be used, because notify is NULL in all callers.
500 */
501
502 if (notify != NULL) {
503 pDRIDrawablePriv->notifiers = x_hook_remove(
504 pDRIDrawablePriv->notifiers,
505 notify, notify_data);
506 }
507
508 --pDRIDrawablePriv->refCount;
509
510 /*
511 * Check if the drawable privates still have a reference to the
512 * surface.
513 */
514
515 if (pDRIDrawablePriv->refCount <= 0) {
516 /*
517 * This calls back to DRIDrawablePrivDelete which
518 * frees the private area and dispatches events, if needed.
519 */
520 FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
521 }
522 }
523
524 return TRUE;
525}
526
527/*
528 * The assumption is that this is called when the refCount of a surface
529 * drops to <= 0, or the window/pixmap is destroyed.
530 */
531Bool
532DRIDrawablePrivDelete(pointer pResource, XID id)
533{
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;
539
540 if (pDrawable->type == DRAWABLE_WINDOW) {
541 pWin = (WindowPtr)pDrawable;
542 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
543 }
544 else if (pDrawable->type == DRAWABLE_PIXMAP) {
545 pPix = (PixmapPtr)pDrawable;
546 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
547 }
548
549 if (pDRIDrawablePriv == NULL) {
550 /*
551 * We reuse __func__ and the resource type for the GLXPixmap code.
552 * Attempt to free a pixmap buffer associated with the resource
553 * if possible.
554 */
555 return DRIFreePixmapImp(pDrawable);
556 }
557
558 if (pDRIDrawablePriv->drawableIndex != -1) {
559 /* release drawable table entry */
560 pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
561 }
562
563 if (pDRIDrawablePriv->sid != 0) {
564 DRISurfaceNotify(pDRIDrawablePriv->sid,
565 AppleDRISurfaceNotifyDestroyed);
566 }
567
568 if (pDRIDrawablePriv->notifiers != NULL)
569 x_hook_free(pDRIDrawablePriv->notifiers);
570
571 free(pDRIDrawablePriv);
572
573 if (pDrawable->type == DRAWABLE_WINDOW) {
574 dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
575 }
576 else if (pDrawable->type == DRAWABLE_PIXMAP) {
577 dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL);
578 }
579
580 --pDRIPriv->nrWindows;
581
582 return TRUE;
583}
584
585void
586DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
587{
588 ScreenPtr pScreen = pWin->drawable.pScreen;
589 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
590 DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
591
592 if (pDRIDrawablePriv) {
593 /* FIXME: something? */
594 }
595
596 pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
597
598 (*pScreen->WindowExposures)(pWin, prgn, bsreg);
599
600 pScreen->WindowExposures = DRIWindowExposures;
601}
602
603void
604DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
605{
606 ScreenPtr pScreen = pWin->drawable.pScreen;
607 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
608 DRIDrawablePrivPtr pDRIDrawablePriv;
609
610 if (pDRIPriv->nrWindows > 0) {
611 pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
612 if (pDRIDrawablePriv != NULL) {
613 DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
614 }
615 }
616
617 /* unwrap */
618 pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
619
620 /* call lower layers */
621 (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
622
623 /* rewrap */
624 pScreen->CopyWindow = DRICopyWindow;
625}
626
627int
628DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
629{
630 ScreenPtr pScreen = pParent->drawable.pScreen;
631 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
632 int returnValue;
633
634 /* unwrap */
635 pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
636
637 /* call lower layers */
638 returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
639
640 /* rewrap */
641 pScreen->ValidateTree = DRIValidateTree;
642
643 return returnValue;
644}
645
646void
647DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
648{
649 ScreenPtr pScreen;
650 DRIScreenPrivPtr pDRIPriv;
651
652 if (pParent) {
653 pScreen = pParent->drawable.pScreen;
654 }
655 else {
656 pScreen = pChild->drawable.pScreen;
657 }
658 pDRIPriv = DRI_SCREEN_PRIV(pScreen);
659
660 if (pDRIPriv->wrap.PostValidateTree) {
661 /* unwrap */
662 pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
663
664 /* call lower layers */
665 (*pScreen->PostValidateTree)(pParent, pChild, kind);
666
667 /* rewrap */
668 pScreen->PostValidateTree = DRIPostValidateTree;
669 }
670}
671
672void
673DRIClipNotify(WindowPtr pWin, int dx, int dy)
674{
675 ScreenPtr pScreen = pWin->drawable.pScreen;
676 DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
677 DRIDrawablePrivPtr pDRIDrawablePriv;
678
679 if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
680 DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable);
681 }
682
683 if (pDRIPriv->wrap.ClipNotify) {
684 pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
685
686 (*pScreen->ClipNotify)(pWin, dx, dy);
687
688 pScreen->ClipNotify = DRIClipNotify;
689 }
690}
691
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).
695 */
696DRIWrappedFuncsRec *
697DRIGetWrappedFuncs(ScreenPtr pScreen)
698{
699 return &(DRI_SCREEN_PRIV(pScreen)->wrap);
700}
701
702void
703DRIQueryVersion(int *majorVersion,
704 int *minorVersion,
705 int *patchVersion)
706{
707 *majorVersion = APPLE_DRI_MAJOR_VERSION;
708 *minorVersion = APPLE_DRI_MINOR_VERSION;
709 *patchVersion = APPLE_DRI_PATCH_VERSION;
710}
711
712/*
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
715 * invalid.
716 */
717void
718DRISurfaceNotify(xp_surface_id id, int kind)
719{
720 DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
721 DRISurfaceNotifyArg arg;
722
723 arg.id = id;
724 arg.kind = kind;
725
726 if (surface_hash != NULL) {
727 pDRIDrawablePriv = x_hash_table_lookup(surface_hash,
728 x_cvt_uint_to_vptr(id), NULL);
729 }
730
731 if (pDRIDrawablePriv == NULL)
732 return;
733
734 if (kind == AppleDRISurfaceNotifyDestroyed) {
735 x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id));
736 }
737
738 x_hook_run(pDRIDrawablePriv->notifiers, &arg);
739
740 if (kind == AppleDRISurfaceNotifyDestroyed) {
741 xp_error error;
742
743 error = xp_destroy_surface(pDRIDrawablePriv->sid);
744
745 if (error)
746 ErrorF("%s: xp_destroy_surface failed: %d\n", __func__, error);
747
748 /* Guard against reuse, even though we are freeing after this. */
749 pDRIDrawablePriv->sid = 0;
750
751 FreeResourceByType(pDRIDrawablePriv->pDraw->id,
752 DRIDrawablePrivResType, FALSE);
753 }
754}
755
756/*
757 * This creates a shared memory buffer for use with GLXPixmaps
758 * and AppleSGLX.
759 */
760Bool
761DRICreatePixmap(ScreenPtr pScreen, Drawable id,
762 DrawablePtr pDrawable, char *path,
763 size_t pathmax)
764{
765 DRIPixmapBufferPtr shared;
766 PixmapPtr pPix;
767
768 if (pDrawable->type != DRAWABLE_PIXMAP)
769 return FALSE;
770
771 pPix = (PixmapPtr)pDrawable;
772
773 shared = malloc(sizeof(*shared));
774 if (NULL == shared) {
775 FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__);
776 }
777
778 shared->pDrawable = pDrawable;
779 shared->refCount = 1;
780
781 if (pDrawable->bitsPerPixel >= 24) {
782 shared->bytesPerPixel = 4;
783 }
784 else if (pDrawable->bitsPerPixel <= 16) {
785 shared->bytesPerPixel = 2;
786 }
787
788 shared->width = pDrawable->width;
789 shared->height = pDrawable->height;
790
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__);
795 }
796
797 shared->fd = shm_open(shared->shmPath,
798 O_RDWR | O_EXCL | O_CREAT,
799 S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
800
801 if (-1 == shared->fd) {
802 free(shared);
803 return FALSE;
804 }
805
806 shared->length = shared->width * shared->height * shared->bytesPerPixel;
807
808 if (-1 == ftruncate(shared->fd, shared->length)) {
809 ErrorF("failed to ftruncate (extend) file.");
810 shm_unlink(shared->shmPath);
811 close(shared->fd);
812 free(shared);
813 return FALSE;
814 }
815
816 shared->buffer = mmap(NULL, shared->length,
817 PROT_READ | PROT_WRITE,
818 MAP_FILE | MAP_SHARED, shared->fd, 0);
819
820 if (MAP_FAILED == shared->buffer) {
821 ErrorF("failed to mmap shared memory.");
822 shm_unlink(shared->shmPath);
823 close(shared->fd);
824 free(shared);
825 return FALSE;
826 }
827
828 strlcpy(path, shared->shmPath, pathmax);
829
830 dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared);
831
832 AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
833
834 return TRUE;
835}
836
837Bool
838DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height,
839 int *pitch, int *bpp, void **ptr)
840{
841 PixmapPtr pPix;
842 DRIPixmapBufferPtr shared;
843
844 if (pDrawable->type != DRAWABLE_PIXMAP)
845 return FALSE;
846
847 pPix = (PixmapPtr)pDrawable;
848
849 shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
850
851 if (NULL == shared)
852 return FALSE;
853
854 assert(pDrawable->width == shared->width);
855 assert(pDrawable->height == shared->height);
856
857 *width = shared->width;
858 *height = shared->height;
859 *bpp = shared->bytesPerPixel;
860 *pitch = shared->width * shared->bytesPerPixel;
861 *ptr = shared->buffer;
862
863 return TRUE;
864}
865
866static Bool
867DRIFreePixmapImp(DrawablePtr pDrawable)
868{
869 DRIPixmapBufferPtr shared;
870 PixmapPtr pPix;
871
872 if (pDrawable->type != DRAWABLE_PIXMAP)
873 return FALSE;
874
875 pPix = (PixmapPtr)pDrawable;
876
877 shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey);
878
879 if (NULL == shared)
880 return FALSE;
881
882 close(shared->fd);
883 munmap(shared->buffer, shared->length);
884 shm_unlink(shared->shmPath);
885 free(shared);
886
887 dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL);
888
889 return TRUE;
890}
891
892void
893DRIDestroyPixmap(DrawablePtr pDrawable)
894{
895 if (DRIFreePixmapImp(pDrawable))
896 FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE);
897
898}