2 * Copyright (c) 2008-2012 Apple Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
31 #define Cursor Mac_Cursor
33 #include <OpenGL/OpenGL.h>
34 #include <OpenGL/gl.h>
35 #include <OpenGL/glu.h>
36 #include <OpenGL/glext.h>
37 #include <ApplicationServices/ApplicationServices.h>
41 #include "capabilities.h"
46 handleBufferModes(struct glCapabilitiesConfig
*c
, GLint bufferModes
)
48 if (bufferModes
& kCGLStereoscopicBit
) {
52 if (bufferModes
& kCGLDoubleBufferBit
) {
61 handleStencilModes(struct glCapabilitiesConfig
*c
, GLint smodes
)
65 if (kCGL0Bit
& smodes
)
66 c
->stencil_bit_depths
[offset
++] = 0;
68 if (kCGL1Bit
& smodes
)
69 c
->stencil_bit_depths
[offset
++] = 1;
71 if (kCGL2Bit
& smodes
)
72 c
->stencil_bit_depths
[offset
++] = 2;
74 if (kCGL3Bit
& smodes
)
75 c
->stencil_bit_depths
[offset
++] = 3;
77 if (kCGL4Bit
& smodes
)
78 c
->stencil_bit_depths
[offset
++] = 4;
80 if (kCGL5Bit
& smodes
)
81 c
->stencil_bit_depths
[offset
++] = 5;
83 if (kCGL6Bit
& smodes
)
84 c
->stencil_bit_depths
[offset
++] = 6;
86 if (kCGL8Bit
& smodes
)
87 c
->stencil_bit_depths
[offset
++] = 8;
89 if (kCGL10Bit
& smodes
)
90 c
->stencil_bit_depths
[offset
++] = 10;
92 if (kCGL12Bit
& smodes
)
93 c
->stencil_bit_depths
[offset
++] = 12;
95 if (kCGL16Bit
& smodes
)
96 c
->stencil_bit_depths
[offset
++] = 16;
98 if (kCGL24Bit
& smodes
)
99 c
->stencil_bit_depths
[offset
++] = 24;
101 if (kCGL32Bit
& smodes
)
102 c
->stencil_bit_depths
[offset
++] = 32;
104 if (kCGL48Bit
& smodes
)
105 c
->stencil_bit_depths
[offset
++] = 48;
107 if (kCGL64Bit
& smodes
)
108 c
->stencil_bit_depths
[offset
++] = 64;
110 if (kCGL96Bit
& smodes
)
111 c
->stencil_bit_depths
[offset
++] = 96;
113 if (kCGL128Bit
& smodes
)
114 c
->stencil_bit_depths
[offset
++] = 128;
116 assert(offset
< GLCAPS_STENCIL_BIT_DEPTH_BUFFERS
);
118 c
->total_stencil_bit_depths
= offset
;
122 handleColorAndAccumulation(struct glColorBufCapabilities
*c
,
123 GLint cmodes
, int forAccum
)
128 if (kCGLRGB444Bit
& cmodes
) {
136 if (kCGLARGB4444Bit
& cmodes
) {
141 c
[offset
].is_argb
= true;
146 if (kCGLRGB444A8Bit
& cmodes
) {
155 if (kCGLRGB555Bit
& cmodes
) {
163 if (kCGLARGB1555Bit
& cmodes
) {
168 c
[offset
].is_argb
= true;
173 if (kCGLRGB555A8Bit
& cmodes
) {
182 if (kCGLRGB565Bit
& cmodes
) {
190 if (kCGLRGB565A8Bit
& cmodes
) {
199 if (kCGLRGB888Bit
& cmodes
) {
207 if (kCGLARGB8888Bit
& cmodes
) {
212 c
[offset
].is_argb
= true;
217 if (kCGLRGB888A8Bit
& cmodes
) {
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.
236 if (kCGLRGB101010Bit
& cmodes
) {
244 if (kCGLARGB2101010Bit
& cmodes
) {
249 c
[offset
].is_argb
= true;
254 if (kCGLRGB101010_A8Bit
& cmodes
) {
263 if (kCGLRGB121212Bit
& cmodes
) {
271 if (kCGLARGB12121212Bit
& cmodes
) {
276 c
[offset
].is_argb
= true;
281 if (kCGLRGB161616Bit
& cmodes
) {
289 if (kCGLRGBA16161616Bit
& cmodes
) {
299 /* FIXME should we handle the floating point color modes, and if so, how? */
305 handleColorModes(struct glCapabilitiesConfig
*c
, GLint cmodes
)
307 c
->total_color_buffers
= handleColorAndAccumulation(c
->color_buffers
,
310 assert(c
->total_color_buffers
< GLCAPS_COLOR_BUFFERS
);
314 handleAccumulationModes(struct glCapabilitiesConfig
*c
, GLint cmodes
)
316 c
->total_accum_buffers
= handleColorAndAccumulation(c
->accum_buffers
,
318 assert(c
->total_accum_buffers
< GLCAPS_COLOR_BUFFERS
);
322 handleDepthModes(struct glCapabilitiesConfig
*c
, GLint dmodes
)
325 #define DEPTH(flag, value) do { \
326 if (dmodes & flag) { \
327 c->depth_buffers[offset++] = value; \
348 DEPTH(kCGL10Bit
, 10);
350 DEPTH(kCGL12Bit
, 12);
352 DEPTH(kCGL16Bit
, 16);
354 DEPTH(kCGL24Bit
, 24);
356 DEPTH(kCGL32Bit
, 32);
358 DEPTH(kCGL48Bit
, 48);
360 DEPTH(kCGL64Bit
, 64);
362 DEPTH(kCGL96Bit
, 96);
364 DEPTH(kCGL128Bit
, 128);
368 c
->total_depth_buffer_depths
= offset
;
369 assert(c
->total_depth_buffer_depths
< GLCAPS_DEPTH_BUFFERS
);
372 /* Return non-zero if an error occured. */
374 handleRendererDescriptions(CGLRendererInfoObj info
, GLint r
,
375 struct glCapabilitiesConfig
*c
)
378 GLint accelerated
= 0, flags
= 0, aux
= 0, samplebufs
= 0, samples
= 0;
380 err
= CGLDescribeRenderer(info
, r
, kCGLRPAccelerated
, &accelerated
);
385 c
->accelerated
= accelerated
;
387 /* Buffering modes: single/double, stereo */
388 err
= CGLDescribeRenderer(info
, r
, kCGLRPBufferModes
, &flags
);
393 handleBufferModes(c
, flags
);
396 err
= CGLDescribeRenderer(info
, r
, kCGLRPMaxAuxBuffers
, &aux
);
401 c
->aux_buffers
= aux
;
403 /* Depth buffer size */
404 err
= CGLDescribeRenderer(info
, r
, kCGLRPDepthModes
, &flags
);
409 handleDepthModes(c
, flags
);
411 /* Multisample buffers */
412 err
= CGLDescribeRenderer(info
, r
, kCGLRPMaxSampleBuffers
, &samplebufs
);
417 c
->multisample_buffers
= samplebufs
;
419 /* Multisample samples per multisample buffer */
420 err
= CGLDescribeRenderer(info
, r
, kCGLRPMaxSamples
, &samples
);
425 c
->multisample_samples
= samples
;
427 /* Stencil bit depths */
428 err
= CGLDescribeRenderer(info
, r
, kCGLRPStencilModes
, &flags
);
433 handleStencilModes(c
, flags
);
435 /* Color modes (RGB/RGBA depths supported */
436 err
= CGLDescribeRenderer(info
, r
, kCGLRPColorModes
, &flags
);
441 handleColorModes(c
, flags
);
443 err
= CGLDescribeRenderer(info
, r
, kCGLRPAccumModes
, &flags
);
448 handleAccumulationModes(c
, flags
);
454 initCapabilities(struct glCapabilities
*cap
)
456 cap
->configurations
= NULL
;
457 cap
->total_configurations
= 0;
461 initConfig(struct glCapabilitiesConfig
*c
)
465 c
->accelerated
= false;
470 c
->total_depth_buffer_depths
= 0;
472 for (i
= 0; i
< GLCAPS_DEPTH_BUFFERS
; ++i
) {
473 c
->depth_buffers
[i
] = GLCAPS_INVALID_DEPTH_VALUE
;
476 c
->multisample_buffers
= 0;
477 c
->multisample_samples
= 0;
479 c
->total_stencil_bit_depths
= 0;
481 for (i
= 0; i
< GLCAPS_STENCIL_BIT_DEPTH_BUFFERS
; ++i
) {
482 c
->stencil_bit_depths
[i
] = GLCAPS_INVALID_STENCIL_DEPTH
;
485 c
->total_color_buffers
= 0;
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;
495 c
->total_accum_buffers
= 0;
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;
509 freeGlCapabilities(struct glCapabilities
*cap
)
511 struct glCapabilitiesConfig
*conf
, *next
;
513 conf
= cap
->configurations
;
521 cap
->configurations
= NULL
;
524 /*Return true if an error occured. */
526 getGlCapabilities(struct glCapabilities
*cap
)
528 CGLRendererInfoObj info
;
530 GLint numRenderers
= 0, r
;
532 initCapabilities(cap
);
534 err
= CGLQueryRendererInfo((GLuint
) - 1, &info
, &numRenderers
);
536 ErrorF("CGLQueryRendererInfo error: %s\n", CGLErrorString(err
));
540 for (r
= 0; r
< numRenderers
; r
++) {
541 struct glCapabilitiesConfig tmpconf
, *conf
;
543 initConfig(&tmpconf
);
545 err
= handleRendererDescriptions(info
, r
, &tmpconf
);
547 ErrorF("handleRendererDescriptions returned error: %s\n",
550 ErrorF("trying to continue...\n");
554 conf
= malloc(sizeof(*conf
));
556 FatalError("Unable to allocate memory for OpenGL capabilities\n");
559 /* Copy the struct. */
562 /* Now link the configuration into the list. */
563 conf
->next
= cap
->configurations
;
564 cap
->configurations
= conf
;
567 CGLDestroyRendererInfo(info
);
569 /* No error occured. We are done. */