src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Sun, 04 Jan 2004 14:55:35 +0000
changeset 761 c5b2b6d2d1fe
child 770 ac44ddb84f6f
permissions -rw-r--r--
Date: Wed, 31 Dec 2003 21:55:30 +0100
From: Max Horn
Subject: SDL: video/quartz cleanup

while doing some experimental changes in the quartz code, I was annoyed
by having to recompile that one big .o file over and over again. So I
decided to finally realize one TODO: properly splitting the code over
multiple files :-).

With two exceptions, I didn't make code changes, only rearranged files
and added new headers. Since there are several new files, making a
patch didn't work out so well, so I decided to just send you all the
new & modified files.

The one source change I made is related to showing/hiding the mouse. I
renamed cursor_visible to cursor_should_be_visible and cursor_hidden to
cursor_visible; I think that makes reading the code easier.
Then I added two new functions: QZ_ShowMouse and QZ_HideMouse. They
help manage cursor_visible (the former 'cursor_hidden'). Finally I
replaced the Carbon ShowCursor/HiderCuror calls by [NSCursor hide] and
[NSCursor unhide]. The API docs are not conclusive, but it might be
that with those the "cursor_visible" (former 'cursor_hidden') hack may
not be necessary anymore; however so far I didn't test this hypothesis,
so I left that in.

The other change was to remove in_foreground and use [NSApp isActive]
instead: Manually keeping track of whether we are in the foreground is
error prone. This should work better in some corner cases.
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@761
    22
slouken@761
    23
#include "SDL_QuartzVideo.h"
slouken@761
    24
slouken@761
    25
/* 
slouken@761
    26
    This is a workaround to directly access NSOpenGLContext's CGL context
slouken@761
    27
    We need this to check for errors NSOpenGLContext doesn't support
slouken@761
    28
*/
slouken@761
    29
@interface NSOpenGLContext (CGLContextAccess)
slouken@761
    30
- (CGLContextObj) cglContext;
slouken@761
    31
@end
slouken@761
    32
slouken@761
    33
@implementation NSOpenGLContext (CGLContextAccess)
slouken@761
    34
- (CGLContextObj) cglContext;
slouken@761
    35
{
slouken@761
    36
    return _contextAuxiliary;
slouken@761
    37
}
slouken@761
    38
@end
slouken@761
    39
slouken@761
    40
/* OpenGL helper functions (used internally) */
slouken@761
    41
slouken@761
    42
int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
slouken@761
    43
slouken@761
    44
    NSOpenGLPixelFormatAttribute attr[32];
slouken@761
    45
    NSOpenGLPixelFormat *fmt;
slouken@761
    46
    int i = 0;
slouken@761
    47
    int colorBits = bpp;
slouken@761
    48
slouken@761
    49
    if ( flags & SDL_FULLSCREEN ) {
slouken@761
    50
slouken@761
    51
        attr[i++] = NSOpenGLPFAFullScreen;
slouken@761
    52
    }
slouken@761
    53
    /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
slouken@761
    54
    else if ( colorBits != device_bpp ) {
slouken@761
    55
slouken@761
    56
        colorBits = device_bpp;
slouken@761
    57
    }
slouken@761
    58
slouken@761
    59
    attr[i++] = NSOpenGLPFAColorSize;
slouken@761
    60
    attr[i++] = colorBits;
slouken@761
    61
slouken@761
    62
    attr[i++] = NSOpenGLPFADepthSize;
slouken@761
    63
    attr[i++] = this->gl_config.depth_size;
slouken@761
    64
slouken@761
    65
    if ( this->gl_config.double_buffer ) {
slouken@761
    66
        attr[i++] = NSOpenGLPFADoubleBuffer;
slouken@761
    67
    }
slouken@761
    68
slouken@761
    69
    if ( this->gl_config.stereo ) {
slouken@761
    70
        attr[i++] = NSOpenGLPFAStereo;
slouken@761
    71
    }
slouken@761
    72
slouken@761
    73
    if ( this->gl_config.stencil_size != 0 ) {
slouken@761
    74
        attr[i++] = NSOpenGLPFAStencilSize;
slouken@761
    75
        attr[i++] = this->gl_config.stencil_size;
slouken@761
    76
    }
slouken@761
    77
slouken@761
    78
#if NSOPENGL_CURRENT_VERSION > 1  /* What version should this be? */
slouken@761
    79
    if ( this->gl_config.multisamplebuffers != 0 ) {
slouken@761
    80
        attr[i++] = NSOpenGLPFASampleBuffers;
slouken@761
    81
        attr[i++] = this->gl_config.multisamplebuffers;
slouken@761
    82
    }
slouken@761
    83
slouken@761
    84
    if ( this->gl_config.multisamplesamples != 0 ) {
slouken@761
    85
        attr[i++] = NSOpenGLPFASamples;
slouken@761
    86
        attr[i++] = this->gl_config.multisamplesamples;
slouken@761
    87
    }
slouken@761
    88
#endif
slouken@761
    89
slouken@761
    90
    attr[i++] = NSOpenGLPFAScreenMask;
slouken@761
    91
    attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
slouken@761
    92
    attr[i] = 0;
slouken@761
    93
slouken@761
    94
    fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
slouken@761
    95
    if (fmt == nil) {
slouken@761
    96
        SDL_SetError ("Failed creating OpenGL pixel format");
slouken@761
    97
        return 0;
slouken@761
    98
    }
slouken@761
    99
slouken@761
   100
    gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
slouken@761
   101
                                               shareContext:nil];
slouken@761
   102
slouken@761
   103
    if (gl_context == nil) {
slouken@761
   104
        SDL_SetError ("Failed creating OpenGL context");
slouken@761
   105
        return 0;
slouken@761
   106
    }
slouken@761
   107
slouken@761
   108
    /*
slouken@761
   109
     * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
slouken@761
   110
     *  "You are blowing a couple of the internal OpenGL function caches. This
slouken@761
   111
     *  appears to be happening in the VAO case.  You can tell OpenGL to up
slouken@761
   112
     *  the cache size by issuing the following calls right after you create
slouken@761
   113
     *  the OpenGL context.  The default cache size is 16."    --ryan.
slouken@761
   114
     */
slouken@761
   115
slouken@761
   116
    #ifndef GLI_ARRAY_FUNC_CACHE_MAX
slouken@761
   117
    #define GLI_ARRAY_FUNC_CACHE_MAX 284
slouken@761
   118
    #endif
slouken@761
   119
slouken@761
   120
    #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
slouken@761
   121
    #define GLI_SUBMIT_FUNC_CACHE_MAX 280
slouken@761
   122
    #endif
slouken@761
   123
slouken@761
   124
    {
slouken@761
   125
        long cache_max = 64;
slouken@761
   126
        CGLContextObj ctx = [ gl_context cglContext ];
slouken@761
   127
        CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
slouken@761
   128
        CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
slouken@761
   129
    }
slouken@761
   130
slouken@761
   131
    /* End Wisdom from Apple Engineer section. --ryan. */
slouken@761
   132
slouken@761
   133
    /* Convince SDL that the GL "driver" is loaded */
slouken@761
   134
    this->gl_config.driver_loaded = 1;
slouken@761
   135
slouken@761
   136
    [ fmt release ];
slouken@761
   137
slouken@761
   138
    return 1;
slouken@761
   139
}
slouken@761
   140
slouken@761
   141
void QZ_TearDownOpenGL (_THIS) {
slouken@761
   142
slouken@761
   143
    [ NSOpenGLContext clearCurrentContext ];
slouken@761
   144
    [ gl_context clearDrawable ];
slouken@761
   145
    [ gl_context release ];
slouken@761
   146
}
slouken@761
   147
slouken@761
   148
slouken@761
   149
/* SDL OpenGL functions */
slouken@761
   150
slouken@761
   151
int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
slouken@761
   152
    this->gl_config.driver_loaded = 1;
slouken@761
   153
    return 1;
slouken@761
   154
}
slouken@761
   155
slouken@761
   156
void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
slouken@761
   157
slouken@761
   158
    /* We may want to cache the bundleRef at some point */
slouken@761
   159
    CFBundleRef bundle;
slouken@761
   160
    CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
slouken@761
   161
                                                        CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
slouken@761
   162
slouken@761
   163
    CFStringRef functionName = CFStringCreateWithCString
slouken@761
   164
        (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
slouken@761
   165
slouken@761
   166
    void *function;
slouken@761
   167
slouken@761
   168
    bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
slouken@761
   169
    assert (bundle != NULL);
slouken@761
   170
slouken@761
   171
    function = CFBundleGetFunctionPointerForName (bundle, functionName);
slouken@761
   172
slouken@761
   173
    CFRelease ( bundleURL );
slouken@761
   174
    CFRelease ( functionName );
slouken@761
   175
    CFRelease ( bundle );
slouken@761
   176
slouken@761
   177
    return function;
slouken@761
   178
}
slouken@761
   179
slouken@761
   180
int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
slouken@761
   181
slouken@761
   182
    GLenum attr = 0;
slouken@761
   183
slouken@761
   184
    QZ_GL_MakeCurrent (this);
slouken@761
   185
slouken@761
   186
    switch (attrib) {
slouken@761
   187
        case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
slouken@761
   188
        case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
slouken@761
   189
        case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
slouken@761
   190
        case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
slouken@761
   191
        case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
slouken@761
   192
        case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
slouken@761
   193
        case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
slouken@761
   194
        case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
slouken@761
   195
        case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
slouken@761
   196
        case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
slouken@761
   197
        case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
slouken@761
   198
        case SDL_GL_STEREO: attr = GL_STEREO; break;
slouken@761
   199
        case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
slouken@761
   200
        case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
slouken@761
   201
        case SDL_GL_BUFFER_SIZE:
slouken@761
   202
        {
slouken@761
   203
            GLint bits = 0;
slouken@761
   204
            GLint component;
slouken@761
   205
slouken@761
   206
            /* there doesn't seem to be a single flag in OpenGL for this! */
slouken@761
   207
            glGetIntegerv (GL_RED_BITS, &component);   bits += component;
slouken@761
   208
            glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
slouken@761
   209
            glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
slouken@761
   210
            glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
slouken@761
   211
slouken@761
   212
            *value = bits;
slouken@761
   213
        }
slouken@761
   214
        return 0;
slouken@761
   215
    }
slouken@761
   216
slouken@761
   217
    glGetIntegerv (attr, (GLint *)value);
slouken@761
   218
    return 0;
slouken@761
   219
}
slouken@761
   220
slouken@761
   221
int    QZ_GL_MakeCurrent    (_THIS) {
slouken@761
   222
    [ gl_context makeCurrentContext ];
slouken@761
   223
    return 0;
slouken@761
   224
}
slouken@761
   225
slouken@761
   226
void   QZ_GL_SwapBuffers    (_THIS) {
slouken@761
   227
    [ gl_context flushBuffer ];
slouken@761
   228
}