1706f2543Smrg/* 2706f2543Smrg * GLX implementation that uses Apple's OpenGL.framework 3706f2543Smrg * (Indirect rendering path -- it's also used for some direct mode code too) 4706f2543Smrg * 5706f2543Smrg * Copyright (c) 2007-2011 Apple Inc. 6706f2543Smrg * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. 7706f2543Smrg * Copyright (c) 2002 Greg Parker. All Rights Reserved. 8706f2543Smrg * 9706f2543Smrg * Portions of this file are copied from Mesa's xf86glx.c, 10706f2543Smrg * which contains the following copyright: 11706f2543Smrg * 12706f2543Smrg * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 13706f2543Smrg * All Rights Reserved. 14706f2543Smrg * 15706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 16706f2543Smrg * copy of this software and associated documentation files (the "Software"), 17706f2543Smrg * to deal in the Software without restriction, including without limitation 18706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 19706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 20706f2543Smrg * Software is furnished to do so, subject to the following conditions: 21706f2543Smrg * 22706f2543Smrg * The above copyright notice and this permission notice shall be included in 23706f2543Smrg * all copies or substantial portions of the Software. 24706f2543Smrg * 25706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 29706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31706f2543Smrg * DEALINGS IN THE SOFTWARE. 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 35706f2543Smrg#include <dix-config.h> 36706f2543Smrg#endif 37706f2543Smrg 38706f2543Smrg#include <AvailabilityMacros.h> 39706f2543Smrg 40706f2543Smrg#include <dlfcn.h> 41706f2543Smrg 42706f2543Smrg#include <OpenGL/OpenGL.h> 43706f2543Smrg#include <OpenGL/gl.h> /* Just to prevent glxserver.h from loading mesa's and colliding with OpenGL.h */ 44706f2543Smrg 45706f2543Smrg#include <X11/Xproto.h> 46706f2543Smrg#include <GL/glxproto.h> 47706f2543Smrg 48706f2543Smrg#include <glxserver.h> 49706f2543Smrg#include <glxutil.h> 50706f2543Smrg 51706f2543Smrgtypedef unsigned long long GLuint64EXT; 52706f2543Smrgtypedef long long GLint64EXT; 53706f2543Smrg#include <dispatch.h> 54706f2543Smrg#include <glapi.h> 55706f2543Smrg 56706f2543Smrg#include "x-hash.h" 57706f2543Smrg 58706f2543Smrg#include "visualConfigs.h" 59706f2543Smrg#include "dri.h" 60706f2543Smrg 61706f2543Smrg// Write debugging output, or not 62706f2543Smrg#ifdef GLAQUA_DEBUG 63706f2543Smrg#define GLAQUA_DEBUG_MSG ErrorF 64706f2543Smrg#else 65706f2543Smrg#define GLAQUA_DEBUG_MSG(a, ...) 66706f2543Smrg#endif 67706f2543Smrg 68706f2543Smrg__GLXprovider * GlxGetDRISWrastProvider (void); 69706f2543Smrg 70706f2543Smrgstatic void setup_dispatch_table(void); 71706f2543SmrgGLuint __glFloorLog2(GLuint val); 72706f2543Smrgvoid warn_func(void * p1, char *format, ...); 73706f2543Smrg 74706f2543Smrg// some prototypes 75706f2543Smrgstatic __GLXscreen * __glXAquaScreenProbe(ScreenPtr pScreen); 76706f2543Smrgstatic __GLXdrawable * __glXAquaScreenCreateDrawable(ClientPtr client, __GLXscreen *screen, DrawablePtr pDraw, XID drawId, int type, XID glxDrawId, __GLXconfig *conf); 77706f2543Smrg 78706f2543Smrgstatic void __glXAquaContextDestroy(__GLXcontext *baseContext); 79706f2543Smrgstatic int __glXAquaContextMakeCurrent(__GLXcontext *baseContext); 80706f2543Smrgstatic int __glXAquaContextLoseCurrent(__GLXcontext *baseContext); 81706f2543Smrgstatic int __glXAquaContextForceCurrent(__GLXcontext *baseContext); 82706f2543Smrgstatic int __glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc, unsigned long mask); 83706f2543Smrg 84706f2543Smrgstatic CGLPixelFormatObj makeFormat(__GLXconfig *conf); 85706f2543Smrg 86706f2543Smrg__GLXprovider __glXDRISWRastProvider = { 87706f2543Smrg __glXAquaScreenProbe, 88706f2543Smrg "Core OpenGL", 89706f2543Smrg NULL 90706f2543Smrg}; 91706f2543Smrg 92706f2543Smrgtypedef struct __GLXAquaScreen __GLXAquaScreen; 93706f2543Smrgtypedef struct __GLXAquaContext __GLXAquaContext; 94706f2543Smrgtypedef struct __GLXAquaDrawable __GLXAquaDrawable; 95706f2543Smrg 96706f2543Smrg/* 97706f2543Smrg * The following structs must keep the base as the first member. 98706f2543Smrg * It's used to treat the start of the struct as a different struct 99706f2543Smrg * in GLX. 100706f2543Smrg * 101706f2543Smrg * Note: these structs should be initialized with xcalloc or memset 102706f2543Smrg * prior to usage, and some of them require initializing 103706f2543Smrg * the base with function pointers. 104706f2543Smrg */ 105706f2543Smrgstruct __GLXAquaScreen { 106706f2543Smrg __GLXscreen base; 107706f2543Smrg int index; 108706f2543Smrg int num_vis; 109706f2543Smrg}; 110706f2543Smrg 111706f2543Smrgstruct __GLXAquaContext { 112706f2543Smrg __GLXcontext base; 113706f2543Smrg CGLContextObj ctx; 114706f2543Smrg CGLPixelFormatObj pixelFormat; 115706f2543Smrg xp_surface_id sid; 116706f2543Smrg unsigned isAttached :1; 117706f2543Smrg}; 118706f2543Smrg 119706f2543Smrgstruct __GLXAquaDrawable { 120706f2543Smrg __GLXdrawable base; 121706f2543Smrg DrawablePtr pDraw; 122706f2543Smrg xp_surface_id sid; 123706f2543Smrg __GLXAquaContext *context; 124706f2543Smrg}; 125706f2543Smrg 126706f2543Smrg 127706f2543Smrgstatic __GLXcontext * 128706f2543Smrg__glXAquaScreenCreateContext(__GLXscreen *screen, 129706f2543Smrg __GLXconfig *conf, 130706f2543Smrg __GLXcontext *baseShareContext) 131706f2543Smrg{ 132706f2543Smrg __GLXAquaContext *context; 133706f2543Smrg __GLXAquaContext *shareContext = (__GLXAquaContext *) baseShareContext; 134706f2543Smrg CGLError gl_err; 135706f2543Smrg 136706f2543Smrg GLAQUA_DEBUG_MSG("glXAquaScreenCreateContext\n"); 137706f2543Smrg 138706f2543Smrg context = calloc(1, sizeof (__GLXAquaContext)); 139706f2543Smrg 140706f2543Smrg if (context == NULL) 141706f2543Smrg return NULL; 142706f2543Smrg 143706f2543Smrg memset(context, 0, sizeof *context); 144706f2543Smrg 145706f2543Smrg context->base.pGlxScreen = screen; 146706f2543Smrg 147706f2543Smrg context->base.destroy = __glXAquaContextDestroy; 148706f2543Smrg context->base.makeCurrent = __glXAquaContextMakeCurrent; 149706f2543Smrg context->base.loseCurrent = __glXAquaContextLoseCurrent; 150706f2543Smrg context->base.copy = __glXAquaContextCopy; 151706f2543Smrg context->base.forceCurrent = __glXAquaContextForceCurrent; 152706f2543Smrg /*FIXME verify that the context->base is fully initialized. */ 153706f2543Smrg 154706f2543Smrg context->pixelFormat = makeFormat(conf); 155706f2543Smrg 156706f2543Smrg if (!context->pixelFormat) { 157706f2543Smrg free(context); 158706f2543Smrg return NULL; 159706f2543Smrg } 160706f2543Smrg 161706f2543Smrg context->ctx = NULL; 162706f2543Smrg gl_err = CGLCreateContext(context->pixelFormat, 163706f2543Smrg shareContext ? shareContext->ctx : NULL, 164706f2543Smrg &context->ctx); 165706f2543Smrg 166706f2543Smrg if (gl_err != 0) { 167706f2543Smrg ErrorF("CGLCreateContext error: %s\n", CGLErrorString(gl_err)); 168706f2543Smrg CGLDestroyPixelFormat(context->pixelFormat); 169706f2543Smrg free(context); 170706f2543Smrg return NULL; 171706f2543Smrg } 172706f2543Smrg 173706f2543Smrg setup_dispatch_table(); 174706f2543Smrg GLAQUA_DEBUG_MSG("glAquaCreateContext done\n"); 175706f2543Smrg 176706f2543Smrg return &context->base; 177706f2543Smrg} 178706f2543Smrg 179706f2543Smrg/* maps from surface id -> list of __GLcontext */ 180706f2543Smrgstatic x_hash_table *surface_hash; 181706f2543Smrg 182706f2543Smrgstatic void __glXAquaContextDestroy(__GLXcontext *baseContext) { 183706f2543Smrg x_list *lst; 184706f2543Smrg 185706f2543Smrg __GLXAquaContext *context = (__GLXAquaContext *) baseContext; 186706f2543Smrg 187706f2543Smrg GLAQUA_DEBUG_MSG("glAquaContextDestroy (ctx %p)\n", baseContext); 188706f2543Smrg if (context != NULL) { 189706f2543Smrg if (context->sid != 0 && surface_hash != NULL) { 190706f2543Smrg lst = x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(context->sid), NULL); 191706f2543Smrg lst = x_list_remove(lst, context); 192706f2543Smrg x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(context->sid), lst); 193706f2543Smrg } 194706f2543Smrg 195706f2543Smrg if (context->ctx != NULL) 196706f2543Smrg CGLDestroyContext(context->ctx); 197706f2543Smrg 198706f2543Smrg if (context->pixelFormat != NULL) 199706f2543Smrg CGLDestroyPixelFormat(context->pixelFormat); 200706f2543Smrg 201706f2543Smrg free(context); 202706f2543Smrg } 203706f2543Smrg} 204706f2543Smrg 205706f2543Smrgstatic int __glXAquaContextLoseCurrent(__GLXcontext *baseContext) { 206706f2543Smrg CGLError gl_err; 207706f2543Smrg 208706f2543Smrg GLAQUA_DEBUG_MSG("glAquaLoseCurrent (ctx 0x%p)\n", baseContext); 209706f2543Smrg 210706f2543Smrg gl_err = CGLSetCurrentContext(NULL); 211706f2543Smrg if (gl_err != 0) 212706f2543Smrg ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err)); 213706f2543Smrg 214706f2543Smrg /* 215706f2543Smrg * There should be no need to set __glXLastContext to NULL here, because 216706f2543Smrg * glxcmds.c does it as part of the context cache flush after calling 217706f2543Smrg * this. 218706f2543Smrg */ 219706f2543Smrg 220706f2543Smrg return GL_TRUE; 221706f2543Smrg} 222706f2543Smrg 223706f2543Smrg/* Called when a surface is destroyed as a side effect of destroying 224706f2543Smrg the window it's attached to. */ 225706f2543Smrgstatic void surface_notify(void *_arg, void *data) { 226706f2543Smrg DRISurfaceNotifyArg *arg = (DRISurfaceNotifyArg *)_arg; 227706f2543Smrg __GLXAquaDrawable *draw = (__GLXAquaDrawable *)data; 228706f2543Smrg __GLXAquaContext *context; 229706f2543Smrg x_list *lst; 230706f2543Smrg if(_arg == NULL || data == NULL) { 231706f2543Smrg ErrorF("surface_notify called with bad params"); 232706f2543Smrg return; 233706f2543Smrg } 234706f2543Smrg 235706f2543Smrg GLAQUA_DEBUG_MSG("surface_notify(%p, %p)\n", _arg, data); 236706f2543Smrg switch (arg->kind) { 237706f2543Smrg case AppleDRISurfaceNotifyDestroyed: 238706f2543Smrg if (surface_hash != NULL) 239706f2543Smrg x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(arg->id)); 240706f2543Smrg draw->pDraw = NULL; 241706f2543Smrg draw->sid = 0; 242706f2543Smrg break; 243706f2543Smrg 244706f2543Smrg case AppleDRISurfaceNotifyChanged: 245706f2543Smrg if (surface_hash != NULL) { 246706f2543Smrg lst = x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(arg->id), NULL); 247706f2543Smrg for (; lst != NULL; lst = lst->next) 248706f2543Smrg { 249706f2543Smrg context = lst->data; 250706f2543Smrg xp_update_gl_context(context->ctx); 251706f2543Smrg } 252706f2543Smrg } 253706f2543Smrg break; 254706f2543Smrg default: 255706f2543Smrg ErrorF("surface_notify: unknown kind %d\n", arg->kind); 256706f2543Smrg break; 257706f2543Smrg } 258706f2543Smrg} 259706f2543Smrg 260706f2543Smrgstatic BOOL attach(__GLXAquaContext *context, __GLXAquaDrawable *draw) { 261706f2543Smrg DrawablePtr pDraw; 262706f2543Smrg 263706f2543Smrg GLAQUA_DEBUG_MSG("attach(%p, %p)\n", context, draw); 264706f2543Smrg 265706f2543Smrg if(NULL == context || NULL == draw) 266706f2543Smrg return TRUE; 267706f2543Smrg 268706f2543Smrg pDraw = draw->base.pDraw; 269706f2543Smrg 270706f2543Smrg if(NULL == pDraw) { 271706f2543Smrg ErrorF("%s:%s() pDraw is NULL!\n", __FILE__, __func__); 272706f2543Smrg return TRUE; 273706f2543Smrg } 274706f2543Smrg 275706f2543Smrg if (draw->sid == 0) { 276706f2543Smrg //if (!quartzProcs->CreateSurface(pDraw->pScreen, pDraw->id, pDraw, 277706f2543Smrg if (!DRICreateSurface(pDraw->pScreen, pDraw->id, pDraw, 278706f2543Smrg 0, &draw->sid, NULL, 279706f2543Smrg surface_notify, draw)) 280706f2543Smrg return TRUE; 281706f2543Smrg draw->pDraw = pDraw; 282706f2543Smrg } 283706f2543Smrg 284706f2543Smrg if (!context->isAttached || context->sid != draw->sid) { 285706f2543Smrg x_list *lst; 286706f2543Smrg 287706f2543Smrg if (xp_attach_gl_context(context->ctx, draw->sid) != Success) { 288706f2543Smrg //quartzProcs->DestroySurface(pDraw->pScreen, pDraw->id, pDraw, 289706f2543Smrg DRIDestroySurface(pDraw->pScreen, pDraw->id, pDraw, 290706f2543Smrg surface_notify, draw); 291706f2543Smrg if (surface_hash != NULL) 292706f2543Smrg x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(draw->sid)); 293706f2543Smrg 294706f2543Smrg draw->sid = 0; 295706f2543Smrg return TRUE; 296706f2543Smrg } 297706f2543Smrg 298706f2543Smrg context->isAttached = TRUE; 299706f2543Smrg context->sid = draw->sid; 300706f2543Smrg 301706f2543Smrg if (surface_hash == NULL) 302706f2543Smrg surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL); 303706f2543Smrg 304706f2543Smrg lst = x_hash_table_lookup(surface_hash, x_cvt_uint_to_vptr(context->sid), NULL); 305706f2543Smrg if (x_list_find(lst, context) == NULL) { 306706f2543Smrg lst = x_list_prepend(lst, context); 307706f2543Smrg x_hash_table_insert(surface_hash, x_cvt_uint_to_vptr(context->sid), lst); 308706f2543Smrg } 309706f2543Smrg 310706f2543Smrg 311706f2543Smrg 312706f2543Smrg GLAQUA_DEBUG_MSG("attached 0x%x to 0x%x\n", (unsigned int) pDraw->id, 313706f2543Smrg (unsigned int) draw->sid); 314706f2543Smrg } 315706f2543Smrg 316706f2543Smrg draw->context = context; 317706f2543Smrg 318706f2543Smrg return FALSE; 319706f2543Smrg} 320706f2543Smrg 321706f2543Smrg#if 0 // unused 322706f2543Smrgstatic void unattach(__GLXAquaContext *context) { 323706f2543Smrg x_list *lst; 324706f2543Smrg GLAQUA_DEBUG_MSG("unattach\n"); 325706f2543Smrg if (context == NULL) { 326706f2543Smrg ErrorF("Tried to unattach a null context\n"); 327706f2543Smrg return; 328706f2543Smrg } 329706f2543Smrg if (context->isAttached) { 330706f2543Smrg GLAQUA_DEBUG_MSG("unattaching\n"); 331706f2543Smrg 332706f2543Smrg if (surface_hash != NULL) { 333706f2543Smrg lst = x_hash_table_lookup(surface_hash, (void *) context->sid, NULL); 334706f2543Smrg lst = x_list_remove(lst, context); 335706f2543Smrg x_hash_table_insert(surface_hash, (void *) context->sid, lst); 336706f2543Smrg } 337706f2543Smrg 338706f2543Smrg CGLClearDrawable(context->ctx); 339706f2543Smrg context->isAttached = FALSE; 340706f2543Smrg context->sid = 0; 341706f2543Smrg } 342706f2543Smrg} 343706f2543Smrg#endif 344706f2543Smrg 345706f2543Smrgstatic int __glXAquaContextMakeCurrent(__GLXcontext *baseContext) { 346706f2543Smrg CGLError gl_err; 347706f2543Smrg __GLXAquaContext *context = (__GLXAquaContext *) baseContext; 348706f2543Smrg __GLXAquaDrawable *drawPriv = (__GLXAquaDrawable *) context->base.drawPriv; 349706f2543Smrg 350706f2543Smrg GLAQUA_DEBUG_MSG("glAquaMakeCurrent (ctx 0x%p)\n", baseContext); 351706f2543Smrg 352706f2543Smrg if(attach(context, drawPriv)) 353706f2543Smrg return /*error*/ 0; 354706f2543Smrg 355706f2543Smrg gl_err = CGLSetCurrentContext(context->ctx); 356706f2543Smrg if (gl_err != 0) 357706f2543Smrg ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err)); 358706f2543Smrg 359706f2543Smrg return gl_err == 0; 360706f2543Smrg} 361706f2543Smrg 362706f2543Smrgstatic int __glXAquaContextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc, unsigned long mask) 363706f2543Smrg{ 364706f2543Smrg CGLError gl_err; 365706f2543Smrg 366706f2543Smrg __GLXAquaContext *dst = (__GLXAquaContext *) baseDst; 367706f2543Smrg __GLXAquaContext *src = (__GLXAquaContext *) baseSrc; 368706f2543Smrg 369706f2543Smrg GLAQUA_DEBUG_MSG("GLXAquaContextCopy\n"); 370706f2543Smrg 371706f2543Smrg gl_err = CGLCopyContext(src->ctx, dst->ctx, mask); 372706f2543Smrg if (gl_err != 0) 373706f2543Smrg ErrorF("CGLCopyContext error: %s\n", CGLErrorString(gl_err)); 374706f2543Smrg 375706f2543Smrg return gl_err == 0; 376706f2543Smrg} 377706f2543Smrg 378706f2543Smrgstatic int __glXAquaContextForceCurrent(__GLXcontext *baseContext) 379706f2543Smrg{ 380706f2543Smrg CGLError gl_err; 381706f2543Smrg __GLXAquaContext *context = (__GLXAquaContext *) baseContext; 382706f2543Smrg GLAQUA_DEBUG_MSG("glAquaForceCurrent (ctx %p)\n", context->ctx); 383706f2543Smrg 384706f2543Smrg gl_err = CGLSetCurrentContext(context->ctx); 385706f2543Smrg if (gl_err != 0) 386706f2543Smrg ErrorF("CGLSetCurrentContext error: %s\n", CGLErrorString(gl_err)); 387706f2543Smrg 388706f2543Smrg return gl_err == 0; 389706f2543Smrg} 390706f2543Smrg 391706f2543Smrg/* Drawing surface notification callbacks */ 392706f2543Smrgstatic GLboolean __glXAquaDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base) { 393706f2543Smrg CGLError err; 394706f2543Smrg __GLXAquaDrawable *drawable; 395706f2543Smrg 396706f2543Smrg // GLAQUA_DEBUG_MSG("glAquaDrawableSwapBuffers(%p)\n",base); 397706f2543Smrg 398706f2543Smrg if(!base) { 399706f2543Smrg ErrorF("%s passed NULL\n", __func__); 400706f2543Smrg return GL_FALSE; 401706f2543Smrg } 402706f2543Smrg 403706f2543Smrg drawable = (__GLXAquaDrawable *)base; 404706f2543Smrg 405706f2543Smrg if(NULL == drawable->context) { 406706f2543Smrg ErrorF("%s called with a NULL->context for drawable %p!\n", 407706f2543Smrg __func__, (void *)drawable); 408706f2543Smrg return GL_FALSE; 409706f2543Smrg } 410706f2543Smrg 411706f2543Smrg err = CGLFlushDrawable(drawable->context->ctx); 412706f2543Smrg 413706f2543Smrg if(kCGLNoError != err) { 414706f2543Smrg ErrorF("CGLFlushDrawable error: %s in %s\n", CGLErrorString(err), 415706f2543Smrg __func__); 416706f2543Smrg return GL_FALSE; 417706f2543Smrg } 418706f2543Smrg 419706f2543Smrg return GL_TRUE; 420706f2543Smrg} 421706f2543Smrg 422706f2543Smrg 423706f2543Smrgstatic CGLPixelFormatObj makeFormat(__GLXconfig *conf) { 424706f2543Smrg CGLPixelFormatAttribute attr[64]; 425706f2543Smrg CGLPixelFormatObj fobj; 426706f2543Smrg GLint formats; 427706f2543Smrg CGLError error; 428706f2543Smrg int i = 0; 429706f2543Smrg 430706f2543Smrg if(conf->doubleBufferMode) 431706f2543Smrg attr[i++] = kCGLPFADoubleBuffer; 432706f2543Smrg 433706f2543Smrg if(conf->stereoMode) 434706f2543Smrg attr[i++] = kCGLPFAStereo; 435706f2543Smrg 436706f2543Smrg attr[i++] = kCGLPFAColorSize; 437706f2543Smrg attr[i++] = conf->redBits + conf->greenBits + conf->blueBits; 438706f2543Smrg attr[i++] = kCGLPFAAlphaSize; 439706f2543Smrg attr[i++] = conf->alphaBits; 440706f2543Smrg 441706f2543Smrg if((conf->accumRedBits + conf->accumGreenBits + conf->accumBlueBits + 442706f2543Smrg conf->accumAlphaBits) > 0) { 443706f2543Smrg 444706f2543Smrg attr[i++] = kCGLPFAAccumSize; 445706f2543Smrg attr[i++] = conf->accumRedBits + conf->accumGreenBits 446706f2543Smrg + conf->accumBlueBits + conf->accumAlphaBits; 447706f2543Smrg } 448706f2543Smrg 449706f2543Smrg attr[i++] = kCGLPFADepthSize; 450706f2543Smrg attr[i++] = conf->depthBits; 451706f2543Smrg 452706f2543Smrg if(conf->stencilBits) { 453706f2543Smrg attr[i++] = kCGLPFAStencilSize; 454706f2543Smrg attr[i++] = conf->stencilBits; 455706f2543Smrg } 456706f2543Smrg 457706f2543Smrg if(conf->numAuxBuffers > 0) { 458706f2543Smrg attr[i++] = kCGLPFAAuxBuffers; 459706f2543Smrg attr[i++] = conf->numAuxBuffers; 460706f2543Smrg } 461706f2543Smrg 462706f2543Smrg if(conf->sampleBuffers > 0) { 463706f2543Smrg attr[i++] = kCGLPFASampleBuffers; 464706f2543Smrg attr[i++] = conf->sampleBuffers; 465706f2543Smrg attr[i++] = kCGLPFASamples; 466706f2543Smrg attr[i++] = conf->samples; 467706f2543Smrg } 468706f2543Smrg 469706f2543Smrg attr[i] = 0; 470706f2543Smrg 471706f2543Smrg error = CGLChoosePixelFormat(attr, &fobj, &formats); 472706f2543Smrg if(error) { 473706f2543Smrg ErrorF("error: creating pixel format %s\n", CGLErrorString(error)); 474706f2543Smrg return NULL; 475706f2543Smrg } 476706f2543Smrg 477706f2543Smrg return fobj; 478706f2543Smrg} 479706f2543Smrg 480706f2543Smrgstatic void __glXAquaScreenDestroy(__GLXscreen *screen) { 481706f2543Smrg 482706f2543Smrg GLAQUA_DEBUG_MSG("glXAquaScreenDestroy(%p)\n", screen); 483706f2543Smrg __glXScreenDestroy(screen); 484706f2543Smrg 485706f2543Smrg free(screen); 486706f2543Smrg} 487706f2543Smrg 488706f2543Smrg/* This is called by __glXInitScreens(). */ 489706f2543Smrgstatic __GLXscreen * __glXAquaScreenProbe(ScreenPtr pScreen) { 490706f2543Smrg __GLXAquaScreen *screen; 491706f2543Smrg 492706f2543Smrg GLAQUA_DEBUG_MSG("glXAquaScreenProbe\n"); 493706f2543Smrg 494706f2543Smrg if (pScreen == NULL) 495706f2543Smrg return NULL; 496706f2543Smrg 497706f2543Smrg screen = calloc(1, sizeof *screen); 498706f2543Smrg 499706f2543Smrg if(NULL == screen) 500706f2543Smrg return NULL; 501706f2543Smrg 502706f2543Smrg screen->base.destroy = __glXAquaScreenDestroy; 503706f2543Smrg screen->base.createContext = __glXAquaScreenCreateContext; 504706f2543Smrg screen->base.createDrawable = __glXAquaScreenCreateDrawable; 505706f2543Smrg screen->base.swapInterval = /*FIXME*/ NULL; 506706f2543Smrg screen->base.pScreen = pScreen; 507706f2543Smrg 508706f2543Smrg screen->base.fbconfigs = __glXAquaCreateVisualConfigs(&screen->base.numFBConfigs, pScreen->myNum); 509706f2543Smrg 510706f2543Smrg __glXScreenInit(&screen->base, pScreen); 511706f2543Smrg 512706f2543Smrg screen->base.GLXmajor = 1; 513706f2543Smrg screen->base.GLXminor = 4; 514706f2543Smrg screen->base.GLXextensions = strdup("GLX_SGIX_fbconfig " 515706f2543Smrg "GLX_SGIS_multisample " 516706f2543Smrg "GLX_ARB_multisample " 517706f2543Smrg "GLX_EXT_visual_info " 518706f2543Smrg "GLX_EXT_import_context "); 519706f2543Smrg 520706f2543Smrg /*We may be able to add more GLXextensions at a later time. */ 521706f2543Smrg 522706f2543Smrg return &screen->base; 523706f2543Smrg} 524706f2543Smrg 525706f2543Smrg#if 0 // unused 526706f2543Smrgstatic void __glXAquaDrawableCopySubBuffer (__GLXdrawable *drawable, 527706f2543Smrg int x, int y, int w, int h) { 528706f2543Smrg /*TODO finish me*/ 529706f2543Smrg} 530706f2543Smrg#endif 531706f2543Smrg 532706f2543Smrgstatic void __glXAquaDrawableDestroy(__GLXdrawable *base) { 533706f2543Smrg /* gstaplin: base is the head of the structure, so it's at the same 534706f2543Smrg * offset in memory. 535706f2543Smrg * Is this safe with strict aliasing? I noticed that the other dri code 536706f2543Smrg * does this too... 537706f2543Smrg */ 538706f2543Smrg __GLXAquaDrawable *glxPriv = (__GLXAquaDrawable *)base; 539706f2543Smrg 540706f2543Smrg GLAQUA_DEBUG_MSG(__func__); 541706f2543Smrg 542706f2543Smrg /* It doesn't work to call DRIDestroySurface here, the drawable's 543706f2543Smrg already gone.. But dri.c notices the window destruction and 544706f2543Smrg frees the surface itself. */ 545706f2543Smrg 546706f2543Smrg /*gstaplin: verify the statement above. The surface destroy 547706f2543Smrg *messages weren't making it through, and may still not be. 548706f2543Smrg *We need a good test case for surface creation and destruction. 549706f2543Smrg *We also need a good way to enable introspection on the server 550706f2543Smrg *to validate the test, beyond using gdb with print. 551706f2543Smrg */ 552706f2543Smrg 553706f2543Smrg free(glxPriv); 554706f2543Smrg} 555706f2543Smrg 556706f2543Smrgstatic __GLXdrawable * 557706f2543Smrg__glXAquaScreenCreateDrawable(ClientPtr client, 558706f2543Smrg __GLXscreen *screen, 559706f2543Smrg DrawablePtr pDraw, 560706f2543Smrg XID drawId, 561706f2543Smrg int type, 562706f2543Smrg XID glxDrawId, 563706f2543Smrg __GLXconfig *conf) { 564706f2543Smrg __GLXAquaDrawable *glxPriv; 565706f2543Smrg 566706f2543Smrg glxPriv = malloc(sizeof *glxPriv); 567706f2543Smrg 568706f2543Smrg if(glxPriv == NULL) 569706f2543Smrg return NULL; 570706f2543Smrg 571706f2543Smrg memset(glxPriv, 0, sizeof *glxPriv); 572706f2543Smrg 573706f2543Smrg if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) { 574706f2543Smrg free(glxPriv); 575706f2543Smrg return NULL; 576706f2543Smrg } 577706f2543Smrg 578706f2543Smrg glxPriv->base.destroy = __glXAquaDrawableDestroy; 579706f2543Smrg glxPriv->base.swapBuffers = __glXAquaDrawableSwapBuffers; 580706f2543Smrg glxPriv->base.copySubBuffer = NULL; /* __glXAquaDrawableCopySubBuffer; */ 581706f2543Smrg 582706f2543Smrg glxPriv->pDraw = pDraw; 583706f2543Smrg glxPriv->sid = 0; 584706f2543Smrg glxPriv->context = NULL; 585706f2543Smrg 586706f2543Smrg return &glxPriv->base; 587706f2543Smrg} 588706f2543Smrg 589706f2543Smrg// Extra goodies for glx 590706f2543Smrg 591706f2543SmrgGLuint __glFloorLog2(GLuint val) 592706f2543Smrg{ 593706f2543Smrg int c = 0; 594706f2543Smrg 595706f2543Smrg while (val > 1) { 596706f2543Smrg c++; 597706f2543Smrg val >>= 1; 598706f2543Smrg } 599706f2543Smrg return c; 600706f2543Smrg} 601706f2543Smrg 602706f2543Smrg#ifndef OPENGL_FRAMEWORK_PATH 603706f2543Smrg#define OPENGL_FRAMEWORK_PATH "/System/Library/Frameworks/OpenGL.framework/OpenGL" 604706f2543Smrg#endif 605706f2543Smrg 606706f2543Smrgstatic void setup_dispatch_table(void) { 607706f2543Smrg static struct _glapi_table *disp = NULL; 608706f2543Smrg static void *handle; 609706f2543Smrg const char *opengl_framework_path; 610706f2543Smrg 611706f2543Smrg if(disp) { 612706f2543Smrg _glapi_set_dispatch(disp); 613706f2543Smrg return; 614706f2543Smrg } 615706f2543Smrg 616706f2543Smrg opengl_framework_path = getenv("OPENGL_FRAMEWORK_PATH"); 617706f2543Smrg if (!opengl_framework_path) { 618706f2543Smrg opengl_framework_path = OPENGL_FRAMEWORK_PATH; 619706f2543Smrg } 620706f2543Smrg 621706f2543Smrg (void) dlerror(); /*drain dlerror */ 622706f2543Smrg handle = dlopen(opengl_framework_path, RTLD_LOCAL); 623706f2543Smrg 624706f2543Smrg if (!handle) { 625706f2543Smrg ErrorF("unable to dlopen %s : %s, using RTLD_DEFAULT\n", 626706f2543Smrg opengl_framework_path, dlerror()); 627706f2543Smrg handle = RTLD_DEFAULT; 628706f2543Smrg } 629706f2543Smrg 630706f2543Smrg disp = _glapi_create_table_from_handle(handle, "gl"); 631706f2543Smrg assert(disp); 632706f2543Smrg 633706f2543Smrg _glapi_set_dispatch(disp); 634706f2543Smrg} 635