src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Thu, 27 Apr 2006 09:09:48 +0000
branchSDL-1.3
changeset 1656 96c2f89cc7e1
parent 1403 376665398b25
child 1662 782fd950bd46
permissions -rw-r--r--
SDL-trunk-1.3-merge-1
slouken@761
     1
/*
slouken@761
     2
    SDL - Simple DirectMedia Layer
slouken@761
     3
    Copyright (C) 1997-2003  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@857
    29
 *   http://developer.apple.com/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@857
    33
 *   http://www.libsdl.org/pipermail/sdl/2003-December/058335.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
slouken@761
    44
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
slouken@761
    51
slouken@761
    52
/* OpenGL helper functions (used internally) */
slouken@761
    53
slouken@761
    54
int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
slouken@761
    55
slouken@761
    56
    NSOpenGLPixelFormatAttribute attr[32];
slouken@761
    57
    NSOpenGLPixelFormat *fmt;
slouken@761
    58
    int i = 0;
slouken@761
    59
    int colorBits = bpp;
slouken@761
    60
icculus@1195
    61
    /* if a GL library hasn't been loaded at this point, load the default. */
icculus@1195
    62
    if (!this->gl_config.driver_loaded) {
icculus@1195
    63
        if (QZ_GL_LoadLibrary(this, NULL) == -1)
icculus@1195
    64
            return 0;
icculus@1195
    65
    }
icculus@1195
    66
slouken@761
    67
    if ( flags & SDL_FULLSCREEN ) {
slouken@761
    68
slouken@761
    69
        attr[i++] = NSOpenGLPFAFullScreen;
slouken@761
    70
    }
slouken@761
    71
    /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
slouken@761
    72
    else if ( colorBits != device_bpp ) {
slouken@761
    73
slouken@761
    74
        colorBits = device_bpp;
slouken@761
    75
    }
slouken@761
    76
slouken@761
    77
    attr[i++] = NSOpenGLPFAColorSize;
slouken@761
    78
    attr[i++] = colorBits;
slouken@761
    79
slouken@761
    80
    attr[i++] = NSOpenGLPFADepthSize;
slouken@761
    81
    attr[i++] = this->gl_config.depth_size;
slouken@761
    82
slouken@761
    83
    if ( this->gl_config.double_buffer ) {
slouken@761
    84
        attr[i++] = NSOpenGLPFADoubleBuffer;
slouken@761
    85
    }
slouken@761
    86
slouken@761
    87
    if ( this->gl_config.stereo ) {
slouken@761
    88
        attr[i++] = NSOpenGLPFAStereo;
slouken@761
    89
    }
slouken@761
    90
slouken@761
    91
    if ( this->gl_config.stencil_size != 0 ) {
slouken@761
    92
        attr[i++] = NSOpenGLPFAStencilSize;
slouken@761
    93
        attr[i++] = this->gl_config.stencil_size;
slouken@761
    94
    }
slouken@761
    95
slouken@890
    96
    if ( (this->gl_config.accum_red_size +
slouken@890
    97
          this->gl_config.accum_green_size +
slouken@890
    98
          this->gl_config.accum_blue_size +
slouken@890
    99
          this->gl_config.accum_alpha_size) > 0 ) {
slouken@890
   100
        attr[i++] = NSOpenGLPFAAccumSize;
slouken@890
   101
        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
   102
    }
slouken@890
   103
slouken@761
   104
    if ( this->gl_config.multisamplebuffers != 0 ) {
slouken@761
   105
        attr[i++] = NSOpenGLPFASampleBuffers;
slouken@761
   106
        attr[i++] = this->gl_config.multisamplebuffers;
slouken@761
   107
    }
slouken@761
   108
slouken@761
   109
    if ( this->gl_config.multisamplesamples != 0 ) {
slouken@761
   110
        attr[i++] = NSOpenGLPFASamples;
slouken@761
   111
        attr[i++] = this->gl_config.multisamplesamples;
slouken@900
   112
        attr[i++] = NSOpenGLPFANoRecovery;
slouken@761
   113
    }
slouken@761
   114
slouken@1656
   115
    if ( this->gl_config.accelerated > 0 ) {
slouken@1656
   116
        attr[i++] = NSOpenGLPFAAccelerated;
slouken@1656
   117
    }
slouken@1656
   118
slouken@761
   119
    attr[i++] = NSOpenGLPFAScreenMask;
slouken@761
   120
    attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
slouken@761
   121
    attr[i] = 0;
slouken@761
   122
slouken@761
   123
    fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
slouken@761
   124
    if (fmt == nil) {
slouken@761
   125
        SDL_SetError ("Failed creating OpenGL pixel format");
slouken@761
   126
        return 0;
slouken@761
   127
    }
slouken@761
   128
slouken@761
   129
    gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
slouken@761
   130
                                               shareContext:nil];
slouken@761
   131
icculus@1160
   132
    [ fmt release ];
icculus@1160
   133
slouken@761
   134
    if (gl_context == nil) {
slouken@761
   135
        SDL_SetError ("Failed creating OpenGL context");
slouken@761
   136
        return 0;
slouken@761
   137
    }
slouken@761
   138
slouken@1656
   139
    /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
slouken@1656
   140
     * (Apple's documentation is not completely clear about what this setting
slouken@1656
   141
     * exactly does, IMHO - for a detailed explanation see
slouken@1656
   142
     * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
slouken@1656
   143
     */
slouken@1656
   144
    if ( this->gl_config.swap_control >= 0 ) {
slouken@1656
   145
        long value;
slouken@1656
   146
        value = this->gl_config.swap_control;
slouken@1656
   147
        [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
slouken@1656
   148
    }
slouken@1656
   149
slouken@761
   150
    /*
slouken@761
   151
     * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
slouken@761
   152
     *  "You are blowing a couple of the internal OpenGL function caches. This
slouken@761
   153
     *  appears to be happening in the VAO case.  You can tell OpenGL to up
slouken@761
   154
     *  the cache size by issuing the following calls right after you create
slouken@761
   155
     *  the OpenGL context.  The default cache size is 16."    --ryan.
slouken@761
   156
     */
slouken@761
   157
slouken@761
   158
    #ifndef GLI_ARRAY_FUNC_CACHE_MAX
slouken@761
   159
    #define GLI_ARRAY_FUNC_CACHE_MAX 284
slouken@761
   160
    #endif
slouken@761
   161
slouken@761
   162
    #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
slouken@761
   163
    #define GLI_SUBMIT_FUNC_CACHE_MAX 280
slouken@761
   164
    #endif
slouken@761
   165
slouken@761
   166
    {
slouken@761
   167
        long cache_max = 64;
slouken@761
   168
        CGLContextObj ctx = [ gl_context cglContext ];
slouken@761
   169
        CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
slouken@761
   170
        CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
slouken@761
   171
    }
slouken@761
   172
slouken@761
   173
    /* End Wisdom from Apple Engineer section. --ryan. */
slouken@761
   174
slouken@761
   175
    return 1;
slouken@761
   176
}
slouken@761
   177
slouken@761
   178
void QZ_TearDownOpenGL (_THIS) {
slouken@761
   179
slouken@761
   180
    [ NSOpenGLContext clearCurrentContext ];
slouken@761
   181
    [ gl_context clearDrawable ];
slouken@761
   182
    [ gl_context release ];
slouken@761
   183
}
slouken@761
   184
slouken@761
   185
slouken@761
   186
/* SDL OpenGL functions */
icculus@1189
   187
static const char *DEFAULT_OPENGL_LIB_NAME =
icculus@1189
   188
    "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
slouken@761
   189
slouken@761
   190
int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
icculus@1181
   191
    if ( gl_context != NULL ) {
icculus@1181
   192
        SDL_SetError("OpenGL context already created");
icculus@1181
   193
        return -1;
icculus@1181
   194
    }
icculus@1181
   195
icculus@1189
   196
    if (opengl_library != NULL)
icculus@1189
   197
        SDL_UnloadObject(opengl_library);
icculus@1181
   198
icculus@1181
   199
    if (location == NULL)
icculus@1189
   200
        location = DEFAULT_OPENGL_LIB_NAME;
icculus@1181
   201
icculus@1189
   202
    opengl_library = SDL_LoadObject(location);
icculus@1189
   203
    if (opengl_library != NULL) {
icculus@1181
   204
        this->gl_config.driver_loaded = 1;
icculus@1181
   205
        return 0;
icculus@1181
   206
    }
icculus@1181
   207
icculus@1189
   208
    this->gl_config.driver_loaded = 0;
icculus@1181
   209
    return -1;
slouken@761
   210
}
slouken@761
   211
slouken@761
   212
void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
icculus@1189
   213
    return SDL_LoadFunction(opengl_library, proc);
slouken@761
   214
}
slouken@761
   215
slouken@761
   216
int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
slouken@761
   217
slouken@761
   218
    GLenum attr = 0;
slouken@761
   219
slouken@761
   220
    QZ_GL_MakeCurrent (this);
slouken@761
   221
slouken@761
   222
    switch (attrib) {
slouken@761
   223
        case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
slouken@761
   224
        case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
slouken@761
   225
        case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
slouken@761
   226
        case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
slouken@761
   227
        case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
slouken@761
   228
        case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
slouken@761
   229
        case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
slouken@761
   230
        case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
slouken@761
   231
        case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
slouken@761
   232
        case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
slouken@761
   233
        case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
slouken@761
   234
        case SDL_GL_STEREO: attr = GL_STEREO; break;
slouken@761
   235
        case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
slouken@761
   236
        case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
slouken@761
   237
        case SDL_GL_BUFFER_SIZE:
slouken@761
   238
        {
slouken@761
   239
            GLint bits = 0;
slouken@761
   240
            GLint component;
slouken@761
   241
slouken@761
   242
            /* there doesn't seem to be a single flag in OpenGL for this! */
slouken@761
   243
            glGetIntegerv (GL_RED_BITS, &component);   bits += component;
slouken@761
   244
            glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
slouken@761
   245
            glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
slouken@761
   246
            glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
slouken@761
   247
slouken@761
   248
            *value = bits;
slouken@1656
   249
            return 0;
slouken@761
   250
        }
slouken@1656
   251
        case SDL_GL_ACCELERATED_VISUAL:
slouken@1656
   252
        {
slouken@1656
   253
            long val;
slouken@1656
   254
	    /* FIXME: How do we get this information here?
slouken@1656
   255
            [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
slouken@1656
   256
	    */
slouken@1656
   257
	    val = (this->gl_config.accelerated != 0);;
slouken@1656
   258
            *value = val;
slouken@1656
   259
            return 0;
slouken@1656
   260
        }
slouken@1656
   261
        case SDL_GL_SWAP_CONTROL:
slouken@1656
   262
        {
slouken@1656
   263
            long val;
slouken@1656
   264
            [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
slouken@1656
   265
            *value = val;
slouken@1656
   266
            return 0;
slouken@1656
   267
        }
slouken@761
   268
    }
slouken@761
   269
slouken@761
   270
    glGetIntegerv (attr, (GLint *)value);
slouken@761
   271
    return 0;
slouken@761
   272
}
slouken@761
   273
slouken@761
   274
int    QZ_GL_MakeCurrent    (_THIS) {
slouken@761
   275
    [ gl_context makeCurrentContext ];
slouken@761
   276
    return 0;
slouken@761
   277
}
slouken@761
   278
slouken@761
   279
void   QZ_GL_SwapBuffers    (_THIS) {
slouken@761
   280
    [ gl_context flushBuffer ];
slouken@761
   281
}