14642e01fSmrg/*
235c4bbdfSmrg * Copyright (c) 2008-2012 Apple Inc.
34642e01fSmrg *
44642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
54642e01fSmrg * copy of this software and associated documentation files (the "Software"),
64642e01fSmrg * to deal in the Software without restriction, including without limitation
74642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
94642e01fSmrg * Software is furnished to do so, subject to the following conditions:
104642e01fSmrg *
114642e01fSmrg * The above copyright notice and this permission notice shall be included in
124642e01fSmrg * all copies or substantial portions of the Software.
134642e01fSmrg *
144642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
204642e01fSmrg * DEALINGS IN THE SOFTWARE.
214642e01fSmrg */
224642e01fSmrg
2335c4bbdfSmrg#ifdef HAVE_DIX_CONFIG_H
2435c4bbdfSmrg#include <dix-config.h>
2535c4bbdfSmrg#endif
2635c4bbdfSmrg
274642e01fSmrg#include <stdio.h>
284642e01fSmrg#include <stdlib.h>
294642e01fSmrg#include <assert.h>
3035c4bbdfSmrg
3135c4bbdfSmrg#define Cursor Mac_Cursor
3235c4bbdfSmrg#define BOOL   Mac_BOOL
334642e01fSmrg#include <OpenGL/OpenGL.h>
344642e01fSmrg#include <OpenGL/gl.h>
354642e01fSmrg#include <OpenGL/glu.h>
364642e01fSmrg#include <OpenGL/glext.h>
374642e01fSmrg#include <ApplicationServices/ApplicationServices.h>
3835c4bbdfSmrg#undef Cursor
3935c4bbdfSmrg#undef BOOL
404642e01fSmrg
414642e01fSmrg#include "capabilities.h"
424642e01fSmrg
436747b715Smrg#include "os.h"
446747b715Smrg
4535c4bbdfSmrgstatic void
4635c4bbdfSmrghandleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes)
4735c4bbdfSmrg{
4835c4bbdfSmrg    if (bufferModes & kCGLStereoscopicBit) {
4935c4bbdfSmrg        c->stereo = true;
504642e01fSmrg    }
514642e01fSmrg
5235c4bbdfSmrg    if (bufferModes & kCGLDoubleBufferBit) {
5335c4bbdfSmrg        c->buffers = 2;
5435c4bbdfSmrg    }
5535c4bbdfSmrg    else {
5635c4bbdfSmrg        c->buffers = 1;
574642e01fSmrg    }
584642e01fSmrg}
594642e01fSmrg
6035c4bbdfSmrgstatic void
6135c4bbdfSmrghandleStencilModes(struct glCapabilitiesConfig *c, GLint smodes)
6235c4bbdfSmrg{
634642e01fSmrg    int offset = 0;
6435c4bbdfSmrg
6535c4bbdfSmrg    if (kCGL0Bit & smodes)
6635c4bbdfSmrg        c->stencil_bit_depths[offset++] = 0;
6735c4bbdfSmrg
6835c4bbdfSmrg    if (kCGL1Bit & smodes)
6935c4bbdfSmrg        c->stencil_bit_depths[offset++] = 1;
7035c4bbdfSmrg
7135c4bbdfSmrg    if (kCGL2Bit & smodes)
7235c4bbdfSmrg        c->stencil_bit_depths[offset++] = 2;
7335c4bbdfSmrg
7435c4bbdfSmrg    if (kCGL3Bit & smodes)
7535c4bbdfSmrg        c->stencil_bit_depths[offset++] = 3;
7635c4bbdfSmrg
7735c4bbdfSmrg    if (kCGL4Bit & smodes)
7835c4bbdfSmrg        c->stencil_bit_depths[offset++] = 4;
7935c4bbdfSmrg
8035c4bbdfSmrg    if (kCGL5Bit & smodes)
8135c4bbdfSmrg        c->stencil_bit_depths[offset++] = 5;
8235c4bbdfSmrg
8335c4bbdfSmrg    if (kCGL6Bit & smodes)
8435c4bbdfSmrg        c->stencil_bit_depths[offset++] = 6;
8535c4bbdfSmrg
8635c4bbdfSmrg    if (kCGL8Bit & smodes)
8735c4bbdfSmrg        c->stencil_bit_depths[offset++] = 8;
8835c4bbdfSmrg
8935c4bbdfSmrg    if (kCGL10Bit & smodes)
9035c4bbdfSmrg        c->stencil_bit_depths[offset++] = 10;
9135c4bbdfSmrg
9235c4bbdfSmrg    if (kCGL12Bit & smodes)
9335c4bbdfSmrg        c->stencil_bit_depths[offset++] = 12;
9435c4bbdfSmrg
9535c4bbdfSmrg    if (kCGL16Bit & smodes)
9635c4bbdfSmrg        c->stencil_bit_depths[offset++] = 16;
9735c4bbdfSmrg
9835c4bbdfSmrg    if (kCGL24Bit & smodes)
9935c4bbdfSmrg        c->stencil_bit_depths[offset++] = 24;
10035c4bbdfSmrg
10135c4bbdfSmrg    if (kCGL32Bit & smodes)
10235c4bbdfSmrg        c->stencil_bit_depths[offset++] = 32;
10335c4bbdfSmrg
10435c4bbdfSmrg    if (kCGL48Bit & smodes)
10535c4bbdfSmrg        c->stencil_bit_depths[offset++] = 48;
10635c4bbdfSmrg
10735c4bbdfSmrg    if (kCGL64Bit & smodes)
10835c4bbdfSmrg        c->stencil_bit_depths[offset++] = 64;
10935c4bbdfSmrg
11035c4bbdfSmrg    if (kCGL96Bit & smodes)
11135c4bbdfSmrg        c->stencil_bit_depths[offset++] = 96;
11235c4bbdfSmrg
11335c4bbdfSmrg    if (kCGL128Bit & smodes)
11435c4bbdfSmrg        c->stencil_bit_depths[offset++] = 128;
1154642e01fSmrg
1164642e01fSmrg    assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS);
1174642e01fSmrg
1184642e01fSmrg    c->total_stencil_bit_depths = offset;
1194642e01fSmrg}
1204642e01fSmrg
12135c4bbdfSmrgstatic int
12235c4bbdfSmrghandleColorAndAccumulation(struct glColorBufCapabilities *c,
12335c4bbdfSmrg                           GLint cmodes, int forAccum)
12435c4bbdfSmrg{
1254642e01fSmrg    int offset = 0;
12635c4bbdfSmrg
1274642e01fSmrg    /*1*/
12835c4bbdfSmrg    if (kCGLRGB444Bit & cmodes) {
12935c4bbdfSmrg        c[offset].r = 4;
13035c4bbdfSmrg        c[offset].g = 4;
13135c4bbdfSmrg        c[offset].b = 4;
13235c4bbdfSmrg        ++offset;
1334642e01fSmrg    }
13435c4bbdfSmrg
1354642e01fSmrg    /*2*/
13635c4bbdfSmrg    if (kCGLARGB4444Bit & cmodes) {
13735c4bbdfSmrg        c[offset].a = 4;
13835c4bbdfSmrg        c[offset].r = 4;
13935c4bbdfSmrg        c[offset].g = 4;
14035c4bbdfSmrg        c[offset].b = 4;
14135c4bbdfSmrg        c[offset].is_argb = true;
14235c4bbdfSmrg        ++offset;
1434642e01fSmrg    }
14435c4bbdfSmrg
1454642e01fSmrg    /*3*/
14635c4bbdfSmrg    if (kCGLRGB444A8Bit & cmodes) {
14735c4bbdfSmrg        c[offset].r = 4;
14835c4bbdfSmrg        c[offset].g = 4;
14935c4bbdfSmrg        c[offset].b = 4;
15035c4bbdfSmrg        c[offset].a = 8;
15135c4bbdfSmrg        ++offset;
1524642e01fSmrg    }
1534642e01fSmrg
1544642e01fSmrg    /*4*/
15535c4bbdfSmrg    if (kCGLRGB555Bit & cmodes) {
15635c4bbdfSmrg        c[offset].r = 5;
15735c4bbdfSmrg        c[offset].g = 5;
15835c4bbdfSmrg        c[offset].b = 5;
15935c4bbdfSmrg        ++offset;
1604642e01fSmrg    }
1614642e01fSmrg
1624642e01fSmrg    /*5*/
16335c4bbdfSmrg    if (kCGLARGB1555Bit & cmodes) {
16435c4bbdfSmrg        c[offset].a = 1;
16535c4bbdfSmrg        c[offset].r = 5;
16635c4bbdfSmrg        c[offset].g = 5;
16735c4bbdfSmrg        c[offset].b = 5;
16835c4bbdfSmrg        c[offset].is_argb = true;
16935c4bbdfSmrg        ++offset;
1704642e01fSmrg    }
1714642e01fSmrg
1724642e01fSmrg    /*6*/
17335c4bbdfSmrg    if (kCGLRGB555A8Bit & cmodes) {
17435c4bbdfSmrg        c[offset].r = 5;
17535c4bbdfSmrg        c[offset].g = 5;
17635c4bbdfSmrg        c[offset].b = 5;
17735c4bbdfSmrg        c[offset].a = 8;
17835c4bbdfSmrg        ++offset;
1794642e01fSmrg    }
1804642e01fSmrg
1814642e01fSmrg    /*7*/
18235c4bbdfSmrg    if (kCGLRGB565Bit & cmodes) {
18335c4bbdfSmrg        c[offset].r = 5;
18435c4bbdfSmrg        c[offset].g = 6;
18535c4bbdfSmrg        c[offset].b = 5;
18635c4bbdfSmrg        ++offset;
1874642e01fSmrg    }
1884642e01fSmrg
1894642e01fSmrg    /*8*/
19035c4bbdfSmrg    if (kCGLRGB565A8Bit & cmodes) {
19135c4bbdfSmrg        c[offset].r = 5;
19235c4bbdfSmrg        c[offset].g = 6;
19335c4bbdfSmrg        c[offset].b = 5;
19435c4bbdfSmrg        c[offset].a = 8;
19535c4bbdfSmrg        ++offset;
1964642e01fSmrg    }
1974642e01fSmrg
1984642e01fSmrg    /*9*/
19935c4bbdfSmrg    if (kCGLRGB888Bit & cmodes) {
20035c4bbdfSmrg        c[offset].r = 8;
20135c4bbdfSmrg        c[offset].g = 8;
20235c4bbdfSmrg        c[offset].b = 8;
20335c4bbdfSmrg        ++offset;
2044642e01fSmrg    }
2054642e01fSmrg
2064642e01fSmrg    /*10*/
20735c4bbdfSmrg    if (kCGLARGB8888Bit & cmodes) {
20835c4bbdfSmrg        c[offset].a = 8;
20935c4bbdfSmrg        c[offset].r = 8;
21035c4bbdfSmrg        c[offset].g = 8;
21135c4bbdfSmrg        c[offset].b = 8;
21235c4bbdfSmrg        c[offset].is_argb = true;
21335c4bbdfSmrg        ++offset;
2144642e01fSmrg    }
2154642e01fSmrg
2164642e01fSmrg    /*11*/
21735c4bbdfSmrg    if (kCGLRGB888A8Bit & cmodes) {
21835c4bbdfSmrg        c[offset].r = 8;
21935c4bbdfSmrg        c[offset].g = 8;
22035c4bbdfSmrg        c[offset].b = 8;
22135c4bbdfSmrg        c[offset].a = 8;
22235c4bbdfSmrg        ++offset;
2234642e01fSmrg    }
2244642e01fSmrg
22535c4bbdfSmrg    if (forAccum) {
22635c4bbdfSmrg        //#if 0
22735c4bbdfSmrg        /* FIXME
22835c4bbdfSmrg         * Disable this path, because some part of libGL, X, or Xplugin
22935c4bbdfSmrg         * doesn't work with sizes greater than 8.
23035c4bbdfSmrg         * When this is enabled and visuals are chosen using depths
23135c4bbdfSmrg         * such as 16, the result is that the windows don't redraw
23235c4bbdfSmrg         * and are often white, until a resize.
23335c4bbdfSmrg         */
23435c4bbdfSmrg
23535c4bbdfSmrg        /*12*/
23635c4bbdfSmrg        if (kCGLRGB101010Bit & cmodes) {
23735c4bbdfSmrg            c[offset].r = 10;
23835c4bbdfSmrg            c[offset].g = 10;
23935c4bbdfSmrg            c[offset].b = 10;
24035c4bbdfSmrg            ++offset;
24135c4bbdfSmrg        }
24235c4bbdfSmrg
24335c4bbdfSmrg        /*13*/
24435c4bbdfSmrg        if (kCGLARGB2101010Bit & cmodes) {
24535c4bbdfSmrg            c[offset].a = 2;
24635c4bbdfSmrg            c[offset].r = 10;
24735c4bbdfSmrg            c[offset].g = 10;
24835c4bbdfSmrg            c[offset].b = 10;
24935c4bbdfSmrg            c[offset].is_argb = true;
25035c4bbdfSmrg            ++offset;
25135c4bbdfSmrg        }
25235c4bbdfSmrg
25335c4bbdfSmrg        /*14*/
25435c4bbdfSmrg        if (kCGLRGB101010_A8Bit & cmodes) {
25535c4bbdfSmrg            c[offset].r = 10;
25635c4bbdfSmrg            c[offset].g = 10;
25735c4bbdfSmrg            c[offset].b = 10;
25835c4bbdfSmrg            c[offset].a = 8;
25935c4bbdfSmrg            ++offset;
26035c4bbdfSmrg        }
26135c4bbdfSmrg
26235c4bbdfSmrg        /*15*/
26335c4bbdfSmrg        if (kCGLRGB121212Bit & cmodes) {
26435c4bbdfSmrg            c[offset].r = 12;
26535c4bbdfSmrg            c[offset].g = 12;
26635c4bbdfSmrg            c[offset].b = 12;
26735c4bbdfSmrg            ++offset;
26835c4bbdfSmrg        }
26935c4bbdfSmrg
27035c4bbdfSmrg        /*16*/
27135c4bbdfSmrg        if (kCGLARGB12121212Bit & cmodes) {
27235c4bbdfSmrg            c[offset].a = 12;
27335c4bbdfSmrg            c[offset].r = 12;
27435c4bbdfSmrg            c[offset].g = 12;
27535c4bbdfSmrg            c[offset].b = 12;
27635c4bbdfSmrg            c[offset].is_argb = true;
27735c4bbdfSmrg            ++offset;
27835c4bbdfSmrg        }
27935c4bbdfSmrg
28035c4bbdfSmrg        /*17*/
28135c4bbdfSmrg        if (kCGLRGB161616Bit & cmodes) {
28235c4bbdfSmrg            c[offset].r = 16;
28335c4bbdfSmrg            c[offset].g = 16;
28435c4bbdfSmrg            c[offset].b = 16;
28535c4bbdfSmrg            ++offset;
28635c4bbdfSmrg        }
28735c4bbdfSmrg
28835c4bbdfSmrg        /*18*/
28935c4bbdfSmrg        if (kCGLRGBA16161616Bit & cmodes) {
29035c4bbdfSmrg            c[offset].r = 16;
29135c4bbdfSmrg            c[offset].g = 16;
29235c4bbdfSmrg            c[offset].b = 16;
29335c4bbdfSmrg            c[offset].a = 16;
29435c4bbdfSmrg            ++offset;
29535c4bbdfSmrg        }
2964642e01fSmrg    }
29735c4bbdfSmrg    //#endif
2984642e01fSmrg
2994642e01fSmrg    /* FIXME should we handle the floating point color modes, and if so, how? */
30035c4bbdfSmrg
3014642e01fSmrg    return offset;
3024642e01fSmrg}
3034642e01fSmrg
30435c4bbdfSmrgstatic void
30535c4bbdfSmrghandleColorModes(struct glCapabilitiesConfig *c, GLint cmodes)
30635c4bbdfSmrg{
3074642e01fSmrg    c->total_color_buffers = handleColorAndAccumulation(c->color_buffers,
30835c4bbdfSmrg                                                        cmodes, 0);
30935c4bbdfSmrg
3104642e01fSmrg    assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS);
3114642e01fSmrg}
3124642e01fSmrg
31335c4bbdfSmrgstatic void
31435c4bbdfSmrghandleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes)
31535c4bbdfSmrg{
3164642e01fSmrg    c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers,
31735c4bbdfSmrg                                                        cmodes, 1);
3184642e01fSmrg    assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS);
3194642e01fSmrg}
3204642e01fSmrg
32135c4bbdfSmrgstatic void
32235c4bbdfSmrghandleDepthModes(struct glCapabilitiesConfig *c, GLint dmodes)
32335c4bbdfSmrg{
3244642e01fSmrg    int offset = 0;
32535c4bbdfSmrg#define DEPTH(flag, value) do { \
32635c4bbdfSmrg        if (dmodes & flag) { \
32735c4bbdfSmrg            c->depth_buffers[offset++] = value; \
32835c4bbdfSmrg        } \
32935c4bbdfSmrg} while (0)
3304642e01fSmrg
3314642e01fSmrg    /*1*/
3324642e01fSmrg    DEPTH(kCGL0Bit, 0);
3334642e01fSmrg    /*2*/
3344642e01fSmrg    DEPTH(kCGL1Bit, 1);
3354642e01fSmrg    /*3*/
3364642e01fSmrg    DEPTH(kCGL2Bit, 2);
3374642e01fSmrg    /*4*/
3384642e01fSmrg    DEPTH(kCGL3Bit, 3);
3394642e01fSmrg    /*5*/
3404642e01fSmrg    DEPTH(kCGL4Bit, 4);
3414642e01fSmrg    /*6*/
3424642e01fSmrg    DEPTH(kCGL5Bit, 5);
3434642e01fSmrg    /*7*/
3444642e01fSmrg    DEPTH(kCGL6Bit, 6);
3454642e01fSmrg    /*8*/
3464642e01fSmrg    DEPTH(kCGL8Bit, 8);
3474642e01fSmrg    /*9*/
3484642e01fSmrg    DEPTH(kCGL10Bit, 10);
3494642e01fSmrg    /*10*/
3504642e01fSmrg    DEPTH(kCGL12Bit, 12);
3514642e01fSmrg    /*11*/
3524642e01fSmrg    DEPTH(kCGL16Bit, 16);
3534642e01fSmrg    /*12*/
3544642e01fSmrg    DEPTH(kCGL24Bit, 24);
3554642e01fSmrg    /*13*/
3564642e01fSmrg    DEPTH(kCGL32Bit, 32);
3574642e01fSmrg    /*14*/
3584642e01fSmrg    DEPTH(kCGL48Bit, 48);
3594642e01fSmrg    /*15*/
3604642e01fSmrg    DEPTH(kCGL64Bit, 64);
3614642e01fSmrg    /*16*/
3624642e01fSmrg    DEPTH(kCGL96Bit, 96);
3634642e01fSmrg    /*17*/
3644642e01fSmrg    DEPTH(kCGL128Bit, 128);
3654642e01fSmrg
3664642e01fSmrg#undef DEPTH
3674642e01fSmrg
3684642e01fSmrg    c->total_depth_buffer_depths = offset;
3694642e01fSmrg    assert(c->total_depth_buffer_depths < GLCAPS_DEPTH_BUFFERS);
3704642e01fSmrg}
3714642e01fSmrg
372c8548ba8Smrg/* Return non-zero if an error occurred. */
37335c4bbdfSmrgstatic CGLError
37435c4bbdfSmrghandleRendererDescriptions(CGLRendererInfoObj info, GLint r,
37535c4bbdfSmrg                           struct glCapabilitiesConfig *c)
37635c4bbdfSmrg{
3774642e01fSmrg    CGLError err;
3784642e01fSmrg    GLint accelerated = 0, flags = 0, aux = 0, samplebufs = 0, samples = 0;
3794642e01fSmrg
38035c4bbdfSmrg    err = CGLDescribeRenderer(info, r, kCGLRPAccelerated, &accelerated);
38135c4bbdfSmrg
38235c4bbdfSmrg    if (err)
38335c4bbdfSmrg        return err;
3844642e01fSmrg
3854642e01fSmrg    c->accelerated = accelerated;
3864642e01fSmrg
3874642e01fSmrg    /* Buffering modes: single/double, stereo */
3884642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags);
3894642e01fSmrg
39035c4bbdfSmrg    if (err)
39135c4bbdfSmrg        return err;
39235c4bbdfSmrg
3934642e01fSmrg    handleBufferModes(c, flags);
39435c4bbdfSmrg
3954642e01fSmrg    /* AUX buffers */
3964642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux);
3974642e01fSmrg
39835c4bbdfSmrg    if (err)
39935c4bbdfSmrg        return err;
40035c4bbdfSmrg
4014642e01fSmrg    c->aux_buffers = aux;
4024642e01fSmrg
4034642e01fSmrg    /* Depth buffer size */
4044642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPDepthModes, &flags);
4054642e01fSmrg
40635c4bbdfSmrg    if (err)
40735c4bbdfSmrg        return err;
4084642e01fSmrg
40935c4bbdfSmrg    handleDepthModes(c, flags);
4104642e01fSmrg
4114642e01fSmrg    /* Multisample buffers */
4124642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPMaxSampleBuffers, &samplebufs);
4134642e01fSmrg
41435c4bbdfSmrg    if (err)
41535c4bbdfSmrg        return err;
4164642e01fSmrg
4174642e01fSmrg    c->multisample_buffers = samplebufs;
4184642e01fSmrg
4194642e01fSmrg    /* Multisample samples per multisample buffer */
4204642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPMaxSamples, &samples);
4214642e01fSmrg
42235c4bbdfSmrg    if (err)
42335c4bbdfSmrg        return err;
4244642e01fSmrg
4254642e01fSmrg    c->multisample_samples = samples;
4264642e01fSmrg
4274642e01fSmrg    /* Stencil bit depths */
4284642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags);
4294642e01fSmrg
43035c4bbdfSmrg    if (err)
43135c4bbdfSmrg        return err;
4324642e01fSmrg
43335c4bbdfSmrg    handleStencilModes(c, flags);
4344642e01fSmrg
4354642e01fSmrg    /* Color modes (RGB/RGBA depths supported */
4364642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags);
4374642e01fSmrg
43835c4bbdfSmrg    if (err)
43935c4bbdfSmrg        return err;
44035c4bbdfSmrg
4414642e01fSmrg    handleColorModes(c, flags);
4424642e01fSmrg
4434642e01fSmrg    err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags);
4444642e01fSmrg
44535c4bbdfSmrg    if (err)
44635c4bbdfSmrg        return err;
4474642e01fSmrg
4484642e01fSmrg    handleAccumulationModes(c, flags);
44935c4bbdfSmrg
4506747b715Smrg    return kCGLNoError;
4514642e01fSmrg}
4524642e01fSmrg
45335c4bbdfSmrgstatic void
45435c4bbdfSmrginitCapabilities(struct glCapabilities *cap)
45535c4bbdfSmrg{
4564642e01fSmrg    cap->configurations = NULL;
4574642e01fSmrg    cap->total_configurations = 0;
4584642e01fSmrg}
4594642e01fSmrg
46035c4bbdfSmrgstatic void
46135c4bbdfSmrginitConfig(struct glCapabilitiesConfig *c)
46235c4bbdfSmrg{
4634642e01fSmrg    int i;
4644642e01fSmrg
4654642e01fSmrg    c->accelerated = false;
4664642e01fSmrg    c->stereo = false;
4674642e01fSmrg    c->aux_buffers = 0;
4684642e01fSmrg    c->buffers = 0;
4694642e01fSmrg
4704642e01fSmrg    c->total_depth_buffer_depths = 0;
4714642e01fSmrg
47235c4bbdfSmrg    for (i = 0; i < GLCAPS_DEPTH_BUFFERS; ++i) {
47335c4bbdfSmrg        c->depth_buffers[i] = GLCAPS_INVALID_DEPTH_VALUE;
4744642e01fSmrg    }
4754642e01fSmrg
4764642e01fSmrg    c->multisample_buffers = 0;
4774642e01fSmrg    c->multisample_samples = 0;
4784642e01fSmrg
4794642e01fSmrg    c->total_stencil_bit_depths = 0;
4804642e01fSmrg
48135c4bbdfSmrg    for (i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) {
48235c4bbdfSmrg        c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH;
4834642e01fSmrg    }
48435c4bbdfSmrg
4854642e01fSmrg    c->total_color_buffers = 0;
4864642e01fSmrg
48735c4bbdfSmrg    for (i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
48835c4bbdfSmrg        c->color_buffers[i].r = c->color_buffers[i].g =
48935c4bbdfSmrg                                    c->color_buffers[i].b =
49035c4bbdfSmrg                                        c->color_buffers[i].a =
49135c4bbdfSmrg                                            GLCAPS_COLOR_BUF_INVALID_VALUE;
49235c4bbdfSmrg        c->color_buffers[i].is_argb = false;
49335c4bbdfSmrg    }
4944642e01fSmrg
4954642e01fSmrg    c->total_accum_buffers = 0;
4964642e01fSmrg
49735c4bbdfSmrg    for (i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
49835c4bbdfSmrg        c->accum_buffers[i].r = c->accum_buffers[i].g =
49935c4bbdfSmrg                                    c->accum_buffers[i].b =
50035c4bbdfSmrg                                        c->accum_buffers[i].a =
50135c4bbdfSmrg                                            GLCAPS_COLOR_BUF_INVALID_VALUE;
50235c4bbdfSmrg        c->accum_buffers[i].is_argb = false;
5034642e01fSmrg    }
5044642e01fSmrg
5054642e01fSmrg    c->next = NULL;
5064642e01fSmrg}
5074642e01fSmrg
50835c4bbdfSmrgvoid
50935c4bbdfSmrgfreeGlCapabilities(struct glCapabilities *cap)
51035c4bbdfSmrg{
5114642e01fSmrg    struct glCapabilitiesConfig *conf, *next;
51235c4bbdfSmrg
5134642e01fSmrg    conf = cap->configurations;
5144642e01fSmrg
51535c4bbdfSmrg    while (conf) {
51635c4bbdfSmrg        next = conf->next;
51735c4bbdfSmrg        free(conf);
51835c4bbdfSmrg        conf = next;
5194642e01fSmrg    }
5204642e01fSmrg
52135c4bbdfSmrg    cap->configurations = NULL;
5224642e01fSmrg}
5234642e01fSmrg
524c8548ba8Smrg/* Return true if an error occurred. */
52535c4bbdfSmrgbool
52635c4bbdfSmrggetGlCapabilities(struct glCapabilities *cap)
52735c4bbdfSmrg{
52835c4bbdfSmrg    CGLRendererInfoObj info;
5296747b715Smrg    CGLError err;
53035c4bbdfSmrg    GLint numRenderers = 0, r;
5314642e01fSmrg
5324642e01fSmrg    initCapabilities(cap);
5334642e01fSmrg
53435c4bbdfSmrg    err = CGLQueryRendererInfo((GLuint) - 1, &info, &numRenderers);
53535c4bbdfSmrg    if (err) {
53635c4bbdfSmrg        ErrorF("CGLQueryRendererInfo error: %s\n", CGLErrorString(err));
5376747b715Smrg        return err;
53835c4bbdfSmrg    }
5394642e01fSmrg
54035c4bbdfSmrg    for (r = 0; r < numRenderers; r++) {
54135c4bbdfSmrg        struct glCapabilitiesConfig tmpconf, *conf;
5424642e01fSmrg
54335c4bbdfSmrg        initConfig(&tmpconf);
5444642e01fSmrg
54535c4bbdfSmrg        err = handleRendererDescriptions(info, r, &tmpconf);
54635c4bbdfSmrg        if (err) {
54735c4bbdfSmrg            ErrorF("handleRendererDescriptions returned error: %s\n",
54835c4bbdfSmrg                   CGLErrorString(
54935c4bbdfSmrg                       err));
55035c4bbdfSmrg            ErrorF("trying to continue...\n");
5516747b715Smrg            continue;
55235c4bbdfSmrg        }
5534642e01fSmrg
55435c4bbdfSmrg        conf = malloc(sizeof(*conf));
55535c4bbdfSmrg        if (NULL == conf) {
55635c4bbdfSmrg            FatalError("Unable to allocate memory for OpenGL capabilities\n");
55735c4bbdfSmrg        }
5584642e01fSmrg
55935c4bbdfSmrg        /* Copy the struct. */
56035c4bbdfSmrg        *conf = tmpconf;
5614642e01fSmrg
56235c4bbdfSmrg        /* Now link the configuration into the list. */
56335c4bbdfSmrg        conf->next = cap->configurations;
56435c4bbdfSmrg        cap->configurations = conf;
56535c4bbdfSmrg    }
5664642e01fSmrg
5676747b715Smrg    CGLDestroyRendererInfo(info);
5686747b715Smrg
569c8548ba8Smrg    /* No error occurred.  We are done. */
5706747b715Smrg    return kCGLNoError;
5714642e01fSmrg}
572