14642e01fSmrg/*
24642e01fSmrg * GLX implementation that uses Apple's OpenGL.framework
34642e01fSmrg * (Indirect rendering path -- it's also used for some direct mode code too)
44642e01fSmrg *
535c4bbdfSmrg * Copyright (c) 2007-2012 Apple Inc.
64642e01fSmrg * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
74642e01fSmrg * Copyright (c) 2002 Greg Parker. All Rights Reserved.
84642e01fSmrg *
94642e01fSmrg * Portions of this file are copied from Mesa's xf86glx.c,
104642e01fSmrg * which contains the following copyright:
114642e01fSmrg *
124642e01fSmrg * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
134642e01fSmrg * All Rights Reserved.
144642e01fSmrg *
154642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
164642e01fSmrg * copy of this software and associated documentation files (the "Software"),
174642e01fSmrg * to deal in the Software without restriction, including without limitation
184642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
194642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
204642e01fSmrg * Software is furnished to do so, subject to the following conditions:
214642e01fSmrg *
224642e01fSmrg * The above copyright notice and this permission notice shall be included in
234642e01fSmrg * all copies or substantial portions of the Software.
244642e01fSmrg *
254642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
264642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
274642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
284642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
294642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
304642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
314642e01fSmrg * DEALINGS IN THE SOFTWARE.
324642e01fSmrg */
334642e01fSmrg
344642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
354642e01fSmrg#include <dix-config.h>
364642e01fSmrg#endif
374642e01fSmrg
389ace9065Smrg#include <dlfcn.h>
394642e01fSmrg
404642e01fSmrg#include <OpenGL/OpenGL.h>
419ace9065Smrg#include <OpenGL/gl.h>     /* Just to prevent glxserver.h from loading mesa's and colliding with OpenGL.h */
426747b715Smrg
439ace9065Smrg#include <X11/Xproto.h>
444642e01fSmrg#include <GL/glxproto.h>
459ace9065Smrg
464642e01fSmrg#include <glxserver.h>
474642e01fSmrg#include <glxutil.h>
484642e01fSmrg
499ace9065Smrg#include "x-hash.h"
509ace9065Smrg
519ace9065Smrg#include "visualConfigs.h"
529ace9065Smrg#include "dri.h"
5335c4bbdfSmrg#include "extension_string.h"
544642e01fSmrg
5535c4bbdfSmrg#include "darwin.h"
5635c4bbdfSmrg#define GLAQUA_DEBUG_MSG(msg, args ...) ASL_LOG(ASL_LEVEL_DEBUG, "GLXAqua", \
5735c4bbdfSmrg                                                msg, \
5835c4bbdfSmrg                                                ## args)
594642e01fSmrg
6035c4bbdfSmrg__GLXprovider *
6135c4bbdfSmrgGlxGetDRISWrastProvider(void);
629ace9065Smrg
6335c4bbdfSmrgstatic void
6435c4bbdfSmrgsetup_dispatch_table(void);
6535c4bbdfSmrgGLuint
6635c4bbdfSmrg__glFloorLog2(GLuint val);
6735c4bbdfSmrgvoid
6835c4bbdfSmrgwarn_func(void * p1, char *format, ...);
694642e01fSmrg
704642e01fSmrg// some prototypes
7135c4bbdfSmrgstatic __GLXscreen *
7235c4bbdfSmrg__glXAquaScreenProbe(ScreenPtr pScreen);
7335c4bbdfSmrgstatic __GLXdrawable *
7435c4bbdfSmrg__glXAquaScreenCreateDrawable(ClientPtr client, __GLXscreen *screen,
7535c4bbdfSmrg                              DrawablePtr pDraw, XID drawId, int type,
7635c4bbdfSmrg                              XID glxDrawId,
7735c4bbdfSmrg                              __GLXconfig *conf);
7835c4bbdfSmrg
7935c4bbdfSmrgstatic void
8035c4bbdfSmrg__glXAquaContextDestroy(__GLXcontext *baseContext);
8135c4bbdfSmrgstatic int
8235c4bbdfSmrg__glXAquaContextMakeCurrent(__GLXcontext *baseContext);
8335c4bbdfSmrgstatic int
8435c4bbdfSmrg__glXAquaContextLoseCurrent(__GLXcontext *baseContext);
8535c4bbdfSmrgstatic int
8635c4bbdfSmrg__glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
8735c4bbdfSmrg                     unsigned long mask);
8835c4bbdfSmrg
8935c4bbdfSmrgstatic CGLPixelFormatObj
9035c4bbdfSmrgmakeFormat(__GLXconfig *conf);
914642e01fSmrg
924642e01fSmrg__GLXprovider __glXDRISWRastProvider = {
934642e01fSmrg    __glXAquaScreenProbe,
944642e01fSmrg    "Core OpenGL",
954642e01fSmrg    NULL
964642e01fSmrg};
974642e01fSmrg
9835c4bbdfSmrgtypedef struct __GLXAquaScreen __GLXAquaScreen;
9935c4bbdfSmrgtypedef struct __GLXAquaContext __GLXAquaContext;
1004642e01fSmrgtypedef struct __GLXAquaDrawable __GLXAquaDrawable;
1014642e01fSmrg
102475c125cSmrg/*
103475c125cSmrg * The following structs must keep the base as the first member.
104475c125cSmrg * It's used to treat the start of the struct as a different struct
10535c4bbdfSmrg * in GLX.
106475c125cSmrg *
10735c4bbdfSmrg * Note: these structs should be initialized with xcalloc or memset
108475c125cSmrg * prior to usage, and some of them require initializing
109475c125cSmrg * the base with function pointers.
110475c125cSmrg */
1114642e01fSmrgstruct __GLXAquaScreen {
1124642e01fSmrg    __GLXscreen base;
1134642e01fSmrg};
1144642e01fSmrg
1154642e01fSmrgstruct __GLXAquaContext {
1164642e01fSmrg    __GLXcontext base;
1174642e01fSmrg    CGLContextObj ctx;
1184642e01fSmrg    CGLPixelFormatObj pixelFormat;
1194642e01fSmrg    xp_surface_id sid;
12035c4bbdfSmrg    unsigned isAttached : 1;
1214642e01fSmrg};
1224642e01fSmrg
1234642e01fSmrgstruct __GLXAquaDrawable {
1244642e01fSmrg    __GLXdrawable base;
1254642e01fSmrg    DrawablePtr pDraw;
1264642e01fSmrg    xp_surface_id sid;
1274642e01fSmrg    __GLXAquaContext *context;
1284642e01fSmrg};
1294642e01fSmrg
1304642e01fSmrgstatic __GLXcontext *
1314642e01fSmrg__glXAquaScreenCreateContext(__GLXscreen *screen,
13235c4bbdfSmrg                             __GLXconfig *conf,
13335c4bbdfSmrg                             __GLXcontext *baseShareContext,
13435c4bbdfSmrg                             unsigned num_attribs,
13535c4bbdfSmrg                             const uint32_t *attribs,
13635c4bbdfSmrg                             int *error)
1374642e01fSmrg{
1384642e01fSmrg    __GLXAquaContext *context;
13935c4bbdfSmrg    __GLXAquaContext *shareContext = (__GLXAquaContext *)baseShareContext;
1404642e01fSmrg    CGLError gl_err;
14135c4bbdfSmrg
14235c4bbdfSmrg    /* Unused (for now?) */
14335c4bbdfSmrg    (void)num_attribs;
14435c4bbdfSmrg    (void)attribs;
14535c4bbdfSmrg    (void)error;
14635c4bbdfSmrg
1474642e01fSmrg    GLAQUA_DEBUG_MSG("glXAquaScreenCreateContext\n");
14835c4bbdfSmrg
14935c4bbdfSmrg    context = calloc(1, sizeof(__GLXAquaContext));
15035c4bbdfSmrg
1514642e01fSmrg    if (context == NULL)
15235c4bbdfSmrg        return NULL;
1534642e01fSmrg
1544642e01fSmrg    memset(context, 0, sizeof *context);
15535c4bbdfSmrg
1564642e01fSmrg    context->base.pGlxScreen = screen;
1571b5d61b8Smrg    context->base.config = conf;
15835c4bbdfSmrg    context->base.destroy = __glXAquaContextDestroy;
15935c4bbdfSmrg    context->base.makeCurrent = __glXAquaContextMakeCurrent;
16035c4bbdfSmrg    context->base.loseCurrent = __glXAquaContextLoseCurrent;
16135c4bbdfSmrg    context->base.copy = __glXAquaContextCopy;
1624642e01fSmrg    /*FIXME verify that the context->base is fully initialized. */
16335c4bbdfSmrg
1644642e01fSmrg    context->pixelFormat = makeFormat(conf);
16535c4bbdfSmrg
1664642e01fSmrg    if (!context->pixelFormat) {
1676747b715Smrg        free(context);
1684642e01fSmrg        return NULL;
1694642e01fSmrg    }
1704642e01fSmrg
1714642e01fSmrg    context->ctx = NULL;
1724642e01fSmrg    gl_err = CGLCreateContext(context->pixelFormat,
17335c4bbdfSmrg                              shareContext ? shareContext->ctx : NULL,
17435c4bbdfSmrg                              &context->ctx);
17535c4bbdfSmrg
1764642e01fSmrg    if (gl_err != 0) {
17735c4bbdfSmrg        ErrorF("CGLCreateContext error: %s\n", CGLErrorString(gl_err));
17835c4bbdfSmrg        CGLDestroyPixelFormat(context->pixelFormat);
17935c4bbdfSmrg        free(context);
18035c4bbdfSmrg        return NULL;
1814642e01fSmrg    }
18235c4bbdfSmrg
1834642e01fSmrg    setup_dispatch_table();
1844642e01fSmrg    GLAQUA_DEBUG_MSG("glAquaCreateContext done\n");
18535c4bbdfSmrg
1864642e01fSmrg    return &context->base;
1874642e01fSmrg}
1884642e01fSmrg
1894642e01fSmrg/* maps from surface id -> list of __GLcontext */
1904642e01fSmrgstatic x_hash_table *surface_hash;
1914642e01fSmrg
19235c4bbdfSmrgstatic void
19335c4bbdfSmrg__glXAquaContextDestroy(__GLXcontext *baseContext)
19435c4bbdfSmrg{
1954642e01fSmrg    x_list *lst;
1964642e01fSmrg
19735c4bbdfSmrg    __GLXAquaContext *context = (__GLXAquaContext *)baseContext;
19835c4bbdfSmrg
1996747b715Smrg    GLAQUA_DEBUG_MSG("glAquaContextDestroy (ctx %p)\n", baseContext);
2004642e01fSmrg    if (context != NULL) {
20135c4bbdfSmrg        if (context->sid != 0 && surface_hash != NULL) {
20235c4bbdfSmrg            lst =
20335c4bbdfSmrg                x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
20435c4bbdfSmrg                                        context->sid), NULL);
20535c4bbdfSmrg            lst = x_list_remove(lst, context);
20635c4bbdfSmrg            x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(
20735c4bbdfSmrg                                    context->sid), lst);
20835c4bbdfSmrg        }
20935c4bbdfSmrg
21035c4bbdfSmrg        if (context->ctx != NULL)
21135c4bbdfSmrg            CGLDestroyContext(context->ctx);
21235c4bbdfSmrg
21335c4bbdfSmrg        if (context->pixelFormat != NULL)
21435c4bbdfSmrg            CGLDestroyPixelFormat(context->pixelFormat);
21535c4bbdfSmrg
21635c4bbdfSmrg        free(context);
2174642e01fSmrg    }
2184642e01fSmrg}
2194642e01fSmrg
22035c4bbdfSmrgstatic int
22135c4bbdfSmrg__glXAquaContextLoseCurrent(__GLXcontext *baseContext)
22235c4bbdfSmrg{
2234642e01fSmrg    CGLError gl_err;
2244642e01fSmrg
2254642e01fSmrg    GLAQUA_DEBUG_MSG("glAquaLoseCurrent (ctx 0x%p)\n", baseContext);
2264642e01fSmrg
2274642e01fSmrg    gl_err = CGLSetCurrentContext(NULL);
2284642e01fSmrg    if (gl_err != 0)
22935c4bbdfSmrg        ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err));
2304642e01fSmrg
23135c4bbdfSmrg    /*
232475c125cSmrg     * There should be no need to set __glXLastContext to NULL here, because
23335c4bbdfSmrg     * glxcmds.c does it as part of the context cache flush after calling
234475c125cSmrg     * this.
235475c125cSmrg     */
2364642e01fSmrg
2374642e01fSmrg    return GL_TRUE;
2384642e01fSmrg}
2394642e01fSmrg
2404642e01fSmrg/* Called when a surface is destroyed as a side effect of destroying
2414642e01fSmrg   the window it's attached to. */
24235c4bbdfSmrgstatic void
24335c4bbdfSmrgsurface_notify(void *_arg, void *data)
24435c4bbdfSmrg{
2454642e01fSmrg    DRISurfaceNotifyArg *arg = (DRISurfaceNotifyArg *)_arg;
2464642e01fSmrg    __GLXAquaDrawable *draw = (__GLXAquaDrawable *)data;
2474642e01fSmrg    __GLXAquaContext *context;
2484642e01fSmrg    x_list *lst;
24935c4bbdfSmrg    if (_arg == NULL || data == NULL) {
25035c4bbdfSmrg        ErrorF("surface_notify called with bad params");
25135c4bbdfSmrg        return;
2524642e01fSmrg    }
25335c4bbdfSmrg
2544642e01fSmrg    GLAQUA_DEBUG_MSG("surface_notify(%p, %p)\n", _arg, data);
2554642e01fSmrg    switch (arg->kind) {
2564642e01fSmrg    case AppleDRISurfaceNotifyDestroyed:
2574642e01fSmrg        if (surface_hash != NULL)
2584642e01fSmrg            x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(arg->id));
25935c4bbdfSmrg        draw->pDraw = NULL;
26035c4bbdfSmrg        draw->sid = 0;
2614642e01fSmrg        break;
2624642e01fSmrg
2634642e01fSmrg    case AppleDRISurfaceNotifyChanged:
2644642e01fSmrg        if (surface_hash != NULL) {
26535c4bbdfSmrg            lst =
26635c4bbdfSmrg                x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
26735c4bbdfSmrg                                        arg->id), NULL);
26835c4bbdfSmrg            for (; lst != NULL; lst = lst->next) {
2694642e01fSmrg                context = lst->data;
2704642e01fSmrg                xp_update_gl_context(context->ctx);
2714642e01fSmrg            }
2724642e01fSmrg        }
2734642e01fSmrg        break;
27435c4bbdfSmrg
2754642e01fSmrg    default:
27635c4bbdfSmrg        ErrorF("surface_notify: unknown kind %d\n", arg->kind);
27735c4bbdfSmrg        break;
2784642e01fSmrg    }
2794642e01fSmrg}
2804642e01fSmrg
28135c4bbdfSmrgstatic BOOL
28235c4bbdfSmrgattach(__GLXAquaContext *context, __GLXAquaDrawable *draw)
28335c4bbdfSmrg{
2844642e01fSmrg    DrawablePtr pDraw;
28535c4bbdfSmrg
2864642e01fSmrg    GLAQUA_DEBUG_MSG("attach(%p, %p)\n", context, draw);
28735c4bbdfSmrg
28835c4bbdfSmrg    if (NULL == context || NULL == draw)
28935c4bbdfSmrg        return TRUE;
2904642e01fSmrg
2914642e01fSmrg    pDraw = draw->base.pDraw;
2924642e01fSmrg
29335c4bbdfSmrg    if (NULL == pDraw) {
29435c4bbdfSmrg        ErrorF("%s:%s() pDraw is NULL!\n", __FILE__, __func__);
29535c4bbdfSmrg        return TRUE;
2964642e01fSmrg    }
2974642e01fSmrg
2984642e01fSmrg    if (draw->sid == 0) {
29935c4bbdfSmrg        //if (!quartzProcs->CreateSurface(pDraw->pScreen, pDraw->id, pDraw,
3004642e01fSmrg        if (!DRICreateSurface(pDraw->pScreen, pDraw->id, pDraw,
30135c4bbdfSmrg                              0, &draw->sid, NULL,
30235c4bbdfSmrg                              surface_notify, draw))
3034642e01fSmrg            return TRUE;
3044642e01fSmrg        draw->pDraw = pDraw;
30535c4bbdfSmrg    }
30635c4bbdfSmrg
3074642e01fSmrg    if (!context->isAttached || context->sid != draw->sid) {
3084642e01fSmrg        x_list *lst;
30935c4bbdfSmrg
3104642e01fSmrg        if (xp_attach_gl_context(context->ctx, draw->sid) != Success) {
31135c4bbdfSmrg            //quartzProcs->DestroySurface(pDraw->pScreen, pDraw->id, pDraw,
3124642e01fSmrg            DRIDestroySurface(pDraw->pScreen, pDraw->id, pDraw,
31335c4bbdfSmrg                              surface_notify, draw);
3144642e01fSmrg            if (surface_hash != NULL)
31535c4bbdfSmrg                x_hash_table_remove(surface_hash,
31635c4bbdfSmrg                                    x_cvt_uint_to_vptr(draw->sid));
31735c4bbdfSmrg
3184642e01fSmrg            draw->sid = 0;
3194642e01fSmrg            return TRUE;
3204642e01fSmrg        }
32135c4bbdfSmrg
3224642e01fSmrg        context->isAttached = TRUE;
3234642e01fSmrg        context->sid = draw->sid;
32435c4bbdfSmrg
3254642e01fSmrg        if (surface_hash == NULL)
3264642e01fSmrg            surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
32735c4bbdfSmrg
32835c4bbdfSmrg        lst =
32935c4bbdfSmrg            x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(
33035c4bbdfSmrg                                    context->sid), NULL);
3314642e01fSmrg        if (x_list_find(lst, context) == NULL) {
3324642e01fSmrg            lst = x_list_prepend(lst, context);
33335c4bbdfSmrg            x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(
33435c4bbdfSmrg                                    context->sid), lst);
3354642e01fSmrg        }
3364642e01fSmrg
33735c4bbdfSmrg        GLAQUA_DEBUG_MSG("attached 0x%x to 0x%x\n", (unsigned int)pDraw->id,
33835c4bbdfSmrg                         (unsigned int)draw->sid);
33935c4bbdfSmrg    }
3404642e01fSmrg
3414642e01fSmrg    draw->context = context;
3424642e01fSmrg
3434642e01fSmrg    return FALSE;
3444642e01fSmrg}
3454642e01fSmrg
3464642e01fSmrg#if 0     // unused
34735c4bbdfSmrgstatic void
34835c4bbdfSmrgunattach(__GLXAquaContext *context)
34935c4bbdfSmrg{
35035c4bbdfSmrg    x_list *lst;
35135c4bbdfSmrg    GLAQUA_DEBUG_MSG("unattach\n");
35235c4bbdfSmrg    if (context == NULL) {
35335c4bbdfSmrg        ErrorF("Tried to unattach a null context\n");
35435c4bbdfSmrg        return;
35535c4bbdfSmrg    }
3564642e01fSmrg    if (context->isAttached) {
3574642e01fSmrg        GLAQUA_DEBUG_MSG("unattaching\n");
3584642e01fSmrg
3594642e01fSmrg        if (surface_hash != NULL) {
36035c4bbdfSmrg            lst = x_hash_table_lookup(surface_hash, (void *)context->sid,
36135c4bbdfSmrg                                      NULL);
3624642e01fSmrg            lst = x_list_remove(lst, context);
36335c4bbdfSmrg            x_hash_table_insert(surface_hash, (void *)context->sid, lst);
3644642e01fSmrg        }
3654642e01fSmrg
3664642e01fSmrg        CGLClearDrawable(context->ctx);
3674642e01fSmrg        context->isAttached = FALSE;
3684642e01fSmrg        context->sid = 0;
3694642e01fSmrg    }
3704642e01fSmrg}
3714642e01fSmrg#endif
3724642e01fSmrg
37335c4bbdfSmrgstatic int
37435c4bbdfSmrg__glXAquaContextMakeCurrent(__GLXcontext *baseContext)
37535c4bbdfSmrg{
3764642e01fSmrg    CGLError gl_err;
37735c4bbdfSmrg    __GLXAquaContext *context = (__GLXAquaContext *)baseContext;
37835c4bbdfSmrg    __GLXAquaDrawable *drawPriv = (__GLXAquaDrawable *)context->base.drawPriv;
37935c4bbdfSmrg
3804642e01fSmrg    GLAQUA_DEBUG_MSG("glAquaMakeCurrent (ctx 0x%p)\n", baseContext);
38135c4bbdfSmrg
3821b5d61b8Smrg    if (context->base.drawPriv != context->base.readPriv)
3831b5d61b8Smrg        return 0;
3841b5d61b8Smrg
38535c4bbdfSmrg    if (attach(context, drawPriv))
38635c4bbdfSmrg        return /*error*/ 0;
3874642e01fSmrg
3884642e01fSmrg    gl_err = CGLSetCurrentContext(context->ctx);
3894642e01fSmrg    if (gl_err != 0)
3904642e01fSmrg        ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err));
39135c4bbdfSmrg
3924642e01fSmrg    return gl_err == 0;
3934642e01fSmrg}
3944642e01fSmrg
39535c4bbdfSmrgstatic int
39635c4bbdfSmrg__glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
39735c4bbdfSmrg                     unsigned long mask)
3984642e01fSmrg{
3994642e01fSmrg    CGLError gl_err;
4004642e01fSmrg
40135c4bbdfSmrg    __GLXAquaContext *dst = (__GLXAquaContext *)baseDst;
40235c4bbdfSmrg    __GLXAquaContext *src = (__GLXAquaContext *)baseSrc;
4034642e01fSmrg
4044642e01fSmrg    GLAQUA_DEBUG_MSG("GLXAquaContextCopy\n");
4054642e01fSmrg
4064642e01fSmrg    gl_err = CGLCopyContext(src->ctx, dst->ctx, mask);
4074642e01fSmrg    if (gl_err != 0)
4084642e01fSmrg        ErrorF("CGLCopyContext error: %s\n", CGLErrorString(gl_err));
4094642e01fSmrg
4104642e01fSmrg    return gl_err == 0;
4114642e01fSmrg}
4124642e01fSmrg
4134642e01fSmrg/* Drawing surface notification callbacks */
41435c4bbdfSmrgstatic GLboolean
41535c4bbdfSmrg__glXAquaDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base)
41635c4bbdfSmrg{
4174642e01fSmrg    CGLError err;
4184642e01fSmrg    __GLXAquaDrawable *drawable;
41935c4bbdfSmrg
4204642e01fSmrg    //    GLAQUA_DEBUG_MSG("glAquaDrawableSwapBuffers(%p)\n",base);
42135c4bbdfSmrg
42235c4bbdfSmrg    if (!base) {
42335c4bbdfSmrg        ErrorF("%s passed NULL\n", __func__);
42435c4bbdfSmrg        return GL_FALSE;
4254642e01fSmrg    }
4264642e01fSmrg
4274642e01fSmrg    drawable = (__GLXAquaDrawable *)base;
4284642e01fSmrg
42935c4bbdfSmrg    if (NULL == drawable->context) {
43035c4bbdfSmrg        ErrorF("%s called with a NULL->context for drawable %p!\n",
43135c4bbdfSmrg               __func__, (void *)drawable);
43235c4bbdfSmrg        return GL_FALSE;
4334642e01fSmrg    }
4344642e01fSmrg
4354642e01fSmrg    err = CGLFlushDrawable(drawable->context->ctx);
4364642e01fSmrg
43735c4bbdfSmrg    if (kCGLNoError != err) {
43835c4bbdfSmrg        ErrorF("CGLFlushDrawable error: %s in %s\n", CGLErrorString(err),
43935c4bbdfSmrg               __func__);
44035c4bbdfSmrg        return GL_FALSE;
4414642e01fSmrg    }
4424642e01fSmrg
4434642e01fSmrg    return GL_TRUE;
4444642e01fSmrg}
4454642e01fSmrg
44635c4bbdfSmrgstatic CGLPixelFormatObj
44735c4bbdfSmrgmakeFormat(__GLXconfig *conf)
44835c4bbdfSmrg{
4494642e01fSmrg    CGLPixelFormatAttribute attr[64];
4504642e01fSmrg    CGLPixelFormatObj fobj;
4514642e01fSmrg    GLint formats;
4524642e01fSmrg    CGLError error;
4534642e01fSmrg    int i = 0;
4544642e01fSmrg
45535c4bbdfSmrg    if (conf->doubleBufferMode)
45635c4bbdfSmrg        attr[i++] = kCGLPFADoubleBuffer;
45735c4bbdfSmrg
45835c4bbdfSmrg    if (conf->stereoMode)
45935c4bbdfSmrg        attr[i++] = kCGLPFAStereo;
4604642e01fSmrg
4614642e01fSmrg    attr[i++] = kCGLPFAColorSize;
4624642e01fSmrg    attr[i++] = conf->redBits + conf->greenBits + conf->blueBits;
4634642e01fSmrg    attr[i++] = kCGLPFAAlphaSize;
4644642e01fSmrg    attr[i++] = conf->alphaBits;
4654642e01fSmrg
46635c4bbdfSmrg    if ((conf->accumRedBits + conf->accumGreenBits + conf->accumBlueBits +
46735c4bbdfSmrg         conf->accumAlphaBits) > 0) {
4684642e01fSmrg
46935c4bbdfSmrg        attr[i++] = kCGLPFAAccumSize;
4704642e01fSmrg        attr[i++] = conf->accumRedBits + conf->accumGreenBits
47135c4bbdfSmrg                    + conf->accumBlueBits + conf->accumAlphaBits;
4724642e01fSmrg    }
47335c4bbdfSmrg
4744642e01fSmrg    attr[i++] = kCGLPFADepthSize;
4754642e01fSmrg    attr[i++] = conf->depthBits;
4764642e01fSmrg
47735c4bbdfSmrg    if (conf->stencilBits) {
47835c4bbdfSmrg        attr[i++] = kCGLPFAStencilSize;
47935c4bbdfSmrg        attr[i++] = conf->stencilBits;
4804642e01fSmrg    }
48135c4bbdfSmrg
48235c4bbdfSmrg    if (conf->numAuxBuffers > 0) {
48335c4bbdfSmrg        attr[i++] = kCGLPFAAuxBuffers;
48435c4bbdfSmrg        attr[i++] = conf->numAuxBuffers;
4854642e01fSmrg    }
4864642e01fSmrg
48735c4bbdfSmrg    if (conf->sampleBuffers > 0) {
48835c4bbdfSmrg        attr[i++] = kCGLPFASampleBuffers;
48935c4bbdfSmrg        attr[i++] = conf->sampleBuffers;
49035c4bbdfSmrg        attr[i++] = kCGLPFASamples;
49135c4bbdfSmrg        attr[i++] = conf->samples;
4924642e01fSmrg    }
49335c4bbdfSmrg
4946747b715Smrg    attr[i] = 0;
4954642e01fSmrg
4964642e01fSmrg    error = CGLChoosePixelFormat(attr, &fobj, &formats);
49735c4bbdfSmrg    if (error) {
49835c4bbdfSmrg        ErrorF("error: creating pixel format %s\n", CGLErrorString(error));
49935c4bbdfSmrg        return NULL;
5004642e01fSmrg    }
5014642e01fSmrg
5024642e01fSmrg    return fobj;
5034642e01fSmrg}
5044642e01fSmrg
50535c4bbdfSmrgstatic void
50635c4bbdfSmrg__glXAquaScreenDestroy(__GLXscreen *screen)
50735c4bbdfSmrg{
5084642e01fSmrg
5094642e01fSmrg    GLAQUA_DEBUG_MSG("glXAquaScreenDestroy(%p)\n", screen);
5104642e01fSmrg    __glXScreenDestroy(screen);
5114642e01fSmrg
5126747b715Smrg    free(screen);
5134642e01fSmrg}
5144642e01fSmrg
5154642e01fSmrg/* This is called by __glXInitScreens(). */
51635c4bbdfSmrgstatic __GLXscreen *
51735c4bbdfSmrg__glXAquaScreenProbe(ScreenPtr pScreen)
51835c4bbdfSmrg{
5194642e01fSmrg    __GLXAquaScreen *screen;
5204642e01fSmrg
5214642e01fSmrg    GLAQUA_DEBUG_MSG("glXAquaScreenProbe\n");
5224642e01fSmrg
52335c4bbdfSmrg    if (pScreen == NULL)
52435c4bbdfSmrg        return NULL;
5254642e01fSmrg
5266747b715Smrg    screen = calloc(1, sizeof *screen);
5276747b715Smrg
52835c4bbdfSmrg    if (NULL == screen)
52935c4bbdfSmrg        return NULL;
53035c4bbdfSmrg
53135c4bbdfSmrg    screen->base.destroy = __glXAquaScreenDestroy;
53235c4bbdfSmrg    screen->base.createContext = __glXAquaScreenCreateContext;
5334642e01fSmrg    screen->base.createDrawable = __glXAquaScreenCreateDrawable;
5344642e01fSmrg    screen->base.swapInterval = /*FIXME*/ NULL;
53535c4bbdfSmrg    screen->base.pScreen = pScreen;
53635c4bbdfSmrg
53735c4bbdfSmrg    screen->base.fbconfigs = __glXAquaCreateVisualConfigs(
53835c4bbdfSmrg        &screen->base.numFBConfigs, pScreen->myNum);
5396747b715Smrg
5401b5d61b8Smrg    __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
5414642e01fSmrg    __glXScreenInit(&screen->base, pScreen);
5424642e01fSmrg
5434642e01fSmrg    return &screen->base;
5444642e01fSmrg}
5454642e01fSmrg
5466747b715Smrg#if 0 // unused
54735c4bbdfSmrgstatic void
54835c4bbdfSmrg__glXAquaDrawableCopySubBuffer(__GLXdrawable *drawable,
54935c4bbdfSmrg                               int x, int y, int w, int h)
55035c4bbdfSmrg{
5514642e01fSmrg    /*TODO finish me*/
5524642e01fSmrg}
5536747b715Smrg#endif
5544642e01fSmrg
55535c4bbdfSmrgstatic void
55635c4bbdfSmrg__glXAquaDrawableDestroy(__GLXdrawable *base)
55735c4bbdfSmrg{
55835c4bbdfSmrg    /* gstaplin: base is the head of the structure, so it's at the same
5594642e01fSmrg     * offset in memory.
5604642e01fSmrg     * Is this safe with strict aliasing?   I noticed that the other dri code
5614642e01fSmrg     * does this too...
5624642e01fSmrg     */
5634642e01fSmrg    __GLXAquaDrawable *glxPriv = (__GLXAquaDrawable *)base;
5644642e01fSmrg
56535c4bbdfSmrg    GLAQUA_DEBUG_MSG("TRACE");
56635c4bbdfSmrg
5674642e01fSmrg    /* It doesn't work to call DRIDestroySurface here, the drawable's
5684642e01fSmrg       already gone.. But dri.c notices the window destruction and
5694642e01fSmrg       frees the surface itself. */
5704642e01fSmrg
5714642e01fSmrg    /*gstaplin: verify the statement above.  The surface destroy
57235c4bbdfSmrg       *messages weren't making it through, and may still not be.
57335c4bbdfSmrg       *We need a good test case for surface creation and destruction.
57435c4bbdfSmrg       *We also need a good way to enable introspection on the server
57535c4bbdfSmrg       *to validate the test, beyond using gdb with print.
5764642e01fSmrg     */
5774642e01fSmrg
5786747b715Smrg    free(glxPriv);
5794642e01fSmrg}
5804642e01fSmrg
5814642e01fSmrgstatic __GLXdrawable *
5826747b715Smrg__glXAquaScreenCreateDrawable(ClientPtr client,
5836747b715Smrg                              __GLXscreen *screen,
58435c4bbdfSmrg                              DrawablePtr pDraw,
58535c4bbdfSmrg                              XID drawId,
58635c4bbdfSmrg                              int type,
58735c4bbdfSmrg                              XID glxDrawId,
58835c4bbdfSmrg                              __GLXconfig *conf)
58935c4bbdfSmrg{
59035c4bbdfSmrg    __GLXAquaDrawable *glxPriv;
5914642e01fSmrg
59235c4bbdfSmrg    glxPriv = malloc(sizeof *glxPriv);
5934642e01fSmrg
59435c4bbdfSmrg    if (glxPriv == NULL)
59535c4bbdfSmrg        return NULL;
5964642e01fSmrg
59735c4bbdfSmrg    memset(glxPriv, 0, sizeof *glxPriv);
5984642e01fSmrg
59935c4bbdfSmrg    if (!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId,
60035c4bbdfSmrg                           conf)) {
60135c4bbdfSmrg        free(glxPriv);
60235c4bbdfSmrg        return NULL;
60335c4bbdfSmrg    }
60435c4bbdfSmrg
60535c4bbdfSmrg    glxPriv->base.destroy = __glXAquaDrawableDestroy;
60635c4bbdfSmrg    glxPriv->base.swapBuffers = __glXAquaDrawableSwapBuffers;
60735c4bbdfSmrg    glxPriv->base.copySubBuffer = NULL; /* __glXAquaDrawableCopySubBuffer; */
60835c4bbdfSmrg
60935c4bbdfSmrg    glxPriv->pDraw = pDraw;
61035c4bbdfSmrg    glxPriv->sid = 0;
61135c4bbdfSmrg    glxPriv->context = NULL;
61235c4bbdfSmrg
61335c4bbdfSmrg    return &glxPriv->base;
6144642e01fSmrg}
6154642e01fSmrg
6164642e01fSmrg// Extra goodies for glx
6174642e01fSmrg
61835c4bbdfSmrgGLuint
61935c4bbdfSmrg__glFloorLog2(GLuint val)
6204642e01fSmrg{
6214642e01fSmrg    int c = 0;
6224642e01fSmrg
6234642e01fSmrg    while (val > 1) {
6244642e01fSmrg        c++;
6254642e01fSmrg        val >>= 1;
6264642e01fSmrg    }
6274642e01fSmrg    return c;
6284642e01fSmrg}
6294642e01fSmrg
6309ace9065Smrg#ifndef OPENGL_FRAMEWORK_PATH
63135c4bbdfSmrg#define OPENGL_FRAMEWORK_PATH \
63235c4bbdfSmrg    "/System/Library/Frameworks/OpenGL.framework/OpenGL"
6336747b715Smrg#endif
6346747b715Smrg
63535c4bbdfSmrgstatic void *opengl_framework_handle;
63635c4bbdfSmrg
63735c4bbdfSmrgstatic glx_func_ptr
63835c4bbdfSmrgget_proc_address(const char *sym)
63935c4bbdfSmrg{
64035c4bbdfSmrg    return (glx_func_ptr) dlsym(opengl_framework_handle, sym);
64135c4bbdfSmrg}
64235c4bbdfSmrg
64335c4bbdfSmrgstatic void
64435c4bbdfSmrgsetup_dispatch_table(void)
64535c4bbdfSmrg{
6469ace9065Smrg    const char *opengl_framework_path;
6476747b715Smrg
64835c4bbdfSmrg    if (opengl_framework_handle) {
6499ace9065Smrg        return;
6509ace9065Smrg    }
6516747b715Smrg
6529ace9065Smrg    opengl_framework_path = getenv("OPENGL_FRAMEWORK_PATH");
6539ace9065Smrg    if (!opengl_framework_path) {
6549ace9065Smrg        opengl_framework_path = OPENGL_FRAMEWORK_PATH;
6559ace9065Smrg    }
6566747b715Smrg
65735c4bbdfSmrg    (void)dlerror();             /*drain dlerror */
65835c4bbdfSmrg    opengl_framework_handle = dlopen(opengl_framework_path, RTLD_LOCAL);
6596747b715Smrg
66035c4bbdfSmrg    if (!opengl_framework_handle) {
6619ace9065Smrg        ErrorF("unable to dlopen %s : %s, using RTLD_DEFAULT\n",
66235c4bbdfSmrg               opengl_framework_path, dlerror());
66335c4bbdfSmrg        opengl_framework_handle = RTLD_DEFAULT;
6649ace9065Smrg    }
6656747b715Smrg
66635c4bbdfSmrg    __glXsetGetProcAddress(get_proc_address);
6674642e01fSmrg}
668