src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Thu, 22 Oct 2009 04:53:44 +0000
branchSDL-1.2
changeset 4370 8d67936e32ec
parent 4204 976bc19f8f6b
child 6137 4720145f848b
permissions -rw-r--r--
C.W. Betts 2009-10-20 09:58:56 PDT

The compiler complains that long is an incompatible pointer type for
[gl_context setValues: forParameter:] and CGLSetParameter. This only shows up
on x86_64, but it still might be an issue.
slouken@761
     1
/*
slouken@761
     2
    SDL - Simple DirectMedia Layer
slouken@4159
     3
    Copyright (C) 1997-2009  Sam Lantinga
slouken@761
     4
slouken@761
     5
    This library is free software; you can redistribute it and/or
slouken@761
     6
    modify it under the terms of the GNU Library General Public
slouken@761
     7
    License as published by the Free Software Foundation; either
slouken@761
     8
    version 2 of the License, or (at your option) any later version.
slouken@761
     9
slouken@761
    10
    This library is distributed in the hope that it will be useful,
slouken@761
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@761
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@761
    13
    Library General Public License for more details.
slouken@761
    14
slouken@761
    15
    You should have received a copy of the GNU Library General Public
slouken@761
    16
    License along with this library; if not, write to the Free
slouken@761
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@761
    18
slouken@761
    19
    Sam Lantinga
slouken@761
    20
    slouken@libsdl.org
slouken@761
    21
*/
slouken@1403
    22
#include "SDL_config.h"
slouken@761
    23
slouken@761
    24
#include "SDL_QuartzVideo.h"
slouken@761
    25
icculus@857
    26
/*
icculus@857
    27
 * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple:
icculus@857
    28
 *
icculus@4188
    29
 *   http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample
icculus@857
    30
 *
icculus@857
    31
 *  ...but it isn't in the system headers, according to Sam:
icculus@857
    32
 *
icculus@4188
    33
 *   http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html
icculus@857
    34
 *
icculus@857
    35
 * These are normally enums and not #defines in the system headers.
icculus@857
    36
 *
icculus@857
    37
 *   --ryan.
icculus@857
    38
 */
icculus@857
    39
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020)
icculus@857
    40
#define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55)
icculus@857
    41
#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
icculus@857
    42
#endif
icculus@857
    43
icculus@4204
    44
#ifdef __powerpc__   /* we lost this in 10.6, which has no PPC support. */
slouken@761
    45
@implementation NSOpenGLContext (CGLContextAccess)
slouken@761
    46
- (CGLContextObj) cglContext;
slouken@761
    47
{
slouken@761
    48
    return _contextAuxiliary;
slouken@761
    49
}
slouken@761
    50
@end
icculus@4204
    51
CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
icculus@4204
    52
{
icculus@4204
    53
    return [nsctx cglContext];
icculus@4204
    54
}
icculus@4204
    55
#else
icculus@4204
    56
CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
icculus@4204
    57
{
icculus@4204
    58
    return (CGLContextObj) [nsctx CGLContextObj];
icculus@4204
    59
}
icculus@4204
    60
#endif
icculus@4204
    61
slouken@761
    62
slouken@761
    63
/* OpenGL helper functions (used internally) */
slouken@761
    64
slouken@761
    65
int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
slouken@761
    66
slouken@761
    67
    NSOpenGLPixelFormatAttribute attr[32];
slouken@761
    68
    NSOpenGLPixelFormat *fmt;
slouken@761
    69
    int i = 0;
slouken@761
    70
    int colorBits = bpp;
slouken@761
    71
icculus@1195
    72
    /* if a GL library hasn't been loaded at this point, load the default. */
icculus@1195
    73
    if (!this->gl_config.driver_loaded) {
icculus@1195
    74
        if (QZ_GL_LoadLibrary(this, NULL) == -1)
icculus@1195
    75
            return 0;
icculus@1195
    76
    }
icculus@1195
    77
slouken@761
    78
    if ( flags & SDL_FULLSCREEN ) {
slouken@761
    79
slouken@761
    80
        attr[i++] = NSOpenGLPFAFullScreen;
slouken@761
    81
    }
slouken@761
    82
    /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
slouken@761
    83
    else if ( colorBits != device_bpp ) {
slouken@761
    84
slouken@761
    85
        colorBits = device_bpp;
slouken@761
    86
    }
slouken@761
    87
slouken@761
    88
    attr[i++] = NSOpenGLPFAColorSize;
slouken@761
    89
    attr[i++] = colorBits;
slouken@761
    90
slouken@761
    91
    attr[i++] = NSOpenGLPFADepthSize;
slouken@761
    92
    attr[i++] = this->gl_config.depth_size;
slouken@761
    93
slouken@761
    94
    if ( this->gl_config.double_buffer ) {
slouken@761
    95
        attr[i++] = NSOpenGLPFADoubleBuffer;
slouken@761
    96
    }
slouken@761
    97
slouken@761
    98
    if ( this->gl_config.stereo ) {
slouken@761
    99
        attr[i++] = NSOpenGLPFAStereo;
slouken@761
   100
    }
slouken@761
   101
slouken@761
   102
    if ( this->gl_config.stencil_size != 0 ) {
slouken@761
   103
        attr[i++] = NSOpenGLPFAStencilSize;
slouken@761
   104
        attr[i++] = this->gl_config.stencil_size;
slouken@761
   105
    }
slouken@761
   106
slouken@890
   107
    if ( (this->gl_config.accum_red_size +
slouken@890
   108
          this->gl_config.accum_green_size +
slouken@890
   109
          this->gl_config.accum_blue_size +
slouken@890
   110
          this->gl_config.accum_alpha_size) > 0 ) {
slouken@890
   111
        attr[i++] = NSOpenGLPFAAccumSize;
slouken@890
   112
        attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size;
slouken@890
   113
    }
slouken@890
   114
slouken@761
   115
    if ( this->gl_config.multisamplebuffers != 0 ) {
slouken@761
   116
        attr[i++] = NSOpenGLPFASampleBuffers;
slouken@761
   117
        attr[i++] = this->gl_config.multisamplebuffers;
slouken@761
   118
    }
slouken@761
   119
slouken@761
   120
    if ( this->gl_config.multisamplesamples != 0 ) {
slouken@761
   121
        attr[i++] = NSOpenGLPFASamples;
slouken@761
   122
        attr[i++] = this->gl_config.multisamplesamples;
slouken@900
   123
        attr[i++] = NSOpenGLPFANoRecovery;
slouken@761
   124
    }
slouken@761
   125
slouken@1737
   126
    if ( this->gl_config.accelerated > 0 ) {
slouken@1737
   127
        attr[i++] = NSOpenGLPFAAccelerated;
slouken@1737
   128
    }
slouken@1737
   129
slouken@761
   130
    attr[i++] = NSOpenGLPFAScreenMask;
slouken@761
   131
    attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
slouken@761
   132
    attr[i] = 0;
slouken@761
   133
slouken@761
   134
    fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
slouken@761
   135
    if (fmt == nil) {
slouken@761
   136
        SDL_SetError ("Failed creating OpenGL pixel format");
slouken@761
   137
        return 0;
slouken@761
   138
    }
slouken@761
   139
slouken@761
   140
    gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
slouken@761
   141
                                               shareContext:nil];
slouken@761
   142
icculus@1160
   143
    [ fmt release ];
icculus@1160
   144
slouken@761
   145
    if (gl_context == nil) {
slouken@761
   146
        SDL_SetError ("Failed creating OpenGL context");
slouken@761
   147
        return 0;
slouken@761
   148
    }
slouken@761
   149
slouken@1736
   150
    /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
slouken@1736
   151
     * (Apple's documentation is not completely clear about what this setting
slouken@1736
   152
     * exactly does, IMHO - for a detailed explanation see
slouken@1736
   153
     * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
slouken@1736
   154
     */
slouken@1736
   155
    if ( this->gl_config.swap_control >= 0 ) {
slouken@4370
   156
        GLint value;
slouken@1736
   157
        value = this->gl_config.swap_control;
slouken@1736
   158
        [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
slouken@1736
   159
    }
slouken@1736
   160
slouken@761
   161
    /*
slouken@761
   162
     * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
slouken@761
   163
     *  "You are blowing a couple of the internal OpenGL function caches. This
slouken@761
   164
     *  appears to be happening in the VAO case.  You can tell OpenGL to up
slouken@761
   165
     *  the cache size by issuing the following calls right after you create
slouken@761
   166
     *  the OpenGL context.  The default cache size is 16."    --ryan.
slouken@761
   167
     */
slouken@761
   168
slouken@761
   169
    #ifndef GLI_ARRAY_FUNC_CACHE_MAX
slouken@761
   170
    #define GLI_ARRAY_FUNC_CACHE_MAX 284
slouken@761
   171
    #endif
slouken@761
   172
slouken@761
   173
    #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
slouken@761
   174
    #define GLI_SUBMIT_FUNC_CACHE_MAX 280
slouken@761
   175
    #endif
slouken@761
   176
slouken@761
   177
    {
slouken@4370
   178
        GLint cache_max = 64;
icculus@4204
   179
        CGLContextObj ctx = QZ_GetCGLContextObj(gl_context);
slouken@761
   180
        CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
slouken@761
   181
        CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
slouken@761
   182
    }
slouken@761
   183
slouken@761
   184
    /* End Wisdom from Apple Engineer section. --ryan. */
slouken@761
   185
slouken@761
   186
    return 1;
slouken@761
   187
}
slouken@761
   188
slouken@761
   189
void QZ_TearDownOpenGL (_THIS) {
slouken@761
   190
slouken@761
   191
    [ NSOpenGLContext clearCurrentContext ];
slouken@761
   192
    [ gl_context clearDrawable ];
slouken@761
   193
    [ gl_context release ];
slouken@761
   194
}
slouken@761
   195
slouken@761
   196
slouken@761
   197
/* SDL OpenGL functions */
icculus@1189
   198
static const char *DEFAULT_OPENGL_LIB_NAME =
icculus@1189
   199
    "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
slouken@761
   200
slouken@761
   201
int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
icculus@1181
   202
    if ( gl_context != NULL ) {
icculus@1181
   203
        SDL_SetError("OpenGL context already created");
icculus@1181
   204
        return -1;
icculus@1181
   205
    }
icculus@1181
   206
icculus@1189
   207
    if (opengl_library != NULL)
icculus@1189
   208
        SDL_UnloadObject(opengl_library);
icculus@1181
   209
icculus@1181
   210
    if (location == NULL)
icculus@1189
   211
        location = DEFAULT_OPENGL_LIB_NAME;
icculus@1181
   212
icculus@1189
   213
    opengl_library = SDL_LoadObject(location);
icculus@1189
   214
    if (opengl_library != NULL) {
icculus@1181
   215
        this->gl_config.driver_loaded = 1;
icculus@1181
   216
        return 0;
icculus@1181
   217
    }
icculus@1181
   218
icculus@1189
   219
    this->gl_config.driver_loaded = 0;
icculus@1181
   220
    return -1;
slouken@761
   221
}
slouken@761
   222
slouken@761
   223
void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
icculus@1189
   224
    return SDL_LoadFunction(opengl_library, proc);
slouken@761
   225
}
slouken@761
   226
slouken@761
   227
int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
slouken@761
   228
slouken@761
   229
    GLenum attr = 0;
slouken@761
   230
slouken@761
   231
    QZ_GL_MakeCurrent (this);
slouken@761
   232
slouken@761
   233
    switch (attrib) {
slouken@761
   234
        case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
slouken@761
   235
        case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
slouken@761
   236
        case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
slouken@761
   237
        case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
slouken@761
   238
        case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
slouken@761
   239
        case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
slouken@761
   240
        case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
slouken@761
   241
        case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
slouken@761
   242
        case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
slouken@761
   243
        case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
slouken@761
   244
        case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
slouken@761
   245
        case SDL_GL_STEREO: attr = GL_STEREO; break;
slouken@761
   246
        case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
slouken@761
   247
        case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
slouken@761
   248
        case SDL_GL_BUFFER_SIZE:
slouken@761
   249
        {
slouken@761
   250
            GLint bits = 0;
slouken@761
   251
            GLint component;
slouken@761
   252
slouken@761
   253
            /* there doesn't seem to be a single flag in OpenGL for this! */
slouken@761
   254
            glGetIntegerv (GL_RED_BITS, &component);   bits += component;
slouken@761
   255
            glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
slouken@761
   256
            glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
slouken@761
   257
            glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
slouken@761
   258
slouken@761
   259
            *value = bits;
slouken@1737
   260
            return 0;
slouken@761
   261
        }
slouken@1737
   262
        case SDL_GL_ACCELERATED_VISUAL:
slouken@1737
   263
        {
slouken@4370
   264
            GLint val;
slouken@1738
   265
	    /* FIXME: How do we get this information here?
slouken@1737
   266
            [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
slouken@1738
   267
	    */
slouken@1738
   268
	    val = (this->gl_config.accelerated != 0);;
slouken@1737
   269
            *value = val;
slouken@1737
   270
            return 0;
slouken@1737
   271
        }
slouken@1737
   272
        case SDL_GL_SWAP_CONTROL:
slouken@1737
   273
        {
slouken@4370
   274
            GLint val;
slouken@1737
   275
            [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
slouken@1737
   276
            *value = val;
slouken@1737
   277
            return 0;
slouken@1737
   278
        }
slouken@761
   279
    }
slouken@761
   280
slouken@761
   281
    glGetIntegerv (attr, (GLint *)value);
slouken@761
   282
    return 0;
slouken@761
   283
}
slouken@761
   284
slouken@761
   285
int    QZ_GL_MakeCurrent    (_THIS) {
slouken@761
   286
    [ gl_context makeCurrentContext ];
slouken@761
   287
    return 0;
slouken@761
   288
}
slouken@761
   289
slouken@761
   290
void   QZ_GL_SwapBuffers    (_THIS) {
slouken@761
   291
    [ gl_context flushBuffer ];
slouken@761
   292
}