src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1656 96c2f89cc7e1
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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