xref: /OK3568_Linux_fs/external/xserver/hw/xquartz/GL/indirect.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * GLX implementation that uses Apple's OpenGL.framework
3*4882a593Smuzhiyun  * (Indirect rendering path -- it's also used for some direct mode code too)
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2007-2012 Apple Inc.
6*4882a593Smuzhiyun  * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
7*4882a593Smuzhiyun  * Copyright (c) 2002 Greg Parker. All Rights Reserved.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Portions of this file are copied from Mesa's xf86glx.c,
10*4882a593Smuzhiyun  * which contains the following copyright:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
13*4882a593Smuzhiyun  * All Rights Reserved.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
16*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
17*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
18*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
20*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
23*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28*4882a593Smuzhiyun  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
29*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
35*4882a593Smuzhiyun #include <dix-config.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include <dlfcn.h>
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #include <OpenGL/OpenGL.h>
41*4882a593Smuzhiyun #include <OpenGL/gl.h>     /* Just to prevent glxserver.h from loading mesa's and colliding with OpenGL.h */
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #include <X11/Xproto.h>
44*4882a593Smuzhiyun #include <GL/glxproto.h>
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #include <glxserver.h>
47*4882a593Smuzhiyun #include <glxutil.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #include "x-hash.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include "visualConfigs.h"
52*4882a593Smuzhiyun #include "dri.h"
53*4882a593Smuzhiyun #include "extension_string.h"
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #include "darwin.h"
56*4882a593Smuzhiyun #define GLAQUA_DEBUG_MSG(msg, args ...) ASL_LOG(ASL_LEVEL_DEBUG, "GLXAqua", \
57*4882a593Smuzhiyun                                                 msg, \
58*4882a593Smuzhiyun                                                 ## args)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun __GLXprovider *
61*4882a593Smuzhiyun GlxGetDRISWrastProvider(void);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static void
64*4882a593Smuzhiyun setup_dispatch_table(void);
65*4882a593Smuzhiyun GLuint
66*4882a593Smuzhiyun __glFloorLog2(GLuint val);
67*4882a593Smuzhiyun void
68*4882a593Smuzhiyun warn_func(void * p1, char *format, ...);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun // some prototypes
71*4882a593Smuzhiyun static __GLXscreen *
72*4882a593Smuzhiyun __glXAquaScreenProbe(ScreenPtr pScreen);
73*4882a593Smuzhiyun static __GLXdrawable *
74*4882a593Smuzhiyun __glXAquaScreenCreateDrawable(ClientPtr client, __GLXscreen *screen,
75*4882a593Smuzhiyun                               DrawablePtr pDraw, XID drawId, int type,
76*4882a593Smuzhiyun                               XID glxDrawId,
77*4882a593Smuzhiyun                               __GLXconfig *conf);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static void
80*4882a593Smuzhiyun __glXAquaContextDestroy(__GLXcontext *baseContext);
81*4882a593Smuzhiyun static int
82*4882a593Smuzhiyun __glXAquaContextMakeCurrent(__GLXcontext *baseContext);
83*4882a593Smuzhiyun static int
84*4882a593Smuzhiyun __glXAquaContextLoseCurrent(__GLXcontext *baseContext);
85*4882a593Smuzhiyun static int
86*4882a593Smuzhiyun __glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
87*4882a593Smuzhiyun                      unsigned long mask);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static CGLPixelFormatObj
90*4882a593Smuzhiyun makeFormat(__GLXconfig *conf);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun __GLXprovider __glXDRISWRastProvider = {
93*4882a593Smuzhiyun     __glXAquaScreenProbe,
94*4882a593Smuzhiyun     "Core OpenGL",
95*4882a593Smuzhiyun     NULL
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun typedef struct __GLXAquaScreen __GLXAquaScreen;
99*4882a593Smuzhiyun typedef struct __GLXAquaContext __GLXAquaContext;
100*4882a593Smuzhiyun typedef struct __GLXAquaDrawable __GLXAquaDrawable;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun  * The following structs must keep the base as the first member.
104*4882a593Smuzhiyun  * It's used to treat the start of the struct as a different struct
105*4882a593Smuzhiyun  * in GLX.
106*4882a593Smuzhiyun  *
107*4882a593Smuzhiyun  * Note: these structs should be initialized with xcalloc or memset
108*4882a593Smuzhiyun  * prior to usage, and some of them require initializing
109*4882a593Smuzhiyun  * the base with function pointers.
110*4882a593Smuzhiyun  */
111*4882a593Smuzhiyun struct __GLXAquaScreen {
112*4882a593Smuzhiyun     __GLXscreen base;
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun struct __GLXAquaContext {
116*4882a593Smuzhiyun     __GLXcontext base;
117*4882a593Smuzhiyun     CGLContextObj ctx;
118*4882a593Smuzhiyun     CGLPixelFormatObj pixelFormat;
119*4882a593Smuzhiyun     xp_surface_id sid;
120*4882a593Smuzhiyun     unsigned isAttached : 1;
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun struct __GLXAquaDrawable {
124*4882a593Smuzhiyun     __GLXdrawable base;
125*4882a593Smuzhiyun     DrawablePtr pDraw;
126*4882a593Smuzhiyun     xp_surface_id sid;
127*4882a593Smuzhiyun     __GLXAquaContext *context;
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun static __GLXcontext *
__glXAquaScreenCreateContext(__GLXscreen * screen,__GLXconfig * conf,__GLXcontext * baseShareContext,unsigned num_attribs,const uint32_t * attribs,int * error)131*4882a593Smuzhiyun __glXAquaScreenCreateContext(__GLXscreen *screen,
132*4882a593Smuzhiyun                              __GLXconfig *conf,
133*4882a593Smuzhiyun                              __GLXcontext *baseShareContext,
134*4882a593Smuzhiyun                              unsigned num_attribs,
135*4882a593Smuzhiyun                              const uint32_t *attribs,
136*4882a593Smuzhiyun                              int *error)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun     __GLXAquaContext *context;
139*4882a593Smuzhiyun     __GLXAquaContext *shareContext = (__GLXAquaContext *)baseShareContext;
140*4882a593Smuzhiyun     CGLError gl_err;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun     /* Unused (for now?) */
143*4882a593Smuzhiyun     (void)num_attribs;
144*4882a593Smuzhiyun     (void)attribs;
145*4882a593Smuzhiyun     (void)error;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glXAquaScreenCreateContext\n");
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     context = calloc(1, sizeof(__GLXAquaContext));
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     if (context == NULL)
152*4882a593Smuzhiyun         return NULL;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun     memset(context, 0, sizeof *context);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     context->base.pGlxScreen = screen;
157*4882a593Smuzhiyun     context->base.config = conf;
158*4882a593Smuzhiyun     context->base.destroy = __glXAquaContextDestroy;
159*4882a593Smuzhiyun     context->base.makeCurrent = __glXAquaContextMakeCurrent;
160*4882a593Smuzhiyun     context->base.loseCurrent = __glXAquaContextLoseCurrent;
161*4882a593Smuzhiyun     context->base.copy = __glXAquaContextCopy;
162*4882a593Smuzhiyun     /*FIXME verify that the context->base is fully initialized. */
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun     context->pixelFormat = makeFormat(conf);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     if (!context->pixelFormat) {
167*4882a593Smuzhiyun         free(context);
168*4882a593Smuzhiyun         return NULL;
169*4882a593Smuzhiyun     }
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     context->ctx = NULL;
172*4882a593Smuzhiyun     gl_err = CGLCreateContext(context->pixelFormat,
173*4882a593Smuzhiyun                               shareContext ? shareContext->ctx : NULL,
174*4882a593Smuzhiyun                               &context->ctx);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun     if (gl_err != 0) {
177*4882a593Smuzhiyun         ErrorF("CGLCreateContext error: %s\n", CGLErrorString(gl_err));
178*4882a593Smuzhiyun         CGLDestroyPixelFormat(context->pixelFormat);
179*4882a593Smuzhiyun         free(context);
180*4882a593Smuzhiyun         return NULL;
181*4882a593Smuzhiyun     }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun     setup_dispatch_table();
184*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glAquaCreateContext done\n");
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun     return &context->base;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /* maps from surface id -> list of __GLcontext */
190*4882a593Smuzhiyun static x_hash_table *surface_hash;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static void
__glXAquaContextDestroy(__GLXcontext * baseContext)193*4882a593Smuzhiyun __glXAquaContextDestroy(__GLXcontext *baseContext)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun     x_list *lst;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     __GLXAquaContext *context = (__GLXAquaContext *)baseContext;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glAquaContextDestroy (ctx %p)\n", baseContext);
200*4882a593Smuzhiyun     if (context != NULL) {
201*4882a593Smuzhiyun         if (context->sid != 0 && surface_hash != NULL) {
202*4882a593Smuzhiyun             lst =
203*4882a593Smuzhiyun                 x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
204*4882a593Smuzhiyun                                         context->sid), NULL);
205*4882a593Smuzhiyun             lst = x_list_remove(lst, context);
206*4882a593Smuzhiyun             x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(
207*4882a593Smuzhiyun                                     context->sid), lst);
208*4882a593Smuzhiyun         }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun         if (context->ctx != NULL)
211*4882a593Smuzhiyun             CGLDestroyContext(context->ctx);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun         if (context->pixelFormat != NULL)
214*4882a593Smuzhiyun             CGLDestroyPixelFormat(context->pixelFormat);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun         free(context);
217*4882a593Smuzhiyun     }
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun static int
__glXAquaContextLoseCurrent(__GLXcontext * baseContext)221*4882a593Smuzhiyun __glXAquaContextLoseCurrent(__GLXcontext *baseContext)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun     CGLError gl_err;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glAquaLoseCurrent (ctx 0x%p)\n", baseContext);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun     gl_err = CGLSetCurrentContext(NULL);
228*4882a593Smuzhiyun     if (gl_err != 0)
229*4882a593Smuzhiyun         ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err));
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun     /*
232*4882a593Smuzhiyun      * There should be no need to set __glXLastContext to NULL here, because
233*4882a593Smuzhiyun      * glxcmds.c does it as part of the context cache flush after calling
234*4882a593Smuzhiyun      * this.
235*4882a593Smuzhiyun      */
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     return GL_TRUE;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun /* Called when a surface is destroyed as a side effect of destroying
241*4882a593Smuzhiyun    the window it's attached to. */
242*4882a593Smuzhiyun static void
surface_notify(void * _arg,void * data)243*4882a593Smuzhiyun surface_notify(void *_arg, void *data)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun     DRISurfaceNotifyArg *arg = (DRISurfaceNotifyArg *)_arg;
246*4882a593Smuzhiyun     __GLXAquaDrawable *draw = (__GLXAquaDrawable *)data;
247*4882a593Smuzhiyun     __GLXAquaContext *context;
248*4882a593Smuzhiyun     x_list *lst;
249*4882a593Smuzhiyun     if (_arg == NULL || data == NULL) {
250*4882a593Smuzhiyun         ErrorF("surface_notify called with bad params");
251*4882a593Smuzhiyun         return;
252*4882a593Smuzhiyun     }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("surface_notify(%p, %p)\n", _arg, data);
255*4882a593Smuzhiyun     switch (arg->kind) {
256*4882a593Smuzhiyun     case AppleDRISurfaceNotifyDestroyed:
257*4882a593Smuzhiyun         if (surface_hash != NULL)
258*4882a593Smuzhiyun             x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(arg->id));
259*4882a593Smuzhiyun         draw->pDraw = NULL;
260*4882a593Smuzhiyun         draw->sid = 0;
261*4882a593Smuzhiyun         break;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun     case AppleDRISurfaceNotifyChanged:
264*4882a593Smuzhiyun         if (surface_hash != NULL) {
265*4882a593Smuzhiyun             lst =
266*4882a593Smuzhiyun                 x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
267*4882a593Smuzhiyun                                         arg->id), NULL);
268*4882a593Smuzhiyun             for (; lst != NULL; lst = lst->next) {
269*4882a593Smuzhiyun                 context = lst->data;
270*4882a593Smuzhiyun                 xp_update_gl_context(context->ctx);
271*4882a593Smuzhiyun             }
272*4882a593Smuzhiyun         }
273*4882a593Smuzhiyun         break;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun     default:
276*4882a593Smuzhiyun         ErrorF("surface_notify: unknown kind %d\n", arg->kind);
277*4882a593Smuzhiyun         break;
278*4882a593Smuzhiyun     }
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun static BOOL
attach(__GLXAquaContext * context,__GLXAquaDrawable * draw)282*4882a593Smuzhiyun attach(__GLXAquaContext *context, __GLXAquaDrawable *draw)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun     DrawablePtr pDraw;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("attach(%p, %p)\n", context, draw);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun     if (NULL == context || NULL == draw)
289*4882a593Smuzhiyun         return TRUE;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun     pDraw = draw->base.pDraw;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun     if (NULL == pDraw) {
294*4882a593Smuzhiyun         ErrorF("%s:%s() pDraw is NULL!\n", __FILE__, __func__);
295*4882a593Smuzhiyun         return TRUE;
296*4882a593Smuzhiyun     }
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun     if (draw->sid == 0) {
299*4882a593Smuzhiyun         //if (!quartzProcs->CreateSurface(pDraw->pScreen, pDraw->id, pDraw,
300*4882a593Smuzhiyun         if (!DRICreateSurface(pDraw->pScreen, pDraw->id, pDraw,
301*4882a593Smuzhiyun                               0, &draw->sid, NULL,
302*4882a593Smuzhiyun                               surface_notify, draw))
303*4882a593Smuzhiyun             return TRUE;
304*4882a593Smuzhiyun         draw->pDraw = pDraw;
305*4882a593Smuzhiyun     }
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     if (!context->isAttached || context->sid != draw->sid) {
308*4882a593Smuzhiyun         x_list *lst;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun         if (xp_attach_gl_context(context->ctx, draw->sid) != Success) {
311*4882a593Smuzhiyun             //quartzProcs->DestroySurface(pDraw->pScreen, pDraw->id, pDraw,
312*4882a593Smuzhiyun             DRIDestroySurface(pDraw->pScreen, pDraw->id, pDraw,
313*4882a593Smuzhiyun                               surface_notify, draw);
314*4882a593Smuzhiyun             if (surface_hash != NULL)
315*4882a593Smuzhiyun                 x_hash_table_remove(surface_hash,
316*4882a593Smuzhiyun                                     x_cvt_uint_to_vptr(draw->sid));
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun             draw->sid = 0;
319*4882a593Smuzhiyun             return TRUE;
320*4882a593Smuzhiyun         }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun         context->isAttached = TRUE;
323*4882a593Smuzhiyun         context->sid = draw->sid;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun         if (surface_hash == NULL)
326*4882a593Smuzhiyun             surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun         lst =
329*4882a593Smuzhiyun             x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
330*4882a593Smuzhiyun                                     context->sid), NULL);
331*4882a593Smuzhiyun         if (x_list_find(lst, context) == NULL) {
332*4882a593Smuzhiyun             lst = x_list_prepend(lst, context);
333*4882a593Smuzhiyun             x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(
334*4882a593Smuzhiyun                                     context->sid), lst);
335*4882a593Smuzhiyun         }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun         GLAQUA_DEBUG_MSG("attached 0x%x to 0x%x\n", (unsigned int)pDraw->id,
338*4882a593Smuzhiyun                          (unsigned int)draw->sid);
339*4882a593Smuzhiyun     }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     draw->context = context;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     return FALSE;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun #if 0     // unused
347*4882a593Smuzhiyun static void
348*4882a593Smuzhiyun unattach(__GLXAquaContext *context)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun     x_list *lst;
351*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("unattach\n");
352*4882a593Smuzhiyun     if (context == NULL) {
353*4882a593Smuzhiyun         ErrorF("Tried to unattach a null context\n");
354*4882a593Smuzhiyun         return;
355*4882a593Smuzhiyun     }
356*4882a593Smuzhiyun     if (context->isAttached) {
357*4882a593Smuzhiyun         GLAQUA_DEBUG_MSG("unattaching\n");
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun         if (surface_hash != NULL) {
360*4882a593Smuzhiyun             lst = x_hash_table_lookup(surface_hash, (void *)context->sid,
361*4882a593Smuzhiyun                                       NULL);
362*4882a593Smuzhiyun             lst = x_list_remove(lst, context);
363*4882a593Smuzhiyun             x_hash_table_insert(surface_hash, (void *)context->sid, lst);
364*4882a593Smuzhiyun         }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun         CGLClearDrawable(context->ctx);
367*4882a593Smuzhiyun         context->isAttached = FALSE;
368*4882a593Smuzhiyun         context->sid = 0;
369*4882a593Smuzhiyun     }
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun #endif
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun static int
__glXAquaContextMakeCurrent(__GLXcontext * baseContext)374*4882a593Smuzhiyun __glXAquaContextMakeCurrent(__GLXcontext *baseContext)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun     CGLError gl_err;
377*4882a593Smuzhiyun     __GLXAquaContext *context = (__GLXAquaContext *)baseContext;
378*4882a593Smuzhiyun     __GLXAquaDrawable *drawPriv = (__GLXAquaDrawable *)context->base.drawPriv;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glAquaMakeCurrent (ctx 0x%p)\n", baseContext);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun     if (context->base.drawPriv != context->base.readPriv)
383*4882a593Smuzhiyun         return 0;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun     if (attach(context, drawPriv))
386*4882a593Smuzhiyun         return /*error*/ 0;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun     gl_err = CGLSetCurrentContext(context->ctx);
389*4882a593Smuzhiyun     if (gl_err != 0)
390*4882a593Smuzhiyun         ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err));
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun     return gl_err == 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun static int
__glXAquaContextCopy(__GLXcontext * baseDst,__GLXcontext * baseSrc,unsigned long mask)396*4882a593Smuzhiyun __glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
397*4882a593Smuzhiyun                      unsigned long mask)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun     CGLError gl_err;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun     __GLXAquaContext *dst = (__GLXAquaContext *)baseDst;
402*4882a593Smuzhiyun     __GLXAquaContext *src = (__GLXAquaContext *)baseSrc;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("GLXAquaContextCopy\n");
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun     gl_err = CGLCopyContext(src->ctx, dst->ctx, mask);
407*4882a593Smuzhiyun     if (gl_err != 0)
408*4882a593Smuzhiyun         ErrorF("CGLCopyContext error: %s\n", CGLErrorString(gl_err));
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun     return gl_err == 0;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun /* Drawing surface notification callbacks */
414*4882a593Smuzhiyun static GLboolean
__glXAquaDrawableSwapBuffers(ClientPtr client,__GLXdrawable * base)415*4882a593Smuzhiyun __glXAquaDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun     CGLError err;
418*4882a593Smuzhiyun     __GLXAquaDrawable *drawable;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     //    GLAQUA_DEBUG_MSG("glAquaDrawableSwapBuffers(%p)\n",base);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     if (!base) {
423*4882a593Smuzhiyun         ErrorF("%s passed NULL\n", __func__);
424*4882a593Smuzhiyun         return GL_FALSE;
425*4882a593Smuzhiyun     }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun     drawable = (__GLXAquaDrawable *)base;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun     if (NULL == drawable->context) {
430*4882a593Smuzhiyun         ErrorF("%s called with a NULL->context for drawable %p!\n",
431*4882a593Smuzhiyun                __func__, (void *)drawable);
432*4882a593Smuzhiyun         return GL_FALSE;
433*4882a593Smuzhiyun     }
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun     err = CGLFlushDrawable(drawable->context->ctx);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun     if (kCGLNoError != err) {
438*4882a593Smuzhiyun         ErrorF("CGLFlushDrawable error: %s in %s\n", CGLErrorString(err),
439*4882a593Smuzhiyun                __func__);
440*4882a593Smuzhiyun         return GL_FALSE;
441*4882a593Smuzhiyun     }
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun     return GL_TRUE;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun static CGLPixelFormatObj
makeFormat(__GLXconfig * conf)447*4882a593Smuzhiyun makeFormat(__GLXconfig *conf)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun     CGLPixelFormatAttribute attr[64];
450*4882a593Smuzhiyun     CGLPixelFormatObj fobj;
451*4882a593Smuzhiyun     GLint formats;
452*4882a593Smuzhiyun     CGLError error;
453*4882a593Smuzhiyun     int i = 0;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun     if (conf->doubleBufferMode)
456*4882a593Smuzhiyun         attr[i++] = kCGLPFADoubleBuffer;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun     if (conf->stereoMode)
459*4882a593Smuzhiyun         attr[i++] = kCGLPFAStereo;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun     attr[i++] = kCGLPFAColorSize;
462*4882a593Smuzhiyun     attr[i++] = conf->redBits + conf->greenBits + conf->blueBits;
463*4882a593Smuzhiyun     attr[i++] = kCGLPFAAlphaSize;
464*4882a593Smuzhiyun     attr[i++] = conf->alphaBits;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun     if ((conf->accumRedBits + conf->accumGreenBits + conf->accumBlueBits +
467*4882a593Smuzhiyun          conf->accumAlphaBits) > 0) {
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun         attr[i++] = kCGLPFAAccumSize;
470*4882a593Smuzhiyun         attr[i++] = conf->accumRedBits + conf->accumGreenBits
471*4882a593Smuzhiyun                     + conf->accumBlueBits + conf->accumAlphaBits;
472*4882a593Smuzhiyun     }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun     attr[i++] = kCGLPFADepthSize;
475*4882a593Smuzhiyun     attr[i++] = conf->depthBits;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun     if (conf->stencilBits) {
478*4882a593Smuzhiyun         attr[i++] = kCGLPFAStencilSize;
479*4882a593Smuzhiyun         attr[i++] = conf->stencilBits;
480*4882a593Smuzhiyun     }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun     if (conf->numAuxBuffers > 0) {
483*4882a593Smuzhiyun         attr[i++] = kCGLPFAAuxBuffers;
484*4882a593Smuzhiyun         attr[i++] = conf->numAuxBuffers;
485*4882a593Smuzhiyun     }
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun     if (conf->sampleBuffers > 0) {
488*4882a593Smuzhiyun         attr[i++] = kCGLPFASampleBuffers;
489*4882a593Smuzhiyun         attr[i++] = conf->sampleBuffers;
490*4882a593Smuzhiyun         attr[i++] = kCGLPFASamples;
491*4882a593Smuzhiyun         attr[i++] = conf->samples;
492*4882a593Smuzhiyun     }
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun     attr[i] = 0;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun     error = CGLChoosePixelFormat(attr, &fobj, &formats);
497*4882a593Smuzhiyun     if (error) {
498*4882a593Smuzhiyun         ErrorF("error: creating pixel format %s\n", CGLErrorString(error));
499*4882a593Smuzhiyun         return NULL;
500*4882a593Smuzhiyun     }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun     return fobj;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun static void
__glXAquaScreenDestroy(__GLXscreen * screen)506*4882a593Smuzhiyun __glXAquaScreenDestroy(__GLXscreen *screen)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glXAquaScreenDestroy(%p)\n", screen);
510*4882a593Smuzhiyun     __glXScreenDestroy(screen);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun     free(screen);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun /* This is called by __glXInitScreens(). */
516*4882a593Smuzhiyun static __GLXscreen *
__glXAquaScreenProbe(ScreenPtr pScreen)517*4882a593Smuzhiyun __glXAquaScreenProbe(ScreenPtr pScreen)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun     __GLXAquaScreen *screen;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("glXAquaScreenProbe\n");
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun     if (pScreen == NULL)
524*4882a593Smuzhiyun         return NULL;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun     screen = calloc(1, sizeof *screen);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     if (NULL == screen)
529*4882a593Smuzhiyun         return NULL;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun     screen->base.destroy = __glXAquaScreenDestroy;
532*4882a593Smuzhiyun     screen->base.createContext = __glXAquaScreenCreateContext;
533*4882a593Smuzhiyun     screen->base.createDrawable = __glXAquaScreenCreateDrawable;
534*4882a593Smuzhiyun     screen->base.swapInterval = /*FIXME*/ NULL;
535*4882a593Smuzhiyun     screen->base.pScreen = pScreen;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun     screen->base.fbconfigs = __glXAquaCreateVisualConfigs(
538*4882a593Smuzhiyun         &screen->base.numFBConfigs, pScreen->myNum);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun     __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
541*4882a593Smuzhiyun     __glXScreenInit(&screen->base, pScreen);
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun     return &screen->base;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun #if 0 // unused
547*4882a593Smuzhiyun static void
548*4882a593Smuzhiyun __glXAquaDrawableCopySubBuffer(__GLXdrawable *drawable,
549*4882a593Smuzhiyun                                int x, int y, int w, int h)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun     /*TODO finish me*/
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun #endif
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static void
__glXAquaDrawableDestroy(__GLXdrawable * base)556*4882a593Smuzhiyun __glXAquaDrawableDestroy(__GLXdrawable *base)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun     /* gstaplin: base is the head of the structure, so it's at the same
559*4882a593Smuzhiyun      * offset in memory.
560*4882a593Smuzhiyun      * Is this safe with strict aliasing?   I noticed that the other dri code
561*4882a593Smuzhiyun      * does this too...
562*4882a593Smuzhiyun      */
563*4882a593Smuzhiyun     __GLXAquaDrawable *glxPriv = (__GLXAquaDrawable *)base;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun     GLAQUA_DEBUG_MSG("TRACE");
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun     /* It doesn't work to call DRIDestroySurface here, the drawable's
568*4882a593Smuzhiyun        already gone.. But dri.c notices the window destruction and
569*4882a593Smuzhiyun        frees the surface itself. */
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun     /*gstaplin: verify the statement above.  The surface destroy
572*4882a593Smuzhiyun        *messages weren't making it through, and may still not be.
573*4882a593Smuzhiyun        *We need a good test case for surface creation and destruction.
574*4882a593Smuzhiyun        *We also need a good way to enable introspection on the server
575*4882a593Smuzhiyun        *to validate the test, beyond using gdb with print.
576*4882a593Smuzhiyun      */
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun     free(glxPriv);
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun static __GLXdrawable *
__glXAquaScreenCreateDrawable(ClientPtr client,__GLXscreen * screen,DrawablePtr pDraw,XID drawId,int type,XID glxDrawId,__GLXconfig * conf)582*4882a593Smuzhiyun __glXAquaScreenCreateDrawable(ClientPtr client,
583*4882a593Smuzhiyun                               __GLXscreen *screen,
584*4882a593Smuzhiyun                               DrawablePtr pDraw,
585*4882a593Smuzhiyun                               XID drawId,
586*4882a593Smuzhiyun                               int type,
587*4882a593Smuzhiyun                               XID glxDrawId,
588*4882a593Smuzhiyun                               __GLXconfig *conf)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun     __GLXAquaDrawable *glxPriv;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun     glxPriv = malloc(sizeof *glxPriv);
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun     if (glxPriv == NULL)
595*4882a593Smuzhiyun         return NULL;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun     memset(glxPriv, 0, sizeof *glxPriv);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun     if (!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId,
600*4882a593Smuzhiyun                            conf)) {
601*4882a593Smuzhiyun         free(glxPriv);
602*4882a593Smuzhiyun         return NULL;
603*4882a593Smuzhiyun     }
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     glxPriv->base.destroy = __glXAquaDrawableDestroy;
606*4882a593Smuzhiyun     glxPriv->base.swapBuffers = __glXAquaDrawableSwapBuffers;
607*4882a593Smuzhiyun     glxPriv->base.copySubBuffer = NULL; /* __glXAquaDrawableCopySubBuffer; */
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun     glxPriv->pDraw = pDraw;
610*4882a593Smuzhiyun     glxPriv->sid = 0;
611*4882a593Smuzhiyun     glxPriv->context = NULL;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun     return &glxPriv->base;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun // Extra goodies for glx
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun GLuint
__glFloorLog2(GLuint val)619*4882a593Smuzhiyun __glFloorLog2(GLuint val)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun     int c = 0;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun     while (val > 1) {
624*4882a593Smuzhiyun         c++;
625*4882a593Smuzhiyun         val >>= 1;
626*4882a593Smuzhiyun     }
627*4882a593Smuzhiyun     return c;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun #ifndef OPENGL_FRAMEWORK_PATH
631*4882a593Smuzhiyun #define OPENGL_FRAMEWORK_PATH \
632*4882a593Smuzhiyun     "/System/Library/Frameworks/OpenGL.framework/OpenGL"
633*4882a593Smuzhiyun #endif
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun static void *opengl_framework_handle;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun static glx_func_ptr
get_proc_address(const char * sym)638*4882a593Smuzhiyun get_proc_address(const char *sym)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun     return (glx_func_ptr) dlsym(opengl_framework_handle, sym);
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun static void
setup_dispatch_table(void)644*4882a593Smuzhiyun setup_dispatch_table(void)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun     const char *opengl_framework_path;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun     if (opengl_framework_handle) {
649*4882a593Smuzhiyun         return;
650*4882a593Smuzhiyun     }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     opengl_framework_path = getenv("OPENGL_FRAMEWORK_PATH");
653*4882a593Smuzhiyun     if (!opengl_framework_path) {
654*4882a593Smuzhiyun         opengl_framework_path = OPENGL_FRAMEWORK_PATH;
655*4882a593Smuzhiyun     }
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun     (void)dlerror();             /*drain dlerror */
658*4882a593Smuzhiyun     opengl_framework_handle = dlopen(opengl_framework_path, RTLD_LOCAL);
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     if (!opengl_framework_handle) {
661*4882a593Smuzhiyun         ErrorF("unable to dlopen %s : %s, using RTLD_DEFAULT\n",
662*4882a593Smuzhiyun                opengl_framework_path, dlerror());
663*4882a593Smuzhiyun         opengl_framework_handle = RTLD_DEFAULT;
664*4882a593Smuzhiyun     }
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun     __glXsetGetProcAddress(get_proc_address);
667*4882a593Smuzhiyun }
668