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