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