1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 2008 Apple Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20706f2543Smrg * DEALINGS IN THE SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#include <stdio.h> 24706f2543Smrg#include <stdlib.h> 25706f2543Smrg#include <assert.h> 26706f2543Smrg#include <OpenGL/OpenGL.h> 27706f2543Smrg#include <OpenGL/gl.h> 28706f2543Smrg#include <OpenGL/glu.h> 29706f2543Smrg#include <OpenGL/glext.h> 30706f2543Smrg#include <ApplicationServices/ApplicationServices.h> 31706f2543Smrg 32706f2543Smrg#include "capabilities.h" 33706f2543Smrg 34706f2543Smrg#define Cursor X_Cursor 35706f2543Smrg#include "os.h" 36706f2543Smrg#undef Cursor 37706f2543Smrg 38706f2543Smrgstatic void handleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes) { 39706f2543Smrg if(bufferModes & kCGLStereoscopicBit) { 40706f2543Smrg c->stereo = true; 41706f2543Smrg } 42706f2543Smrg 43706f2543Smrg if(bufferModes & kCGLDoubleBufferBit) { 44706f2543Smrg c->buffers = 2; 45706f2543Smrg } else { 46706f2543Smrg c->buffers = 1; 47706f2543Smrg } 48706f2543Smrg} 49706f2543Smrg 50706f2543Smrgstatic void handleStencilModes(struct glCapabilitiesConfig *c, GLint smodes) { 51706f2543Smrg int offset = 0; 52706f2543Smrg 53706f2543Smrg if(kCGL0Bit & smodes) 54706f2543Smrg c->stencil_bit_depths[offset++] = 0; 55706f2543Smrg 56706f2543Smrg if(kCGL1Bit & smodes) 57706f2543Smrg c->stencil_bit_depths[offset++] = 1; 58706f2543Smrg 59706f2543Smrg if(kCGL2Bit & smodes) 60706f2543Smrg c->stencil_bit_depths[offset++] = 2; 61706f2543Smrg 62706f2543Smrg if(kCGL3Bit & smodes) 63706f2543Smrg c->stencil_bit_depths[offset++] = 3; 64706f2543Smrg 65706f2543Smrg if(kCGL4Bit & smodes) 66706f2543Smrg c->stencil_bit_depths[offset++] = 4; 67706f2543Smrg 68706f2543Smrg if(kCGL5Bit & smodes) 69706f2543Smrg c->stencil_bit_depths[offset++] = 5; 70706f2543Smrg 71706f2543Smrg if(kCGL6Bit & smodes) 72706f2543Smrg c->stencil_bit_depths[offset++] = 6; 73706f2543Smrg 74706f2543Smrg if(kCGL8Bit & smodes) 75706f2543Smrg c->stencil_bit_depths[offset++] = 8; 76706f2543Smrg 77706f2543Smrg if(kCGL10Bit & smodes) 78706f2543Smrg c->stencil_bit_depths[offset++] = 10; 79706f2543Smrg 80706f2543Smrg if(kCGL12Bit & smodes) 81706f2543Smrg c->stencil_bit_depths[offset++] = 12; 82706f2543Smrg 83706f2543Smrg if(kCGL16Bit & smodes) 84706f2543Smrg c->stencil_bit_depths[offset++] = 16; 85706f2543Smrg 86706f2543Smrg if(kCGL24Bit & smodes) 87706f2543Smrg c->stencil_bit_depths[offset++] = 24; 88706f2543Smrg 89706f2543Smrg if(kCGL32Bit & smodes) 90706f2543Smrg c->stencil_bit_depths[offset++] = 32; 91706f2543Smrg 92706f2543Smrg if(kCGL48Bit & smodes) 93706f2543Smrg c->stencil_bit_depths[offset++] = 48; 94706f2543Smrg 95706f2543Smrg if(kCGL64Bit & smodes) 96706f2543Smrg c->stencil_bit_depths[offset++] = 64; 97706f2543Smrg 98706f2543Smrg if(kCGL96Bit & smodes) 99706f2543Smrg c->stencil_bit_depths[offset++] = 96; 100706f2543Smrg 101706f2543Smrg if(kCGL128Bit & smodes) 102706f2543Smrg c->stencil_bit_depths[offset++] = 128; 103706f2543Smrg 104706f2543Smrg assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS); 105706f2543Smrg 106706f2543Smrg c->total_stencil_bit_depths = offset; 107706f2543Smrg} 108706f2543Smrg 109706f2543Smrgstatic int handleColorAndAccumulation(struct glColorBufCapabilities *c, 110706f2543Smrg GLint cmodes, int forAccum) { 111706f2543Smrg int offset = 0; 112706f2543Smrg 113706f2543Smrg /*1*/ 114706f2543Smrg if(kCGLRGB444Bit & cmodes) { 115706f2543Smrg c[offset].r = 4; 116706f2543Smrg c[offset].g = 4; 117706f2543Smrg c[offset].b = 4; 118706f2543Smrg ++offset; 119706f2543Smrg } 120706f2543Smrg 121706f2543Smrg /*2*/ 122706f2543Smrg if(kCGLARGB4444Bit & cmodes) { 123706f2543Smrg c[offset].a = 4; 124706f2543Smrg c[offset].r = 4; 125706f2543Smrg c[offset].g = 4; 126706f2543Smrg c[offset].b = 4; 127706f2543Smrg c[offset].is_argb = true; 128706f2543Smrg ++offset; 129706f2543Smrg } 130706f2543Smrg 131706f2543Smrg /*3*/ 132706f2543Smrg if(kCGLRGB444A8Bit & cmodes) { 133706f2543Smrg c[offset].r = 4; 134706f2543Smrg c[offset].g = 4; 135706f2543Smrg c[offset].b = 4; 136706f2543Smrg c[offset].a = 8; 137706f2543Smrg ++offset; 138706f2543Smrg } 139706f2543Smrg 140706f2543Smrg /*4*/ 141706f2543Smrg if(kCGLRGB555Bit & cmodes) { 142706f2543Smrg c[offset].r = 5; 143706f2543Smrg c[offset].g = 5; 144706f2543Smrg c[offset].b = 5; 145706f2543Smrg ++offset; 146706f2543Smrg } 147706f2543Smrg 148706f2543Smrg /*5*/ 149706f2543Smrg if(kCGLARGB1555Bit & cmodes) { 150706f2543Smrg c[offset].a = 1; 151706f2543Smrg c[offset].r = 5; 152706f2543Smrg c[offset].g = 5; 153706f2543Smrg c[offset].b = 5; 154706f2543Smrg c[offset].is_argb = true; 155706f2543Smrg ++offset; 156706f2543Smrg } 157706f2543Smrg 158706f2543Smrg /*6*/ 159706f2543Smrg if(kCGLRGB555A8Bit & cmodes) { 160706f2543Smrg c[offset].r = 5; 161706f2543Smrg c[offset].g = 5; 162706f2543Smrg c[offset].b = 5; 163706f2543Smrg c[offset].a = 8; 164706f2543Smrg ++offset; 165706f2543Smrg } 166706f2543Smrg 167706f2543Smrg /*7*/ 168706f2543Smrg if(kCGLRGB565Bit & cmodes) { 169706f2543Smrg c[offset].r = 5; 170706f2543Smrg c[offset].g = 6; 171706f2543Smrg c[offset].b = 5; 172706f2543Smrg ++offset; 173706f2543Smrg } 174706f2543Smrg 175706f2543Smrg /*8*/ 176706f2543Smrg if(kCGLRGB565A8Bit & cmodes) { 177706f2543Smrg c[offset].r = 5; 178706f2543Smrg c[offset].g = 6; 179706f2543Smrg c[offset].b = 5; 180706f2543Smrg c[offset].a = 8; 181706f2543Smrg ++offset; 182706f2543Smrg } 183706f2543Smrg 184706f2543Smrg /*9*/ 185706f2543Smrg if(kCGLRGB888Bit & cmodes) { 186706f2543Smrg c[offset].r = 8; 187706f2543Smrg c[offset].g = 8; 188706f2543Smrg c[offset].b = 8; 189706f2543Smrg ++offset; 190706f2543Smrg } 191706f2543Smrg 192706f2543Smrg /*10*/ 193706f2543Smrg if(kCGLARGB8888Bit & cmodes) { 194706f2543Smrg c[offset].a = 8; 195706f2543Smrg c[offset].r = 8; 196706f2543Smrg c[offset].g = 8; 197706f2543Smrg c[offset].b = 8; 198706f2543Smrg c[offset].is_argb = true; 199706f2543Smrg ++offset; 200706f2543Smrg } 201706f2543Smrg 202706f2543Smrg /*11*/ 203706f2543Smrg if(kCGLRGB888A8Bit & cmodes) { 204706f2543Smrg c[offset].r = 8; 205706f2543Smrg c[offset].g = 8; 206706f2543Smrg c[offset].b = 8; 207706f2543Smrg c[offset].a = 8; 208706f2543Smrg ++offset; 209706f2543Smrg } 210706f2543Smrg 211706f2543Smrg if(forAccum) { 212706f2543Smrg//#if 0 213706f2543Smrg /* FIXME 214706f2543Smrg * Disable this path, because some part of libGL, X, or Xplugin 215706f2543Smrg * doesn't work with sizes greater than 8. 216706f2543Smrg * When this is enabled and visuals are chosen using depths 217706f2543Smrg * such as 16, the result is that the windows don't redraw 218706f2543Smrg * and are often white, until a resize. 219706f2543Smrg */ 220706f2543Smrg 221706f2543Smrg /*12*/ 222706f2543Smrg if(kCGLRGB101010Bit & cmodes) { 223706f2543Smrg c[offset].r = 10; 224706f2543Smrg c[offset].g = 10; 225706f2543Smrg c[offset].b = 10; 226706f2543Smrg ++offset; 227706f2543Smrg } 228706f2543Smrg 229706f2543Smrg /*13*/ 230706f2543Smrg if(kCGLARGB2101010Bit & cmodes) { 231706f2543Smrg c[offset].a = 2; 232706f2543Smrg c[offset].r = 10; 233706f2543Smrg c[offset].g = 10; 234706f2543Smrg c[offset].b = 10; 235706f2543Smrg c[offset].is_argb = true; 236706f2543Smrg ++offset; 237706f2543Smrg } 238706f2543Smrg 239706f2543Smrg /*14*/ 240706f2543Smrg if(kCGLRGB101010_A8Bit & cmodes) { 241706f2543Smrg c[offset].r = 10; 242706f2543Smrg c[offset].g = 10; 243706f2543Smrg c[offset].b = 10; 244706f2543Smrg c[offset].a = 8; 245706f2543Smrg ++offset; 246706f2543Smrg } 247706f2543Smrg 248706f2543Smrg /*15*/ 249706f2543Smrg if(kCGLRGB121212Bit & cmodes) { 250706f2543Smrg c[offset].r = 12; 251706f2543Smrg c[offset].g = 12; 252706f2543Smrg c[offset].b = 12; 253706f2543Smrg ++offset; 254706f2543Smrg } 255706f2543Smrg 256706f2543Smrg /*16*/ 257706f2543Smrg if(kCGLARGB12121212Bit & cmodes) { 258706f2543Smrg c[offset].a = 12; 259706f2543Smrg c[offset].r = 12; 260706f2543Smrg c[offset].g = 12; 261706f2543Smrg c[offset].b = 12; 262706f2543Smrg c[offset].is_argb = true; 263706f2543Smrg ++offset; 264706f2543Smrg } 265706f2543Smrg 266706f2543Smrg /*17*/ 267706f2543Smrg if(kCGLRGB161616Bit & cmodes) { 268706f2543Smrg c[offset].r = 16; 269706f2543Smrg c[offset].g = 16; 270706f2543Smrg c[offset].b = 16; 271706f2543Smrg ++offset; 272706f2543Smrg } 273706f2543Smrg 274706f2543Smrg /*18*/ 275706f2543Smrg if(kCGLRGBA16161616Bit & cmodes) { 276706f2543Smrg c[offset].r = 16; 277706f2543Smrg c[offset].g = 16; 278706f2543Smrg c[offset].b = 16; 279706f2543Smrg c[offset].a = 16; 280706f2543Smrg ++offset; 281706f2543Smrg } 282706f2543Smrg } 283706f2543Smrg//#endif 284706f2543Smrg 285706f2543Smrg /* FIXME should we handle the floating point color modes, and if so, how? */ 286706f2543Smrg 287706f2543Smrg return offset; 288706f2543Smrg} 289706f2543Smrg 290706f2543Smrg 291706f2543Smrgstatic void handleColorModes(struct glCapabilitiesConfig *c, GLint cmodes) { 292706f2543Smrg c->total_color_buffers = handleColorAndAccumulation(c->color_buffers, 293706f2543Smrg cmodes, 0); 294706f2543Smrg 295706f2543Smrg assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS); 296706f2543Smrg} 297706f2543Smrg 298706f2543Smrgstatic void handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes) { 299706f2543Smrg c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers, 300706f2543Smrg cmodes, 1); 301706f2543Smrg assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS); 302706f2543Smrg} 303706f2543Smrg 304706f2543Smrgstatic void handleDepthModes(struct glCapabilitiesConfig *c, GLint dmodes) { 305706f2543Smrg int offset = 0; 306706f2543Smrg#define DEPTH(flag,value) do { \ 307706f2543Smrg if(dmodes & flag) { \ 308706f2543Smrg c->depth_buffers[offset++] = value; \ 309706f2543Smrg } \ 310706f2543Smrg } while(0) 311706f2543Smrg 312706f2543Smrg /*1*/ 313706f2543Smrg DEPTH(kCGL0Bit, 0); 314706f2543Smrg /*2*/ 315706f2543Smrg DEPTH(kCGL1Bit, 1); 316706f2543Smrg /*3*/ 317706f2543Smrg DEPTH(kCGL2Bit, 2); 318706f2543Smrg /*4*/ 319706f2543Smrg DEPTH(kCGL3Bit, 3); 320706f2543Smrg /*5*/ 321706f2543Smrg DEPTH(kCGL4Bit, 4); 322706f2543Smrg /*6*/ 323706f2543Smrg DEPTH(kCGL5Bit, 5); 324706f2543Smrg /*7*/ 325706f2543Smrg DEPTH(kCGL6Bit, 6); 326706f2543Smrg /*8*/ 327706f2543Smrg DEPTH(kCGL8Bit, 8); 328706f2543Smrg /*9*/ 329706f2543Smrg DEPTH(kCGL10Bit, 10); 330706f2543Smrg /*10*/ 331706f2543Smrg DEPTH(kCGL12Bit, 12); 332706f2543Smrg /*11*/ 333706f2543Smrg DEPTH(kCGL16Bit, 16); 334706f2543Smrg /*12*/ 335706f2543Smrg DEPTH(kCGL24Bit, 24); 336706f2543Smrg /*13*/ 337706f2543Smrg DEPTH(kCGL32Bit, 32); 338706f2543Smrg /*14*/ 339706f2543Smrg DEPTH(kCGL48Bit, 48); 340706f2543Smrg /*15*/ 341706f2543Smrg DEPTH(kCGL64Bit, 64); 342706f2543Smrg /*16*/ 343706f2543Smrg DEPTH(kCGL96Bit, 96); 344706f2543Smrg /*17*/ 345706f2543Smrg DEPTH(kCGL128Bit, 128); 346706f2543Smrg 347706f2543Smrg#undef DEPTH 348706f2543Smrg 349706f2543Smrg c->total_depth_buffer_depths = offset; 350706f2543Smrg assert(c->total_depth_buffer_depths < GLCAPS_DEPTH_BUFFERS); 351706f2543Smrg} 352706f2543Smrg 353706f2543Smrg/* Return non-zero if an error occured. */ 354706f2543Smrgstatic CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r, 355706f2543Smrg struct glCapabilitiesConfig *c) { 356706f2543Smrg CGLError err; 357706f2543Smrg GLint accelerated = 0, flags = 0, aux = 0, samplebufs = 0, samples = 0; 358706f2543Smrg 359706f2543Smrg err = CGLDescribeRenderer (info, r, kCGLRPAccelerated, &accelerated); 360706f2543Smrg 361706f2543Smrg if(err) 362706f2543Smrg return err; 363706f2543Smrg 364706f2543Smrg c->accelerated = accelerated; 365706f2543Smrg 366706f2543Smrg /* Buffering modes: single/double, stereo */ 367706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags); 368706f2543Smrg 369706f2543Smrg if(err) 370706f2543Smrg return err; 371706f2543Smrg 372706f2543Smrg handleBufferModes(c, flags); 373706f2543Smrg 374706f2543Smrg /* AUX buffers */ 375706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux); 376706f2543Smrg 377706f2543Smrg if(err) 378706f2543Smrg return err; 379706f2543Smrg 380706f2543Smrg c->aux_buffers = aux; 381706f2543Smrg 382706f2543Smrg 383706f2543Smrg /* Depth buffer size */ 384706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPDepthModes, &flags); 385706f2543Smrg 386706f2543Smrg if(err) 387706f2543Smrg return err; 388706f2543Smrg 389706f2543Smrg handleDepthModes(c, flags); 390706f2543Smrg 391706f2543Smrg 392706f2543Smrg /* Multisample buffers */ 393706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPMaxSampleBuffers, &samplebufs); 394706f2543Smrg 395706f2543Smrg if(err) 396706f2543Smrg return err; 397706f2543Smrg 398706f2543Smrg c->multisample_buffers = samplebufs; 399706f2543Smrg 400706f2543Smrg 401706f2543Smrg /* Multisample samples per multisample buffer */ 402706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPMaxSamples, &samples); 403706f2543Smrg 404706f2543Smrg if(err) 405706f2543Smrg return err; 406706f2543Smrg 407706f2543Smrg c->multisample_samples = samples; 408706f2543Smrg 409706f2543Smrg 410706f2543Smrg /* Stencil bit depths */ 411706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags); 412706f2543Smrg 413706f2543Smrg if(err) 414706f2543Smrg return err; 415706f2543Smrg 416706f2543Smrg handleStencilModes(c, flags); 417706f2543Smrg 418706f2543Smrg 419706f2543Smrg /* Color modes (RGB/RGBA depths supported */ 420706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags); 421706f2543Smrg 422706f2543Smrg if(err) 423706f2543Smrg return err; 424706f2543Smrg 425706f2543Smrg handleColorModes(c, flags); 426706f2543Smrg 427706f2543Smrg err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags); 428706f2543Smrg 429706f2543Smrg if(err) 430706f2543Smrg return err; 431706f2543Smrg 432706f2543Smrg handleAccumulationModes(c, flags); 433706f2543Smrg 434706f2543Smrg return kCGLNoError; 435706f2543Smrg} 436706f2543Smrg 437706f2543Smrgstatic void initCapabilities(struct glCapabilities *cap) { 438706f2543Smrg cap->configurations = NULL; 439706f2543Smrg cap->total_configurations = 0; 440706f2543Smrg} 441706f2543Smrg 442706f2543Smrgstatic void initConfig(struct glCapabilitiesConfig *c) { 443706f2543Smrg int i; 444706f2543Smrg 445706f2543Smrg c->accelerated = false; 446706f2543Smrg c->stereo = false; 447706f2543Smrg c->aux_buffers = 0; 448706f2543Smrg c->buffers = 0; 449706f2543Smrg 450706f2543Smrg c->total_depth_buffer_depths = 0; 451706f2543Smrg 452706f2543Smrg for(i = 0; i < GLCAPS_DEPTH_BUFFERS; ++i) { 453706f2543Smrg c->depth_buffers[i] = GLCAPS_INVALID_DEPTH_VALUE; 454706f2543Smrg } 455706f2543Smrg 456706f2543Smrg c->multisample_buffers = 0; 457706f2543Smrg c->multisample_samples = 0; 458706f2543Smrg 459706f2543Smrg c->total_stencil_bit_depths = 0; 460706f2543Smrg 461706f2543Smrg for(i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) { 462706f2543Smrg c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH; 463706f2543Smrg } 464706f2543Smrg 465706f2543Smrg c->total_color_buffers = 0; 466706f2543Smrg 467706f2543Smrg for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { 468706f2543Smrg c->color_buffers[i].r = c->color_buffers[i].g = 469706f2543Smrg c->color_buffers[i].b = c->color_buffers[i].a = 470706f2543Smrg GLCAPS_COLOR_BUF_INVALID_VALUE; 471706f2543Smrg c->color_buffers[i].is_argb = false; 472706f2543Smrg } 473706f2543Smrg 474706f2543Smrg c->total_accum_buffers = 0; 475706f2543Smrg 476706f2543Smrg for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { 477706f2543Smrg c->accum_buffers[i].r = c->accum_buffers[i].g = 478706f2543Smrg c->accum_buffers[i].b = c->accum_buffers[i].a = 479706f2543Smrg GLCAPS_COLOR_BUF_INVALID_VALUE; 480706f2543Smrg c->accum_buffers[i].is_argb = false; 481706f2543Smrg } 482706f2543Smrg 483706f2543Smrg c->next = NULL; 484706f2543Smrg} 485706f2543Smrg 486706f2543Smrgvoid freeGlCapabilities(struct glCapabilities *cap) { 487706f2543Smrg struct glCapabilitiesConfig *conf, *next; 488706f2543Smrg 489706f2543Smrg conf = cap->configurations; 490706f2543Smrg 491706f2543Smrg while(conf) { 492706f2543Smrg next = conf->next; 493706f2543Smrg free(conf); 494706f2543Smrg conf = next; 495706f2543Smrg } 496706f2543Smrg 497706f2543Smrg cap->configurations = NULL; 498706f2543Smrg} 499706f2543Smrg 500706f2543Smrg/*Return true if an error occured. */ 501706f2543Smrgbool getGlCapabilities(struct glCapabilities *cap) { 502706f2543Smrg CGLRendererInfoObj info; 503706f2543Smrg CGLError err; 504706f2543Smrg GLint numRenderers = 0, r; 505706f2543Smrg 506706f2543Smrg initCapabilities(cap); 507706f2543Smrg 508706f2543Smrg err = CGLQueryRendererInfo((GLuint)-1, &info, &numRenderers); 509706f2543Smrg if(err) { 510706f2543Smrg fprintf(stderr, "CGLQueryRendererInfo error: %s\n", CGLErrorString(err)); 511706f2543Smrg return err; 512706f2543Smrg } 513706f2543Smrg 514706f2543Smrg for(r = 0; r < numRenderers; r++) { 515706f2543Smrg struct glCapabilitiesConfig tmpconf, *conf; 516706f2543Smrg 517706f2543Smrg initConfig(&tmpconf); 518706f2543Smrg 519706f2543Smrg err = handleRendererDescriptions(info, r, &tmpconf); 520706f2543Smrg if(err) { 521706f2543Smrg fprintf(stderr, "handleRendererDescriptions returned error: %s\n", CGLErrorString(err)); 522706f2543Smrg fprintf(stderr, "trying to continue...\n"); 523706f2543Smrg continue; 524706f2543Smrg } 525706f2543Smrg 526706f2543Smrg conf = malloc(sizeof(*conf)); 527706f2543Smrg if(NULL == conf) { 528706f2543Smrg FatalError("Unable to allocate memory for OpenGL capabilities\n"); 529706f2543Smrg } 530706f2543Smrg 531706f2543Smrg /* Copy the struct. */ 532706f2543Smrg *conf = tmpconf; 533706f2543Smrg 534706f2543Smrg /* Now link the configuration into the list. */ 535706f2543Smrg conf->next = cap->configurations; 536706f2543Smrg cap->configurations = conf; 537706f2543Smrg } 538706f2543Smrg 539706f2543Smrg CGLDestroyRendererInfo(info); 540706f2543Smrg 541706f2543Smrg /* No error occured. We are done. */ 542706f2543Smrg return kCGLNoError; 543706f2543Smrg} 544