Allow PasteCanvas layers with unset canvas parameters to be exported.
[synfig.git] / synfig-osx / trunk / launcher / dri-surface.c
1 /* $XFree86: xc/programs/Xserver/GL/dri/dri.c,v 1.34 2001/12/10 19:07:19 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 Copyright 2000 VA Linux Systems, Inc.
6 Copyright (c) 2002 Apple Computer, Inc.
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32  * Authors:
33  *   Jens Owen <jens@valinux.com>
34  *   Rickard E. (Rik) Faith <faith@valinux.com>
35  *
36  */
37
38 #ifdef XFree86LOADER
39 #include "xf86.h"
40 #include "xf86_ansic.h"
41 #else
42 #include <sys/time.h>
43 #include <unistd.h>
44 #endif
45
46 #define NEED_REPLIES
47 #define NEED_EVENTS
48 #include "X.h"
49 #include "Xproto.h"
50 #include "misc.h"
51 #include "dixstruct.h"
52 #include "extnsionst.h"
53 #include "colormapst.h"
54 #include "cursorstr.h"
55 #include "scrnintstr.h"
56 #include "windowstr.h"
57 #include "servermd.h"
58 #define _APPLEDRI_SERVER_
59 #include "appledristr.h"
60 #include "swaprep.h"
61 #include "dri-surface.h"
62 #include "dristruct.h"
63 #include "mi.h"
64 #include "mipointer.h"
65 #include "rootless-common.h"
66 #include "x-hash.h"
67 #include "x-hook.h"
68
69 #include <AvailabilityMacros.h>
70
71 static int DRIScreenPrivIndex = -1;
72 static int DRIWindowPrivIndex = -1;
73 static int DRIPixmapPrivIndex = -1;
74 static unsigned long DRIGeneration = 0;
75
76 static RESTYPE DRIDrawablePrivResType;
77
78 static x_hash_table *surface_hash;      /* maps surface ids -> drawablePrivs */
79
80 Bool
81 DRIScreenInit(ScreenPtr pScreen)
82 {
83     DRIScreenPrivPtr    pDRIPriv;
84     int                 i;
85
86     if (DRIGeneration != serverGeneration) {
87         if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
88             return FALSE;
89         DRIGeneration = serverGeneration;
90     }
91
92     pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
93     if (!pDRIPriv) {
94         pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
95         return FALSE;
96     }
97
98     pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
99     pDRIPriv->directRenderingSupport = TRUE;
100     pDRIPriv->nrWindows = 0;
101
102     /* Initialize drawable tables */
103     for( i=0; i < DRI_MAX_DRAWABLES; i++) {
104         pDRIPriv->DRIDrawables[i] = NULL;
105     }
106
107     return TRUE;
108 }
109
110 Bool
111 DRIFinishScreenInit(ScreenPtr pScreen)
112 {
113     DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
114
115     /* Wrap DRI support */
116     pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
117     pScreen->ValidateTree = DRIValidateTree;
118
119     pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
120     pScreen->PostValidateTree = DRIPostValidateTree;
121
122     pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
123     pScreen->WindowExposures = DRIWindowExposures;
124
125     pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
126     pScreen->CopyWindow = DRICopyWindow;
127
128     pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
129     pScreen->ClipNotify = DRIClipNotify;
130
131     ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
132
133     return TRUE;
134 }
135
136 void
137 DRICloseScreen(ScreenPtr pScreen)
138 {
139     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
140
141     if (pDRIPriv && pDRIPriv->directRenderingSupport) {
142         xfree(pDRIPriv);
143         pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
144     }
145 }
146
147 Bool
148 DRIExtensionInit(void)
149 {
150     int                 i;
151     ScreenPtr           pScreen;
152
153     if (DRIScreenPrivIndex < 0) {
154         return FALSE;
155     }
156
157     /* Allocate a window private index with a zero sized private area for
158      * each window, then should a window become a DRI window, we'll hang
159      * a DRIWindowPrivateRec off of this private index.
160      */
161     if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0)
162         return FALSE;
163     if ((DRIPixmapPrivIndex = AllocatePixmapPrivateIndex()) < 0)
164         return FALSE;
165
166     DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete);
167
168     for (i = 0; i < screenInfo.numScreens; i++)
169     {
170         pScreen = screenInfo.screens[i];
171         if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0))
172             return FALSE;
173         if (!AllocatePixmapPrivate(pScreen, DRIPixmapPrivIndex, 0))
174             return FALSE;
175     }
176
177     return TRUE;
178 }
179
180 void
181 DRIReset(void)
182 {
183     /*
184      * This stub routine is called when the X Server recycles, resources
185      * allocated by DRIExtensionInit need to be managed here.
186      *
187      * Currently this routine is a stub because all the interesting resources
188      * are managed via the screen init process.
189      */
190 }
191
192 Bool
193 DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
194 {
195     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
196
197     if (pDRIPriv)
198         *isCapable = pDRIPriv->directRenderingSupport;
199     else
200         *isCapable = FALSE;
201
202     return TRUE;
203 }
204
205 Bool
206 DRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
207 {
208 #if 0
209     /* FIXME: something? */
210
211     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
212
213     if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
214 #endif
215     return TRUE;
216 }
217
218 static void
219 DRIUpdateSurface (DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
220 {
221     WindowPtr pTopWin;
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
238         DRIStopDrawing (&pWin->drawable, FALSE);
239
240         pTopWin = TopLevelParent (pWin);
241
242         wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth);
243         wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth);
244         wc.width = pWin->drawable.width;
245         wc.height = pWin->drawable.height;
246         wc.bit_gravity = XP_GRAVITY_NONE;
247
248         wc.shape_nrects = REGION_NUM_RECTS (&pWin->clipList);
249         wc.shape_rects = REGION_RECTS (&pWin->clipList);
250         wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth);
251         wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth);
252
253         flags |= XP_BOUNDS | XP_SHAPE;
254
255         pDRIDrawablePriv->x = pWin->drawable.x - pTopWin->borderWidth;
256         pDRIDrawablePriv->y = pWin->drawable.y - pTopWin->borderWidth;
257
258     } else if (pDraw->type == DRAWABLE_PIXMAP) {
259         wc.x = 0;
260         wc.y = 0;
261         wc.width = pDraw->width;
262         wc.height = pDraw->height;
263         wc.bit_gravity = XP_GRAVITY_NONE;
264         flags |= XP_BOUNDS;
265     }
266
267     xp_configure_surface (pDRIDrawablePriv->sid, flags, &wc);
268 }
269
270 Bool
271 DRICreateSurface (ScreenPtr pScreen, Drawable id,
272                   DrawablePtr pDrawable, xp_client_id client_id,
273                   xp_surface_id *surface_id, unsigned int ret_key[2],
274                   void (*notify) (void *arg, void *data), void *notify_data)
275 {
276     DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
277     DRIDrawablePrivPtr  pDRIDrawablePriv;
278     WindowPtr           pWin;
279     PixmapPtr           pPix;
280     xp_window_id        wid = 0;
281
282     if (pDrawable->type == DRAWABLE_WINDOW) {
283         pWin = (WindowPtr)pDrawable;
284         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
285         if (pDRIDrawablePriv == NULL) {
286             WindowPtr pTopWin;
287             xp_error err;
288             xp_window_changes wc;
289
290             pTopWin = TopLevelParent (pWin);
291
292             /* allocate a DRI Window Private record */
293             if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) {
294                 return FALSE;
295             }
296
297             pDRIDrawablePriv->pDraw = pDrawable;
298             pDRIDrawablePriv->pScreen = pScreen;
299             pDRIDrawablePriv->refCount = 0;
300             pDRIDrawablePriv->drawableIndex = -1;
301             pDRIDrawablePriv->notifiers = NULL;
302
303             /* find the physical window */
304             wid = RootlessGetPhysicalWindow (pTopWin, TRUE);
305             if (wid == 0) {
306                 xfree (pDRIDrawablePriv);
307                 return FALSE;
308             }
309
310             /* allocate the physical surface */
311             err = xp_create_surface (wid, &pDRIDrawablePriv->sid);
312             if (err != Success) {
313                 xfree (pDRIDrawablePriv);
314                 return FALSE;
315             }
316
317             /* Make it visible */
318             wc.stack_mode = XP_MAPPED_ABOVE;
319             wc.sibling = 0;
320             err = xp_configure_surface (pDRIDrawablePriv->sid,
321                                         XP_STACKING, &wc);
322             if (err != Success)
323             {
324                 xp_destroy_surface (pDRIDrawablePriv->sid);
325                 xfree (pDRIDrawablePriv);
326                 return FALSE;
327             }
328
329             /* save private off of preallocated index */
330             pWin->devPrivates[DRIWindowPrivIndex].ptr = (pointer)pDRIDrawablePriv;
331         }
332     }
333 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
334     else if (pDrawable->type == DRAWABLE_PIXMAP) {
335         pPix = (PixmapPtr)pDrawable;
336         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
337         if (pDRIDrawablePriv == NULL) {
338             xp_error err;
339
340             /* allocate a DRI Window Private record */
341             if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) {
342                 return FALSE;
343             }
344
345             pDRIDrawablePriv->pDraw = pDrawable;
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                 xfree (pDRIDrawablePriv);
357                 return FALSE;
358             }
359
360             /* save private off of preallocated index */
361             pPix->devPrivates[DRIPixmapPrivIndex].ptr = (pointer)pDRIDrawablePriv;
362         }
363     }
364 #endif
365     else { /* for GLX 1.3, a PBuffer */
366         /* NOT_DONE */
367         return FALSE;
368     }
369
370     /* Finish initialization of new surfaces */
371     if (pDRIDrawablePriv->refCount == 0) {
372         unsigned int key[2] = {0};
373         xp_error err;
374
375         /* try to give the client access to the surface
376            FIXME: how to export pixmaps? */
377         if (client_id != 0 && wid != 0)
378         {
379             err = xp_export_surface (wid, pDRIDrawablePriv->sid,
380                                      client_id, key);
381             if (err != Success) {
382                 xp_destroy_surface (pDRIDrawablePriv->sid);
383                 xfree (pDRIDrawablePriv);
384                 return FALSE;
385             }
386         }
387
388         pDRIDrawablePriv->key[0] = key[0];
389         pDRIDrawablePriv->key[1] = key[1];
390
391         ++pDRIPriv->nrWindows;
392
393         /* and stash it by surface id */
394         if (surface_hash == NULL)
395             surface_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
396         x_hash_table_insert (surface_hash,
397                              (void *) pDRIDrawablePriv->sid, pDRIDrawablePriv);
398
399         /* track this in case this window is destroyed */
400         AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
401
402         /* Initialize shape */
403         DRIUpdateSurface (pDRIDrawablePriv, pDrawable);
404     }
405
406     pDRIDrawablePriv->refCount++;
407
408     *surface_id = pDRIDrawablePriv->sid;
409
410     if (ret_key != NULL) {
411         ret_key[0] = pDRIDrawablePriv->key[0];
412         ret_key[1] = pDRIDrawablePriv->key[1];
413     }
414
415     if (notify != NULL) {
416         pDRIDrawablePriv->notifiers = x_hook_add (pDRIDrawablePriv->notifiers,
417                                                   notify, notify_data);
418     }
419
420     return TRUE;
421 }
422
423 Bool
424 DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
425                   void (*notify) (void *, void *), void *notify_data)
426 {
427     DRIDrawablePrivPtr  pDRIDrawablePriv;
428
429     if (pDrawable->type == DRAWABLE_WINDOW) {
430         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
431     } else if (pDrawable->type == DRAWABLE_PIXMAP) {
432         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
433     } else {
434         return FALSE;
435     }
436
437     if (pDRIDrawablePriv != NULL) {
438         if (notify != NULL) {
439             pDRIDrawablePriv->notifiers = x_hook_remove (pDRIDrawablePriv->notifiers,
440                                                          notify, notify_data);
441         }
442         if (--pDRIDrawablePriv->refCount <= 0) {
443             /* This calls back to DRIDrawablePrivDelete
444                which frees the private area */
445             FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
446         }
447     }
448
449     return TRUE;
450 }
451
452 Bool
453 DRIDrawablePrivDelete(pointer pResource, XID id)
454 {
455     DrawablePtr         pDrawable = (DrawablePtr)pResource;
456     DRIScreenPrivPtr    pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
457     DRIDrawablePrivPtr  pDRIDrawablePriv = NULL;
458     WindowPtr           pWin = NULL;
459     PixmapPtr           pPix = NULL;
460
461     if (pDrawable->type == DRAWABLE_WINDOW) {
462         pWin = (WindowPtr)pDrawable;
463         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
464         DRIStopDrawing (pDrawable, FALSE);
465         pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing,
466                                            pDRIDrawablePriv);
467     } else if (pDrawable->type == DRAWABLE_PIXMAP) {
468         pPix = (PixmapPtr)pDrawable;
469         pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
470     }
471
472     if (pDRIDrawablePriv == NULL)
473         return FALSE;
474
475     if (pDRIDrawablePriv->drawableIndex != -1) {
476         /* release drawable table entry */
477         pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
478     }
479
480     if (pDRIDrawablePriv->sid != 0) {
481         xp_destroy_surface (pDRIDrawablePriv->sid);
482         x_hash_table_remove (surface_hash, (void *) pDRIDrawablePriv->sid);
483     }
484
485     if (pDRIDrawablePriv->notifiers != NULL)
486         x_hook_free (pDRIDrawablePriv->notifiers);
487
488     xfree(pDRIDrawablePriv);
489
490     if (pDrawable->type == DRAWABLE_WINDOW) {
491         pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
492     } else if (pDrawable->type == DRAWABLE_PIXMAP) {
493         pPix->devPrivates[DRIPixmapPrivIndex].ptr = NULL;
494     }
495
496     --pDRIPriv->nrWindows;
497
498     return TRUE;
499 }
500
501 void
502 DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
503 {
504     ScreenPtr pScreen = pWin->drawable.pScreen;
505     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
506     DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
507
508     if(pDRIDrawablePriv) {
509         /* FIXME: something? */
510     }
511
512     pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
513
514     (*pScreen->WindowExposures)(pWin, prgn, bsreg);
515
516     pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
517     pScreen->WindowExposures = DRIWindowExposures;
518
519 }
520
521 void
522 DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
523 {
524     ScreenPtr pScreen = pWin->drawable.pScreen;
525     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
526     DRIDrawablePrivPtr pDRIDrawablePriv;
527
528     if(pDRIPriv->nrWindows > 0) {
529        pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW (pWin);
530        if (pDRIDrawablePriv != NULL) {
531            DRIUpdateSurface (pDRIDrawablePriv, &pWin->drawable);
532        }
533     }
534
535     /* unwrap */
536     pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
537
538     /* call lower layers */
539     (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
540
541     /* rewrap */
542     pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
543     pScreen->CopyWindow = DRICopyWindow;
544 }
545
546 int
547 DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
548 {
549     ScreenPtr pScreen = pParent->drawable.pScreen;
550     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
551     int returnValue;
552
553     /* unwrap */
554     pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
555
556     /* call lower layers */
557     returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
558
559     /* rewrap */
560     pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
561     pScreen->ValidateTree = DRIValidateTree;
562
563     return returnValue;
564 }
565
566 void
567 DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
568 {
569     ScreenPtr pScreen;
570     DRIScreenPrivPtr pDRIPriv;
571
572     if (pParent) {
573         pScreen = pParent->drawable.pScreen;
574     } else {
575         pScreen = pChild->drawable.pScreen;
576     }
577     pDRIPriv = DRI_SCREEN_PRIV(pScreen);
578
579     if (pDRIPriv->wrap.PostValidateTree) {
580         /* unwrap */
581         pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
582
583         /* call lower layers */
584         (*pScreen->PostValidateTree)(pParent, pChild, kind);
585
586         /* rewrap */
587         pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
588         pScreen->PostValidateTree = DRIPostValidateTree;
589     }
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         pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
609         pScreen->ClipNotify = DRIClipNotify;
610     }
611 }
612
613 /* This lets get at the unwrapped functions so that they can correctly
614  * call the lowerlevel functions, and choose whether they will be
615  * called at every level of recursion (eg in validatetree).
616  */
617 DRIWrappedFuncsRec *
618 DRIGetWrappedFuncs(ScreenPtr pScreen)
619 {
620     return &(DRI_SCREEN_PRIV(pScreen)->wrap);
621 }
622
623 void
624 DRIQueryVersion(int *majorVersion,
625                 int *minorVersion,
626                 int *patchVersion)
627 {
628     *majorVersion = APPLE_DRI_MAJOR_VERSION;
629     *minorVersion = APPLE_DRI_MINOR_VERSION;
630     *patchVersion = APPLE_DRI_PATCH_VERSION;
631 }
632
633 void
634 DRISurfaceNotify (xp_surface_id id, int kind)
635 {
636     DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
637     DRISurfaceNotifyArg arg;
638
639     arg.id = id;
640     arg.kind = kind;
641
642     if (surface_hash != NULL)
643     {
644         pDRIDrawablePriv = x_hash_table_lookup (surface_hash,
645                                                 (void *) id, NULL);
646     }
647
648     if (pDRIDrawablePriv == NULL)
649         return;
650
651     if (kind == AppleDRISurfaceNotifyDestroyed)
652     {
653         pDRIDrawablePriv->sid = 0;
654         x_hash_table_remove (surface_hash, (void *) id);
655     }
656
657     x_hook_run (pDRIDrawablePriv->notifiers, &arg);
658
659     if (kind == AppleDRISurfaceNotifyDestroyed)
660     {
661         /* Kill off the handle. */
662
663         FreeResourceByType (pDRIDrawablePriv->pDraw->id,
664                             DRIDrawablePrivResType, FALSE);
665     }
666 }
667
668 \f
669 /* Experimental support for X drawing directly into VRAM surfaces. */
670
671 Bool
672 DRIStartDrawing (DrawablePtr pDraw)
673 {
674 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
675     return FALSE;
676 #else
677     DRIDrawablePrivPtr priv = NULL;
678     DRIScreenPrivPtr pDRIPriv;
679
680     if (pDraw->type == DRAWABLE_WINDOW)
681         priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
682 #if 0
683     /* FIXME: support pixmaps */
684     else if (pDraw->type == DRAWABLE_PIXMAP)
685         priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw);
686 #endif
687
688     if (priv == NULL)
689         return FALSE;
690
691     pDRIPriv = DRI_SCREEN_PRIV(priv->pScreen);
692
693     if (!priv->is_drawing)
694     {
695         xp_error err;
696         xp_box r;
697
698         err = xp_lock_window (priv->sid, NULL, NULL,
699                               &priv->data, &priv->rowbytes, &r);
700         if (err != Success)
701             return FALSE;
702
703         if (pDraw->type == DRAWABLE_WINDOW)
704         {
705             WindowPtr pWin = (WindowPtr) pDraw;
706             int bw = wBorderWidth (pWin);
707
708             priv->pixmap =
709             GetScratchPixmapHeader(pWin->drawable.pScreen, r.x2 - r.x1,
710                                    r.y2 - r.y1, pWin->drawable.depth,
711                                    pWin->drawable.bitsPerPixel,
712                                    priv->rowbytes, priv->data);
713             TranslatePixmapBase (priv->pixmap,
714                                  - (pWin->drawable.x - bw),
715                                  - (pWin->drawable.y - bw));
716         }
717
718         priv->is_drawing = TRUE;
719         pDRIPriv->drawing = x_list_prepend (pDRIPriv->drawing, priv);
720     }
721     
722     if (pDraw->type == DRAWABLE_WINDOW)
723     {
724         WindowPtr pWin = (WindowPtr) pDraw;
725
726         priv->oldPixmap = pWin->drawable.pScreen->GetWindowPixmap (pWin);
727         pWin->drawable.pScreen->SetWindowPixmap (pWin, priv->pixmap);
728     }
729
730     return TRUE;
731 #endif
732 }
733
734 Bool
735 DRIStopDrawing (DrawablePtr pDraw, Bool flush)
736 {
737 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
738     return FALSE;
739 #else
740     DRIDrawablePrivPtr priv = NULL;
741     ScreenPtr pScreen;
742     DRIScreenPrivPtr pDRIPriv;
743
744     if (pDraw->type == DRAWABLE_WINDOW)
745         priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
746     else if (pDraw->type == DRAWABLE_PIXMAP)
747         priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw);
748
749     if (priv == NULL)
750         return FALSE;
751
752     pScreen = priv->pScreen;
753     pDRIPriv = DRI_SCREEN_PRIV(pScreen);
754
755     if (priv->is_drawing)
756     {
757         xp_unlock_window (priv->sid, flush);
758
759         if (pDraw->type == DRAWABLE_WINDOW)
760         {
761             FreeScratchPixmapHeader (priv->pixmap);
762             pScreen->SetWindowPixmap ((WindowPtr)pDraw, priv->oldPixmap);
763         }
764
765         priv->pixmap = NULL;
766
767         /* If we didn't flush don't forget that we still need to.. */
768         if (flush)
769             pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing, priv);
770
771         priv->is_drawing = FALSE;
772     }
773     else if (flush)
774     {
775         xp_flush_window (priv->sid);
776     }
777
778     return TRUE;
779 #endif /* 10.3 */
780 }
781
782 /*  true iff two Boxes overlap */
783 #define EXTENTCHECK(r1,r2) \
784       (!( ((r1)->x2 <= (r2)->x1)  || \
785           ((r1)->x1 >= (r2)->x2)  || \
786           ((r1)->y2 <= (r2)->y1)  || \
787           ((r1)->y1 >= (r2)->y2) ) )
788
789 Bool
790 DRIDamageRegion (DrawablePtr pDraw, RegionPtr pRegion)
791 {
792 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
793     return FALSE;
794 #else
795     DRIDrawablePrivPtr priv = NULL;
796     RegionRec clipped;
797     BoxPtr b1, b2;
798
799     if (pDraw->type == DRAWABLE_WINDOW)
800         priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
801
802     if (priv == NULL)
803         return FALSE;
804
805     /* adapted from RootlessDamageRegion () */
806
807     if (pDraw->type == DRAWABLE_WINDOW)
808     {
809         WindowPtr pWin = (WindowPtr) pDraw;
810
811         b1 = REGION_EXTENTS (pWin->drawable.pScreen, &pWin->borderClip);
812         b2 = REGION_EXTENTS (pWin->drawable.pScreen, pRegion);
813
814         if (EXTENTCHECK (b1, b2))
815         {
816             /* Regions may overlap. */
817
818             if (REGION_NUM_RECTS (pRegion) == 1)
819             {
820                 int in;
821
822                 /* Damaged region only has a single rect, so we can
823                    just compare that against the region */
824
825                 in = RECT_IN_REGION (pWin->drawable.pScreen, &pWin->borderClip,
826                                      REGION_RECTS (pRegion));
827                 if (in == rgnIN)
828                 {
829                     /* clip totally contains pRegion */
830
831                     xp_mark_window (priv->sid, REGION_NUM_RECTS (pRegion),
832                                     REGION_RECTS (pRegion),
833                                     -priv->x, -priv->y);
834
835                     RootlessQueueRedisplay (pWin->drawable.pScreen);
836                     goto out;
837                 }
838                 else if (in == rgnOUT)
839                 {
840                     /* clip doesn't contain pRegion */
841
842                     goto out;
843                 }
844             }
845
846             /* clip overlaps pRegion, need to intersect */
847
848             REGION_INIT (pWin->drawable.pScreen, &clipped, NullBox, 0);
849             REGION_INTERSECT (pWin->drawable.pScreen, &clipped,
850                               &pWin->borderClip, pRegion);
851
852             xp_mark_window (priv->sid, REGION_NUM_RECTS (&clipped),
853                             REGION_RECTS (&clipped), -priv->x, -priv->y);
854
855             REGION_UNINIT (pWin->drawable.pScreen, &clipped);
856
857             RootlessQueueRedisplay (pWin->drawable.pScreen);
858         }
859     }
860
861 out:
862     return TRUE;
863 #endif /* 10.3 */
864 }
865
866 void
867 DRISynchronizeDrawable (DrawablePtr pDraw, Bool flush)
868 {
869 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
870     ScreenPtr pScreen;
871     DRIScreenPrivPtr pDRIPriv;
872     DRIDrawablePrivPtr priv;
873     x_list *node, *copy;
874
875     pScreen = pDraw->pScreen;
876     pDRIPriv = DRI_SCREEN_PRIV(pScreen);
877
878     if (pDRIPriv == NULL || pDRIPriv->drawing == NULL)
879         return;
880
881     if (pDraw->type == DRAWABLE_WINDOW)
882     {
883         WindowPtr pWin = TopLevelParent ((WindowPtr) pDraw);
884
885         /* need to find _any_ window under pWin that is drawing. Scan the
886            list looking for candidates. */
887
888         copy = x_list_copy (pDRIPriv->drawing);
889
890         for (node = copy; node != NULL; node = node->next)
891         {
892             priv = node->data;
893
894             if (priv->pDraw->type == DRAWABLE_WINDOW
895                 && TopLevelParent ((WindowPtr) priv->pDraw) == pWin)
896             {
897                 DRIStopDrawing (priv->pDraw, flush);
898             }
899         }
900
901         x_list_free (copy);
902     }
903     else
904     {
905         DRIStopDrawing (pDraw, flush);
906     }
907 #endif /* 10.3 */
908 }
909
910 void
911 DRISynchronize (Bool flush)
912 {
913 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
914     int i;
915     ScreenPtr pScreen;
916     DRIScreenPrivPtr pDRIPriv;
917     DRIDrawablePrivPtr priv;
918     x_list *node, *copy;
919
920     for (i = 0; i < screenInfo.numScreens; i++)
921     {
922         pScreen = screenInfo.screens[i];
923         pDRIPriv = DRI_SCREEN_PRIV(pScreen);
924
925         if (pDRIPriv == NULL || pDRIPriv->drawing == NULL)
926             continue;
927
928         copy = x_list_copy (pDRIPriv->drawing);
929
930         for (node = copy; node != NULL; node = node->next)
931         {
932             priv = node->data;
933
934             DRIStopDrawing (priv->pDraw, flush);
935         }
936
937         x_list_free (copy);
938     }
939 #endif /* 10.3 */
940 }