src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 00:25:44 -0800
changeset 5249 7a963be087ef
parent 5246 58265e606e4e
child 5262 b530ef003506
permissions -rw-r--r--
Mostly fixed fullscreen mode on Mac OS X, and you can toggle it on and off.

There are still some problems with the ConvertNSRect() calculations when switching video modes, which causes wierd window positioning issues, and the fullscreen window is still minimized on exit.
slouken@1936
     1
/*
slouken@1936
     2
    SDL - Simple DirectMedia Layer
slouken@4498
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1936
     4
slouken@1936
     5
    This library is free software; you can redistribute it and/or
slouken@1936
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1936
     7
    License as published by the Free Software Foundation; either
slouken@1936
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1936
     9
slouken@1936
    10
    This library is distributed in the hope that it will be useful,
slouken@1936
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1936
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1936
    13
    Lesser General Public License for more details.
slouken@1936
    14
slouken@1936
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1936
    16
    License along with this library; if not, write to the Free Software
slouken@1936
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1936
    18
slouken@1936
    19
    Sam Lantinga
slouken@1936
    20
    slouken@libsdl.org
slouken@1936
    21
*/
slouken@1936
    22
#include "SDL_config.h"
slouken@1936
    23
slouken@1936
    24
#include "SDL_cocoavideo.h"
slouken@1936
    25
slouken@1936
    26
/* NSOpenGL implementation of SDL OpenGL support */
slouken@1936
    27
slouken@1952
    28
#if SDL_VIDEO_OPENGL_CGL
slouken@1936
    29
#include <OpenGL/CGLTypes.h>
slouken@2738
    30
#include <OpenGL/OpenGL.h>
slouken@3570
    31
#include <OpenGL/CGLRenderers.h>
slouken@1936
    32
slouken@1936
    33
#include "SDL_loadso.h"
slouken@1936
    34
#include "SDL_opengl.h"
slouken@1936
    35
slouken@1936
    36
slouken@1952
    37
#define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
slouken@1936
    38
slouken@1936
    39
int
slouken@1936
    40
Cocoa_GL_LoadLibrary(_THIS, const char *path)
slouken@1936
    41
{
slouken@3057
    42
    /* Load the OpenGL library */
slouken@1936
    43
    if (path == NULL) {
slouken@1952
    44
        path = SDL_getenv("SDL_OPENGL_LIBRARY");
slouken@1952
    45
    }
slouken@1952
    46
    if (path == NULL) {
slouken@1952
    47
        path = DEFAULT_OPENGL;
slouken@1936
    48
    }
slouken@1936
    49
    _this->gl_config.dll_handle = SDL_LoadObject(path);
slouken@1936
    50
    if (!_this->gl_config.dll_handle) {
slouken@1936
    51
        return -1;
slouken@1936
    52
    }
slouken@1936
    53
    SDL_strlcpy(_this->gl_config.driver_path, path,
slouken@1936
    54
                SDL_arraysize(_this->gl_config.driver_path));
slouken@1936
    55
    return 0;
slouken@1936
    56
}
slouken@1936
    57
slouken@1936
    58
void *
slouken@1936
    59
Cocoa_GL_GetProcAddress(_THIS, const char *proc)
slouken@1936
    60
{
slouken@1936
    61
    return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
slouken@1936
    62
}
slouken@1936
    63
slouken@3057
    64
void
slouken@1936
    65
Cocoa_GL_UnloadLibrary(_THIS)
slouken@1936
    66
{
slouken@3057
    67
    SDL_UnloadObject(_this->gl_config.dll_handle);
slouken@3057
    68
    _this->gl_config.dll_handle = NULL;
slouken@1936
    69
}
slouken@1936
    70
slouken@1936
    71
SDL_GLContext
slouken@1936
    72
Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1936
    73
{
slouken@1936
    74
    NSAutoreleasePool *pool;
slouken@5246
    75
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@1936
    76
    SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
slouken@1936
    77
    NSOpenGLPixelFormatAttribute attr[32];
slouken@1936
    78
    NSOpenGLPixelFormat *fmt;
slouken@2178
    79
    NSOpenGLContext *context;
slouken@1936
    80
    int i = 0;
slouken@1936
    81
slouken@1936
    82
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
    83
slouken@5249
    84
#ifndef FULLSCREEN_TOGGLEABLE
slouken@1936
    85
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1936
    86
        attr[i++] = NSOpenGLPFAFullScreen;
slouken@1936
    87
    }
slouken@5249
    88
#endif
slouken@1936
    89
slouken@1936
    90
    attr[i++] = NSOpenGLPFAColorSize;
slouken@1936
    91
    attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
slouken@1936
    92
slouken@1936
    93
    attr[i++] = NSOpenGLPFADepthSize;
slouken@1936
    94
    attr[i++] = _this->gl_config.depth_size;
slouken@1936
    95
slouken@1936
    96
    if (_this->gl_config.double_buffer) {
slouken@1936
    97
        attr[i++] = NSOpenGLPFADoubleBuffer;
slouken@1936
    98
    }
slouken@1936
    99
slouken@1936
   100
    if (_this->gl_config.stereo) {
slouken@1936
   101
        attr[i++] = NSOpenGLPFAStereo;
slouken@1936
   102
    }
slouken@1936
   103
slouken@1936
   104
    if (_this->gl_config.stencil_size) {
slouken@1936
   105
        attr[i++] = NSOpenGLPFAStencilSize;
slouken@1936
   106
        attr[i++] = _this->gl_config.stencil_size;
slouken@1936
   107
    }
slouken@1936
   108
slouken@1936
   109
    if ((_this->gl_config.accum_red_size +
slouken@1936
   110
         _this->gl_config.accum_green_size +
slouken@1936
   111
         _this->gl_config.accum_blue_size +
slouken@1936
   112
         _this->gl_config.accum_alpha_size) > 0) {
slouken@1936
   113
        attr[i++] = NSOpenGLPFAAccumSize;
slouken@1936
   114
        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@1936
   115
    }
slouken@1936
   116
slouken@1936
   117
    if (_this->gl_config.multisamplebuffers) {
slouken@1936
   118
        attr[i++] = NSOpenGLPFASampleBuffers;
slouken@1936
   119
        attr[i++] = _this->gl_config.multisamplebuffers;
slouken@1936
   120
    }
slouken@1936
   121
slouken@1936
   122
    if (_this->gl_config.multisamplesamples) {
slouken@1936
   123
        attr[i++] = NSOpenGLPFASamples;
slouken@1936
   124
        attr[i++] = _this->gl_config.multisamplesamples;
slouken@1936
   125
        attr[i++] = NSOpenGLPFANoRecovery;
slouken@1936
   126
    }
slouken@1936
   127
slouken@3571
   128
    if (_this->gl_config.accelerated >= 0) {
slouken@3571
   129
        if (_this->gl_config.accelerated) {
slouken@3571
   130
            attr[i++] = NSOpenGLPFAAccelerated;
slouken@3571
   131
        } else {
slouken@3571
   132
            attr[i++] = NSOpenGLPFARendererID;
slouken@3571
   133
            attr[i++] = kCGLRendererGenericFloatID;
slouken@3571
   134
        }
slouken@1936
   135
    }
slouken@1936
   136
slouken@1936
   137
    attr[i++] = NSOpenGLPFAScreenMask;
slouken@1936
   138
    attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
slouken@1936
   139
    attr[i] = 0;
slouken@1936
   140
slouken@1936
   141
    fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
slouken@1936
   142
    if (fmt == nil) {
slouken@1936
   143
        SDL_SetError ("Failed creating OpenGL pixel format");
slouken@1936
   144
        [pool release];
slouken@1936
   145
        return NULL;
slouken@1936
   146
    }
slouken@1936
   147
slouken@2178
   148
    context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
slouken@1936
   149
slouken@1936
   150
    [fmt release];
slouken@1936
   151
slouken@2178
   152
    if (context == nil) {
slouken@1936
   153
        SDL_SetError ("Failed creating OpenGL context");
slouken@1936
   154
        [pool release];
slouken@1936
   155
        return NULL;
slouken@1936
   156
    }
slouken@1936
   157
slouken@1936
   158
    /*
slouken@1936
   159
     * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
slouken@1936
   160
     *  "You are blowing a couple of the internal OpenGL function caches. This
slouken@1936
   161
     *  appears to be happening in the VAO case.  You can tell OpenGL to up
slouken@1936
   162
     *  the cache size by issuing the following calls right after you create
slouken@1936
   163
     *  the OpenGL context.  The default cache size is 16."    --ryan.
slouken@1936
   164
     */
slouken@1936
   165
slouken@1936
   166
    #ifndef GLI_ARRAY_FUNC_CACHE_MAX
slouken@1936
   167
    #define GLI_ARRAY_FUNC_CACHE_MAX 284
slouken@1936
   168
    #endif
slouken@1936
   169
slouken@1936
   170
    #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
slouken@1936
   171
    #define GLI_SUBMIT_FUNC_CACHE_MAX 280
slouken@1936
   172
    #endif
slouken@1936
   173
slouken@1936
   174
    {
slouken@4925
   175
        GLint cache_max = 64;
slouken@2178
   176
        CGLContextObj ctx = [context CGLContextObj];
slouken@1936
   177
        CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
slouken@1936
   178
        CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
slouken@1936
   179
    }
slouken@1936
   180
slouken@1936
   181
    /* End Wisdom from Apple Engineer section. --ryan. */
slouken@1936
   182
slouken@1936
   183
    [pool release];
slouken@2178
   184
slouken@2178
   185
    if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
slouken@2178
   186
        Cocoa_GL_DeleteContext(_this, context);
slouken@2178
   187
        return NULL;
slouken@2178
   188
    }
slouken@2178
   189
slouken@2178
   190
    return context;
slouken@1936
   191
}
slouken@1936
   192
slouken@1936
   193
int
slouken@1936
   194
Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1936
   195
{
slouken@1936
   196
    NSAutoreleasePool *pool;
slouken@1936
   197
slouken@1936
   198
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
   199
slouken@1936
   200
    if (context) {
slouken@1936
   201
        SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
slouken@1936
   202
        NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
slouken@1936
   203
slouken@5249
   204
#ifndef FULLSCREEN_TOGGLEABLE
slouken@1973
   205
        if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1973
   206
            [nscontext setFullScreen];
slouken@5249
   207
        } else
slouken@5249
   208
#endif
slouken@5249
   209
        {
slouken@3688
   210
            [nscontext setView:[windowdata->nswindow contentView]];
slouken@1973
   211
            [nscontext update];
slouken@1973
   212
        }
slouken@1936
   213
        [nscontext makeCurrentContext];
slouken@1936
   214
    } else {
slouken@1936
   215
        [NSOpenGLContext clearCurrentContext];
slouken@1936
   216
    }
slouken@1936
   217
slouken@1936
   218
    [pool release];
slouken@1936
   219
    return 0;
slouken@1936
   220
}
slouken@1936
   221
slouken@1936
   222
int
slouken@1936
   223
Cocoa_GL_SetSwapInterval(_THIS, int interval)
slouken@1936
   224
{
slouken@1936
   225
    NSAutoreleasePool *pool;
slouken@1936
   226
    NSOpenGLContext *nscontext;
slouken@2703
   227
    GLint value;
slouken@1936
   228
    int status;
slouken@1936
   229
slouken@1936
   230
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
   231
slouken@1936
   232
    nscontext = [NSOpenGLContext currentContext];
slouken@1936
   233
    if (nscontext != nil) {
slouken@1936
   234
        value = interval;
slouken@1936
   235
        [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
slouken@1936
   236
        status = 0;
slouken@1936
   237
    } else {
slouken@1936
   238
        SDL_SetError("No current OpenGL context");
slouken@1936
   239
        status = -1;
slouken@1936
   240
    }
slouken@1936
   241
slouken@1936
   242
    [pool release];
slouken@1936
   243
    return status;
slouken@1936
   244
}
slouken@1936
   245
slouken@1936
   246
int
slouken@1936
   247
Cocoa_GL_GetSwapInterval(_THIS)
slouken@1936
   248
{
slouken@1936
   249
    NSAutoreleasePool *pool;
slouken@1936
   250
    NSOpenGLContext *nscontext;
slouken@2703
   251
    GLint value;
slouken@1936
   252
    int status;
slouken@1936
   253
slouken@1936
   254
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
   255
slouken@1936
   256
    nscontext = [NSOpenGLContext currentContext];
slouken@1936
   257
    if (nscontext != nil) {
slouken@1936
   258
        [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
slouken@1936
   259
        status = (int)value;
slouken@1936
   260
    } else {
slouken@1936
   261
        SDL_SetError("No current OpenGL context");
slouken@1936
   262
        status = -1;
slouken@1936
   263
    }
slouken@1936
   264
slouken@1936
   265
    [pool release];
slouken@1936
   266
    return status;
slouken@1936
   267
}
slouken@1936
   268
slouken@1936
   269
void
slouken@1936
   270
Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1936
   271
{
slouken@1936
   272
    NSAutoreleasePool *pool;
slouken@1936
   273
    NSOpenGLContext *nscontext;
slouken@1936
   274
slouken@1936
   275
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
   276
slouken@1936
   277
    /* FIXME: Do we need to get the context for the window? */
slouken@1936
   278
    nscontext = [NSOpenGLContext currentContext];
slouken@1936
   279
    if (nscontext != nil) {
slouken@1936
   280
        [nscontext flushBuffer];
slouken@1936
   281
    }
slouken@1936
   282
slouken@1936
   283
    [pool release];
slouken@1936
   284
}
slouken@1936
   285
slouken@1936
   286
void
slouken@1936
   287
Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1936
   288
{
slouken@1936
   289
    NSAutoreleasePool *pool;
slouken@1936
   290
    NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
slouken@1936
   291
slouken@1936
   292
    pool = [[NSAutoreleasePool alloc] init];
slouken@1936
   293
slouken@1936
   294
    [nscontext clearDrawable];
slouken@1936
   295
    [nscontext release];
slouken@1936
   296
slouken@1936
   297
    [pool release];
slouken@1936
   298
}
slouken@1936
   299
slouken@1952
   300
#endif /* SDL_VIDEO_OPENGL_CGL */
slouken@1936
   301
slouken@1936
   302
/* vi: set ts=4 sw=4 expandtab: */