src/video/quartz/SDL_QuartzGL.m
changeset 761 c5b2b6d2d1fe
child 770 ac44ddb84f6f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/quartz/SDL_QuartzGL.m	Sun Jan 04 14:55:35 2004 +0000
     1.3 @@ -0,0 +1,228 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2003  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +
    1.26 +#include "SDL_QuartzVideo.h"
    1.27 +
    1.28 +/* 
    1.29 +    This is a workaround to directly access NSOpenGLContext's CGL context
    1.30 +    We need this to check for errors NSOpenGLContext doesn't support
    1.31 +*/
    1.32 +@interface NSOpenGLContext (CGLContextAccess)
    1.33 +- (CGLContextObj) cglContext;
    1.34 +@end
    1.35 +
    1.36 +@implementation NSOpenGLContext (CGLContextAccess)
    1.37 +- (CGLContextObj) cglContext;
    1.38 +{
    1.39 +    return _contextAuxiliary;
    1.40 +}
    1.41 +@end
    1.42 +
    1.43 +/* OpenGL helper functions (used internally) */
    1.44 +
    1.45 +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
    1.46 +
    1.47 +    NSOpenGLPixelFormatAttribute attr[32];
    1.48 +    NSOpenGLPixelFormat *fmt;
    1.49 +    int i = 0;
    1.50 +    int colorBits = bpp;
    1.51 +
    1.52 +    if ( flags & SDL_FULLSCREEN ) {
    1.53 +
    1.54 +        attr[i++] = NSOpenGLPFAFullScreen;
    1.55 +    }
    1.56 +    /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    1.57 +    else if ( colorBits != device_bpp ) {
    1.58 +
    1.59 +        colorBits = device_bpp;
    1.60 +    }
    1.61 +
    1.62 +    attr[i++] = NSOpenGLPFAColorSize;
    1.63 +    attr[i++] = colorBits;
    1.64 +
    1.65 +    attr[i++] = NSOpenGLPFADepthSize;
    1.66 +    attr[i++] = this->gl_config.depth_size;
    1.67 +
    1.68 +    if ( this->gl_config.double_buffer ) {
    1.69 +        attr[i++] = NSOpenGLPFADoubleBuffer;
    1.70 +    }
    1.71 +
    1.72 +    if ( this->gl_config.stereo ) {
    1.73 +        attr[i++] = NSOpenGLPFAStereo;
    1.74 +    }
    1.75 +
    1.76 +    if ( this->gl_config.stencil_size != 0 ) {
    1.77 +        attr[i++] = NSOpenGLPFAStencilSize;
    1.78 +        attr[i++] = this->gl_config.stencil_size;
    1.79 +    }
    1.80 +
    1.81 +#if NSOPENGL_CURRENT_VERSION > 1  /* What version should this be? */
    1.82 +    if ( this->gl_config.multisamplebuffers != 0 ) {
    1.83 +        attr[i++] = NSOpenGLPFASampleBuffers;
    1.84 +        attr[i++] = this->gl_config.multisamplebuffers;
    1.85 +    }
    1.86 +
    1.87 +    if ( this->gl_config.multisamplesamples != 0 ) {
    1.88 +        attr[i++] = NSOpenGLPFASamples;
    1.89 +        attr[i++] = this->gl_config.multisamplesamples;
    1.90 +    }
    1.91 +#endif
    1.92 +
    1.93 +    attr[i++] = NSOpenGLPFAScreenMask;
    1.94 +    attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
    1.95 +    attr[i] = 0;
    1.96 +
    1.97 +    fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
    1.98 +    if (fmt == nil) {
    1.99 +        SDL_SetError ("Failed creating OpenGL pixel format");
   1.100 +        return 0;
   1.101 +    }
   1.102 +
   1.103 +    gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
   1.104 +                                               shareContext:nil];
   1.105 +
   1.106 +    if (gl_context == nil) {
   1.107 +        SDL_SetError ("Failed creating OpenGL context");
   1.108 +        return 0;
   1.109 +    }
   1.110 +
   1.111 +    /*
   1.112 +     * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   1.113 +     *  "You are blowing a couple of the internal OpenGL function caches. This
   1.114 +     *  appears to be happening in the VAO case.  You can tell OpenGL to up
   1.115 +     *  the cache size by issuing the following calls right after you create
   1.116 +     *  the OpenGL context.  The default cache size is 16."    --ryan.
   1.117 +     */
   1.118 +
   1.119 +    #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   1.120 +    #define GLI_ARRAY_FUNC_CACHE_MAX 284
   1.121 +    #endif
   1.122 +
   1.123 +    #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   1.124 +    #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   1.125 +    #endif
   1.126 +
   1.127 +    {
   1.128 +        long cache_max = 64;
   1.129 +        CGLContextObj ctx = [ gl_context cglContext ];
   1.130 +        CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   1.131 +        CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   1.132 +    }
   1.133 +
   1.134 +    /* End Wisdom from Apple Engineer section. --ryan. */
   1.135 +
   1.136 +    /* Convince SDL that the GL "driver" is loaded */
   1.137 +    this->gl_config.driver_loaded = 1;
   1.138 +
   1.139 +    [ fmt release ];
   1.140 +
   1.141 +    return 1;
   1.142 +}
   1.143 +
   1.144 +void QZ_TearDownOpenGL (_THIS) {
   1.145 +
   1.146 +    [ NSOpenGLContext clearCurrentContext ];
   1.147 +    [ gl_context clearDrawable ];
   1.148 +    [ gl_context release ];
   1.149 +}
   1.150 +
   1.151 +
   1.152 +/* SDL OpenGL functions */
   1.153 +
   1.154 +int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
   1.155 +    this->gl_config.driver_loaded = 1;
   1.156 +    return 1;
   1.157 +}
   1.158 +
   1.159 +void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
   1.160 +
   1.161 +    /* We may want to cache the bundleRef at some point */
   1.162 +    CFBundleRef bundle;
   1.163 +    CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
   1.164 +                                                        CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
   1.165 +
   1.166 +    CFStringRef functionName = CFStringCreateWithCString
   1.167 +        (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
   1.168 +
   1.169 +    void *function;
   1.170 +
   1.171 +    bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
   1.172 +    assert (bundle != NULL);
   1.173 +
   1.174 +    function = CFBundleGetFunctionPointerForName (bundle, functionName);
   1.175 +
   1.176 +    CFRelease ( bundleURL );
   1.177 +    CFRelease ( functionName );
   1.178 +    CFRelease ( bundle );
   1.179 +
   1.180 +    return function;
   1.181 +}
   1.182 +
   1.183 +int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
   1.184 +
   1.185 +    GLenum attr = 0;
   1.186 +
   1.187 +    QZ_GL_MakeCurrent (this);
   1.188 +
   1.189 +    switch (attrib) {
   1.190 +        case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
   1.191 +        case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
   1.192 +        case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
   1.193 +        case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
   1.194 +        case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
   1.195 +        case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
   1.196 +        case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
   1.197 +        case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
   1.198 +        case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
   1.199 +        case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
   1.200 +        case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
   1.201 +        case SDL_GL_STEREO: attr = GL_STEREO; break;
   1.202 +        case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
   1.203 +        case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
   1.204 +        case SDL_GL_BUFFER_SIZE:
   1.205 +        {
   1.206 +            GLint bits = 0;
   1.207 +            GLint component;
   1.208 +
   1.209 +            /* there doesn't seem to be a single flag in OpenGL for this! */
   1.210 +            glGetIntegerv (GL_RED_BITS, &component);   bits += component;
   1.211 +            glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
   1.212 +            glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
   1.213 +            glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
   1.214 +
   1.215 +            *value = bits;
   1.216 +        }
   1.217 +        return 0;
   1.218 +    }
   1.219 +
   1.220 +    glGetIntegerv (attr, (GLint *)value);
   1.221 +    return 0;
   1.222 +}
   1.223 +
   1.224 +int    QZ_GL_MakeCurrent    (_THIS) {
   1.225 +    [ gl_context makeCurrentContext ];
   1.226 +    return 0;
   1.227 +}
   1.228 +
   1.229 +void   QZ_GL_SwapBuffers    (_THIS) {
   1.230 +    [ gl_context flushBuffer ];
   1.231 +}