capabilities.c revision 35c4bbdf
17ec681f3Smrg/* 27ec681f3Smrg * Copyright (c) 2008-2012 Apple Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice shall be included in 127ec681f3Smrg * all copies or substantial portions of the Software. 137ec681f3Smrg * 147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 187ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 207ec681f3Smrg * DEALINGS IN THE SOFTWARE. 217ec681f3Smrg */ 227ec681f3Smrg 237ec681f3Smrg#ifdef HAVE_DIX_CONFIG_H 247ec681f3Smrg#include <dix-config.h> 257ec681f3Smrg#endif 267ec681f3Smrg 277ec681f3Smrg#include <stdio.h> 287ec681f3Smrg#include <stdlib.h> 297ec681f3Smrg#include <assert.h> 307ec681f3Smrg 317ec681f3Smrg#define Cursor Mac_Cursor 327ec681f3Smrg#define BOOL Mac_BOOL 337ec681f3Smrg#include <OpenGL/OpenGL.h> 347ec681f3Smrg#include <OpenGL/gl.h> 357ec681f3Smrg#include <OpenGL/glu.h> 367ec681f3Smrg#include <OpenGL/glext.h> 377ec681f3Smrg#include <ApplicationServices/ApplicationServices.h> 387ec681f3Smrg#undef Cursor 397ec681f3Smrg#undef BOOL 407ec681f3Smrg 417ec681f3Smrg#include "capabilities.h" 427ec681f3Smrg 437ec681f3Smrg#include "os.h" 447ec681f3Smrg 457ec681f3Smrgstatic void 467ec681f3SmrghandleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes) 477ec681f3Smrg{ 487ec681f3Smrg if (bufferModes & kCGLStereoscopicBit) { 497ec681f3Smrg c->stereo = true; 507ec681f3Smrg } 517ec681f3Smrg 527ec681f3Smrg if (bufferModes & kCGLDoubleBufferBit) { 537ec681f3Smrg c->buffers = 2; 547ec681f3Smrg } 557ec681f3Smrg else { 567ec681f3Smrg c->buffers = 1; 577ec681f3Smrg } 587ec681f3Smrg} 597ec681f3Smrg 607ec681f3Smrgstatic void 617ec681f3SmrghandleStencilModes(struct glCapabilitiesConfig *c, GLint smodes) 627ec681f3Smrg{ 637ec681f3Smrg int offset = 0; 647ec681f3Smrg 657ec681f3Smrg if (kCGL0Bit & smodes) 667ec681f3Smrg c->stencil_bit_depths[offset++] = 0; 677ec681f3Smrg 687ec681f3Smrg if (kCGL1Bit & smodes) 697ec681f3Smrg c->stencil_bit_depths[offset++] = 1; 707ec681f3Smrg 717ec681f3Smrg if (kCGL2Bit & smodes) 727ec681f3Smrg c->stencil_bit_depths[offset++] = 2; 737ec681f3Smrg 747ec681f3Smrg if (kCGL3Bit & smodes) 757ec681f3Smrg c->stencil_bit_depths[offset++] = 3; 767ec681f3Smrg 777ec681f3Smrg if (kCGL4Bit & smodes) 787ec681f3Smrg c->stencil_bit_depths[offset++] = 4; 797ec681f3Smrg 807ec681f3Smrg if (kCGL5Bit & smodes) 817ec681f3Smrg c->stencil_bit_depths[offset++] = 5; 827ec681f3Smrg 837ec681f3Smrg if (kCGL6Bit & smodes) 847ec681f3Smrg c->stencil_bit_depths[offset++] = 6; 857ec681f3Smrg 867ec681f3Smrg if (kCGL8Bit & smodes) 877ec681f3Smrg c->stencil_bit_depths[offset++] = 8; 887ec681f3Smrg 897ec681f3Smrg if (kCGL10Bit & smodes) 907ec681f3Smrg c->stencil_bit_depths[offset++] = 10; 917ec681f3Smrg 927ec681f3Smrg if (kCGL12Bit & smodes) 93 c->stencil_bit_depths[offset++] = 12; 94 95 if (kCGL16Bit & smodes) 96 c->stencil_bit_depths[offset++] = 16; 97 98 if (kCGL24Bit & smodes) 99 c->stencil_bit_depths[offset++] = 24; 100 101 if (kCGL32Bit & smodes) 102 c->stencil_bit_depths[offset++] = 32; 103 104 if (kCGL48Bit & smodes) 105 c->stencil_bit_depths[offset++] = 48; 106 107 if (kCGL64Bit & smodes) 108 c->stencil_bit_depths[offset++] = 64; 109 110 if (kCGL96Bit & smodes) 111 c->stencil_bit_depths[offset++] = 96; 112 113 if (kCGL128Bit & smodes) 114 c->stencil_bit_depths[offset++] = 128; 115 116 assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS); 117 118 c->total_stencil_bit_depths = offset; 119} 120 121static int 122handleColorAndAccumulation(struct glColorBufCapabilities *c, 123 GLint cmodes, int forAccum) 124{ 125 int offset = 0; 126 127 /*1*/ 128 if (kCGLRGB444Bit & cmodes) { 129 c[offset].r = 4; 130 c[offset].g = 4; 131 c[offset].b = 4; 132 ++offset; 133 } 134 135 /*2*/ 136 if (kCGLARGB4444Bit & cmodes) { 137 c[offset].a = 4; 138 c[offset].r = 4; 139 c[offset].g = 4; 140 c[offset].b = 4; 141 c[offset].is_argb = true; 142 ++offset; 143 } 144 145 /*3*/ 146 if (kCGLRGB444A8Bit & cmodes) { 147 c[offset].r = 4; 148 c[offset].g = 4; 149 c[offset].b = 4; 150 c[offset].a = 8; 151 ++offset; 152 } 153 154 /*4*/ 155 if (kCGLRGB555Bit & cmodes) { 156 c[offset].r = 5; 157 c[offset].g = 5; 158 c[offset].b = 5; 159 ++offset; 160 } 161 162 /*5*/ 163 if (kCGLARGB1555Bit & cmodes) { 164 c[offset].a = 1; 165 c[offset].r = 5; 166 c[offset].g = 5; 167 c[offset].b = 5; 168 c[offset].is_argb = true; 169 ++offset; 170 } 171 172 /*6*/ 173 if (kCGLRGB555A8Bit & cmodes) { 174 c[offset].r = 5; 175 c[offset].g = 5; 176 c[offset].b = 5; 177 c[offset].a = 8; 178 ++offset; 179 } 180 181 /*7*/ 182 if (kCGLRGB565Bit & cmodes) { 183 c[offset].r = 5; 184 c[offset].g = 6; 185 c[offset].b = 5; 186 ++offset; 187 } 188 189 /*8*/ 190 if (kCGLRGB565A8Bit & cmodes) { 191 c[offset].r = 5; 192 c[offset].g = 6; 193 c[offset].b = 5; 194 c[offset].a = 8; 195 ++offset; 196 } 197 198 /*9*/ 199 if (kCGLRGB888Bit & cmodes) { 200 c[offset].r = 8; 201 c[offset].g = 8; 202 c[offset].b = 8; 203 ++offset; 204 } 205 206 /*10*/ 207 if (kCGLARGB8888Bit & cmodes) { 208 c[offset].a = 8; 209 c[offset].r = 8; 210 c[offset].g = 8; 211 c[offset].b = 8; 212 c[offset].is_argb = true; 213 ++offset; 214 } 215 216 /*11*/ 217 if (kCGLRGB888A8Bit & cmodes) { 218 c[offset].r = 8; 219 c[offset].g = 8; 220 c[offset].b = 8; 221 c[offset].a = 8; 222 ++offset; 223 } 224 225 if (forAccum) { 226 //#if 0 227 /* FIXME 228 * Disable this path, because some part of libGL, X, or Xplugin 229 * doesn't work with sizes greater than 8. 230 * When this is enabled and visuals are chosen using depths 231 * such as 16, the result is that the windows don't redraw 232 * and are often white, until a resize. 233 */ 234 235 /*12*/ 236 if (kCGLRGB101010Bit & cmodes) { 237 c[offset].r = 10; 238 c[offset].g = 10; 239 c[offset].b = 10; 240 ++offset; 241 } 242 243 /*13*/ 244 if (kCGLARGB2101010Bit & cmodes) { 245 c[offset].a = 2; 246 c[offset].r = 10; 247 c[offset].g = 10; 248 c[offset].b = 10; 249 c[offset].is_argb = true; 250 ++offset; 251 } 252 253 /*14*/ 254 if (kCGLRGB101010_A8Bit & cmodes) { 255 c[offset].r = 10; 256 c[offset].g = 10; 257 c[offset].b = 10; 258 c[offset].a = 8; 259 ++offset; 260 } 261 262 /*15*/ 263 if (kCGLRGB121212Bit & cmodes) { 264 c[offset].r = 12; 265 c[offset].g = 12; 266 c[offset].b = 12; 267 ++offset; 268 } 269 270 /*16*/ 271 if (kCGLARGB12121212Bit & cmodes) { 272 c[offset].a = 12; 273 c[offset].r = 12; 274 c[offset].g = 12; 275 c[offset].b = 12; 276 c[offset].is_argb = true; 277 ++offset; 278 } 279 280 /*17*/ 281 if (kCGLRGB161616Bit & cmodes) { 282 c[offset].r = 16; 283 c[offset].g = 16; 284 c[offset].b = 16; 285 ++offset; 286 } 287 288 /*18*/ 289 if (kCGLRGBA16161616Bit & cmodes) { 290 c[offset].r = 16; 291 c[offset].g = 16; 292 c[offset].b = 16; 293 c[offset].a = 16; 294 ++offset; 295 } 296 } 297 //#endif 298 299 /* FIXME should we handle the floating point color modes, and if so, how? */ 300 301 return offset; 302} 303 304static void 305handleColorModes(struct glCapabilitiesConfig *c, GLint cmodes) 306{ 307 c->total_color_buffers = handleColorAndAccumulation(c->color_buffers, 308 cmodes, 0); 309 310 assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS); 311} 312 313static void 314handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes) 315{ 316 c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers, 317 cmodes, 1); 318 assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS); 319} 320 321static void 322handleDepthModes(struct glCapabilitiesConfig *c, GLint dmodes) 323{ 324 int offset = 0; 325#define DEPTH(flag, value) do { \ 326 if (dmodes & flag) { \ 327 c->depth_buffers[offset++] = value; \ 328 } \ 329} while (0) 330 331 /*1*/ 332 DEPTH(kCGL0Bit, 0); 333 /*2*/ 334 DEPTH(kCGL1Bit, 1); 335 /*3*/ 336 DEPTH(kCGL2Bit, 2); 337 /*4*/ 338 DEPTH(kCGL3Bit, 3); 339 /*5*/ 340 DEPTH(kCGL4Bit, 4); 341 /*6*/ 342 DEPTH(kCGL5Bit, 5); 343 /*7*/ 344 DEPTH(kCGL6Bit, 6); 345 /*8*/ 346 DEPTH(kCGL8Bit, 8); 347 /*9*/ 348 DEPTH(kCGL10Bit, 10); 349 /*10*/ 350 DEPTH(kCGL12Bit, 12); 351 /*11*/ 352 DEPTH(kCGL16Bit, 16); 353 /*12*/ 354 DEPTH(kCGL24Bit, 24); 355 /*13*/ 356 DEPTH(kCGL32Bit, 32); 357 /*14*/ 358 DEPTH(kCGL48Bit, 48); 359 /*15*/ 360 DEPTH(kCGL64Bit, 64); 361 /*16*/ 362 DEPTH(kCGL96Bit, 96); 363 /*17*/ 364 DEPTH(kCGL128Bit, 128); 365 366#undef DEPTH 367 368 c->total_depth_buffer_depths = offset; 369 assert(c->total_depth_buffer_depths < GLCAPS_DEPTH_BUFFERS); 370} 371 372/* Return non-zero if an error occured. */ 373static CGLError 374handleRendererDescriptions(CGLRendererInfoObj info, GLint r, 375 struct glCapabilitiesConfig *c) 376{ 377 CGLError err; 378 GLint accelerated = 0, flags = 0, aux = 0, samplebufs = 0, samples = 0; 379 380 err = CGLDescribeRenderer(info, r, kCGLRPAccelerated, &accelerated); 381 382 if (err) 383 return err; 384 385 c->accelerated = accelerated; 386 387 /* Buffering modes: single/double, stereo */ 388 err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags); 389 390 if (err) 391 return err; 392 393 handleBufferModes(c, flags); 394 395 /* AUX buffers */ 396 err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux); 397 398 if (err) 399 return err; 400 401 c->aux_buffers = aux; 402 403 /* Depth buffer size */ 404 err = CGLDescribeRenderer(info, r, kCGLRPDepthModes, &flags); 405 406 if (err) 407 return err; 408 409 handleDepthModes(c, flags); 410 411 /* Multisample buffers */ 412 err = CGLDescribeRenderer(info, r, kCGLRPMaxSampleBuffers, &samplebufs); 413 414 if (err) 415 return err; 416 417 c->multisample_buffers = samplebufs; 418 419 /* Multisample samples per multisample buffer */ 420 err = CGLDescribeRenderer(info, r, kCGLRPMaxSamples, &samples); 421 422 if (err) 423 return err; 424 425 c->multisample_samples = samples; 426 427 /* Stencil bit depths */ 428 err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags); 429 430 if (err) 431 return err; 432 433 handleStencilModes(c, flags); 434 435 /* Color modes (RGB/RGBA depths supported */ 436 err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags); 437 438 if (err) 439 return err; 440 441 handleColorModes(c, flags); 442 443 err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags); 444 445 if (err) 446 return err; 447 448 handleAccumulationModes(c, flags); 449 450 return kCGLNoError; 451} 452 453static void 454initCapabilities(struct glCapabilities *cap) 455{ 456 cap->configurations = NULL; 457 cap->total_configurations = 0; 458} 459 460static void 461initConfig(struct glCapabilitiesConfig *c) 462{ 463 int i; 464 465 c->accelerated = false; 466 c->stereo = false; 467 c->aux_buffers = 0; 468 c->buffers = 0; 469 470 c->total_depth_buffer_depths = 0; 471 472 for (i = 0; i < GLCAPS_DEPTH_BUFFERS; ++i) { 473 c->depth_buffers[i] = GLCAPS_INVALID_DEPTH_VALUE; 474 } 475 476 c->multisample_buffers = 0; 477 c->multisample_samples = 0; 478 479 c->total_stencil_bit_depths = 0; 480 481 for (i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) { 482 c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH; 483 } 484 485 c->total_color_buffers = 0; 486 487 for (i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { 488 c->color_buffers[i].r = c->color_buffers[i].g = 489 c->color_buffers[i].b = 490 c->color_buffers[i].a = 491 GLCAPS_COLOR_BUF_INVALID_VALUE; 492 c->color_buffers[i].is_argb = false; 493 } 494 495 c->total_accum_buffers = 0; 496 497 for (i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { 498 c->accum_buffers[i].r = c->accum_buffers[i].g = 499 c->accum_buffers[i].b = 500 c->accum_buffers[i].a = 501 GLCAPS_COLOR_BUF_INVALID_VALUE; 502 c->accum_buffers[i].is_argb = false; 503 } 504 505 c->next = NULL; 506} 507 508void 509freeGlCapabilities(struct glCapabilities *cap) 510{ 511 struct glCapabilitiesConfig *conf, *next; 512 513 conf = cap->configurations; 514 515 while (conf) { 516 next = conf->next; 517 free(conf); 518 conf = next; 519 } 520 521 cap->configurations = NULL; 522} 523 524/*Return true if an error occured. */ 525bool 526getGlCapabilities(struct glCapabilities *cap) 527{ 528 CGLRendererInfoObj info; 529 CGLError err; 530 GLint numRenderers = 0, r; 531 532 initCapabilities(cap); 533 534 err = CGLQueryRendererInfo((GLuint) - 1, &info, &numRenderers); 535 if (err) { 536 ErrorF("CGLQueryRendererInfo error: %s\n", CGLErrorString(err)); 537 return err; 538 } 539 540 for (r = 0; r < numRenderers; r++) { 541 struct glCapabilitiesConfig tmpconf, *conf; 542 543 initConfig(&tmpconf); 544 545 err = handleRendererDescriptions(info, r, &tmpconf); 546 if (err) { 547 ErrorF("handleRendererDescriptions returned error: %s\n", 548 CGLErrorString( 549 err)); 550 ErrorF("trying to continue...\n"); 551 continue; 552 } 553 554 conf = malloc(sizeof(*conf)); 555 if (NULL == conf) { 556 FatalError("Unable to allocate memory for OpenGL capabilities\n"); 557 } 558 559 /* Copy the struct. */ 560 *conf = tmpconf; 561 562 /* Now link the configuration into the list. */ 563 conf->next = cap->configurations; 564 cap->configurations = conf; 565 } 566 567 CGLDestroyRendererInfo(info); 568 569 /* No error occured. We are done. */ 570 return kCGLNoError; 571} 572