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