src/video/x11/SDL_x11opengl.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 24 Mar 2009 10:43:53 +0000
changeset 3100 7dc982143c06
parent 3057 089a77aebb7d
child 3105 cdeee9f9b14b
permissions -rw-r--r--
Date: Sun, 22 Mar 2009 12:52:29 +0000
From: Luke Benstead
Subject: OpenGL 3.0 Context Creation

I've attached a patch which implements OpenGL 3.x context creation on
the latest SVN. I've added two options to SDL_GL_SetAttribute, these
are SDL_GL_CONTEXT_MAJOR_VERSION and SDL_GL_CONTEXT_MINOR_VERSION.
These default to 2 and 1 respectively. If the major version is less
than 3 then the current context creation method is used, otherwise the
appropriate new context creation function is called (depending on the
platform).

Sample code:

if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //Without these 2 lines, SDL will create a GL 2.x context
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL | SDL_FULLSCREEN );


I've implemented context creation on both Win32 and X and run basic
tests on both. This patch doesn't provide access to all the options
allowed by the new context creation (e.g. shared contexts, forward
compatible contexts) but they can be added pretty easily.
slouken@1952
     1
/*
slouken@1952
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@1952
     4
slouken@1952
     5
    This library is free software; you can redistribute it and/or
slouken@1952
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1952
     7
    License as published by the Free Software Foundation; either
slouken@1952
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1952
     9
slouken@1952
    10
    This library is distributed in the hope that it will be useful,
slouken@1952
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1952
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1952
    13
    Lesser General Public License for more details.
slouken@1952
    14
slouken@1952
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1952
    16
    License along with _this library; if not, write to the Free Software
slouken@1952
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1952
    18
slouken@1952
    19
    Sam Lantinga
slouken@1952
    20
    slouken@libsdl.org
slouken@1952
    21
*/
slouken@1952
    22
#include "SDL_config.h"
slouken@1952
    23
slouken@1952
    24
#include "SDL_x11video.h"
slouken@1952
    25
slouken@1952
    26
/* GLX implementation of SDL OpenGL support */
slouken@1952
    27
slouken@1952
    28
#if SDL_VIDEO_OPENGL_GLX
slouken@1952
    29
#include "SDL_loadso.h"
slouken@1952
    30
slouken@1952
    31
#if defined(__IRIX__)
slouken@1952
    32
/* IRIX doesn't have a GL library versioning system */
slouken@1952
    33
#define DEFAULT_OPENGL	"libGL.so"
slouken@1952
    34
#elif defined(__MACOSX__)
slouken@1952
    35
#define DEFAULT_OPENGL	"/usr/X11R6/lib/libGL.1.dylib"
slouken@1952
    36
#elif defined(__QNXNTO__)
slouken@1952
    37
#define DEFAULT_OPENGL	"libGL.so.3"
slouken@1952
    38
#else
slouken@1952
    39
#define DEFAULT_OPENGL	"libGL.so.1"
slouken@1952
    40
#endif
slouken@1952
    41
slouken@1952
    42
#ifndef GLX_ARB_multisample
slouken@1952
    43
#define GLX_ARB_multisample
slouken@1952
    44
#define GLX_SAMPLE_BUFFERS_ARB             100000
slouken@1952
    45
#define GLX_SAMPLES_ARB                    100001
slouken@1952
    46
#endif
slouken@1952
    47
slouken@1952
    48
#ifndef GLX_EXT_visual_rating
slouken@1952
    49
#define GLX_EXT_visual_rating
slouken@1952
    50
#define GLX_VISUAL_CAVEAT_EXT              0x20
slouken@1952
    51
#define GLX_NONE_EXT                       0x8000
slouken@1952
    52
#define GLX_SLOW_VISUAL_EXT                0x8001
slouken@1952
    53
#define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
slouken@1952
    54
#endif
slouken@1952
    55
slouken@3100
    56
#ifndef GLX_ARB_create_context
slouken@3100
    57
#define GLX_ARB_create_context
slouken@3100
    58
#define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091
slouken@3100
    59
#define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092
slouken@3100
    60
#define GLX_CONTEXT_FLAGS_ARB              0x2094
slouken@3100
    61
#define GLX_CONTEXT_DEBUG_BIT_ARB          0x0001
slouken@3100
    62
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
slouken@3100
    63
#endif
slouken@3100
    64
slouken@1952
    65
#define OPENGL_REQUIRS_DLOPEN
slouken@1952
    66
#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
slouken@1952
    67
#include <dlfcn.h>
slouken@1952
    68
#define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
slouken@1952
    69
#define GL_LoadFunction		dlsym
slouken@1952
    70
#define GL_UnloadObject		dlclose
slouken@1952
    71
#else
slouken@1952
    72
#define GL_LoadObject	SDL_LoadObject
slouken@1952
    73
#define GL_LoadFunction	SDL_LoadFunction
slouken@1952
    74
#define GL_UnloadObject	SDL_UnloadObject
slouken@1952
    75
#endif
slouken@1952
    76
slouken@3057
    77
static void X11_GL_InitExtensions(_THIS);
bob@2322
    78
slouken@3100
    79
/* Typedef for the GL 3.0 context creation function */
slouken@3100
    80
typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
slouken@3100
    81
slouken@1952
    82
int
slouken@1952
    83
X11_GL_LoadLibrary(_THIS, const char *path)
slouken@1952
    84
{
slouken@1952
    85
    void *handle;
slouken@1952
    86
slouken@3057
    87
    /* Load the OpenGL library */
slouken@3057
    88
    if (path == NULL) {
slouken@3057
    89
        path = SDL_getenv("SDL_OPENGL_LIBRARY");
slouken@1952
    90
    }
slouken@3057
    91
    if (path == NULL) {
slouken@3057
    92
        path = DEFAULT_OPENGL;
slouken@3057
    93
    }
slouken@3057
    94
    _this->gl_config.dll_handle = SDL_LoadObject(path);
slouken@3057
    95
    if (!_this->gl_config.dll_handle) {
slouken@3057
    96
        return -1;
slouken@3057
    97
    }
slouken@3057
    98
    SDL_strlcpy(_this->gl_config.driver_path, path,
slouken@3057
    99
                SDL_arraysize(_this->gl_config.driver_path));
slouken@2244
   100
slouken@3057
   101
    /* Allocate OpenGL memory */
slouken@3057
   102
    _this->gl_data =
slouken@3057
   103
        (struct SDL_GLDriverData *) SDL_calloc(1,
slouken@3057
   104
                                               sizeof(struct
slouken@3057
   105
                                                      SDL_GLDriverData));
slouken@3057
   106
    if (!_this->gl_data) {
slouken@3057
   107
        SDL_OutOfMemory();
slouken@3057
   108
        return -1;
slouken@3057
   109
    }
slouken@3057
   110
slouken@3057
   111
    /* Load function pointers */
slouken@3057
   112
    handle = _this->gl_config.dll_handle;
slouken@1952
   113
    _this->gl_data->glXGetProcAddress =
slouken@1952
   114
        (void *(*)(const GLubyte *)) GL_LoadFunction(handle,
slouken@1952
   115
                                                     "glXGetProcAddressARB");
slouken@1952
   116
    _this->gl_data->glXChooseVisual =
slouken@1952
   117
        (XVisualInfo * (*)(Display *, int, int *)) GL_LoadFunction(handle,
slouken@1952
   118
                                                                   "glXChooseVisual");
slouken@1952
   119
    _this->gl_data->glXCreateContext =
slouken@1952
   120
        (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
slouken@1952
   121
        GL_LoadFunction(handle, "glXCreateContext");
slouken@1952
   122
    _this->gl_data->glXDestroyContext =
slouken@1952
   123
        (void (*)(Display *, GLXContext)) GL_LoadFunction(handle,
slouken@1952
   124
                                                          "glXDestroyContext");
slouken@1952
   125
    _this->gl_data->glXMakeCurrent =
slouken@1952
   126
        (int (*)(Display *, GLXDrawable, GLXContext)) GL_LoadFunction(handle,
slouken@1952
   127
                                                                      "glXMakeCurrent");
slouken@1952
   128
    _this->gl_data->glXSwapBuffers =
slouken@1952
   129
        (void (*)(Display *, GLXDrawable)) GL_LoadFunction(handle,
slouken@1952
   130
                                                           "glXSwapBuffers");
slouken@1952
   131
slouken@1952
   132
    if (!_this->gl_data->glXChooseVisual ||
slouken@1952
   133
        !_this->gl_data->glXCreateContext ||
slouken@1952
   134
        !_this->gl_data->glXDestroyContext ||
slouken@1956
   135
        !_this->gl_data->glXMakeCurrent || !_this->gl_data->glXSwapBuffers) {
slouken@1952
   136
        SDL_SetError("Could not retrieve OpenGL functions");
slouken@1952
   137
        return -1;
slouken@1952
   138
    }
slouken@1952
   139
slouken@3057
   140
    /* Initialize extensions */
slouken@3057
   141
    X11_GL_InitExtensions(_this);
slouken@3057
   142
slouken@1952
   143
    return 0;
slouken@1952
   144
}
slouken@1952
   145
slouken@1952
   146
void *
slouken@1952
   147
X11_GL_GetProcAddress(_THIS, const char *proc)
slouken@1952
   148
{
slouken@1952
   149
    void *handle;
slouken@1952
   150
slouken@1952
   151
    handle = _this->gl_config.dll_handle;
slouken@1952
   152
    if (_this->gl_data->glXGetProcAddress) {
slouken@1952
   153
        return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
slouken@1952
   154
    }
slouken@1952
   155
    return GL_LoadFunction(handle, proc);
slouken@1952
   156
}
slouken@1952
   157
slouken@3057
   158
void
slouken@1952
   159
X11_GL_UnloadLibrary(_THIS)
slouken@1952
   160
{
slouken@3057
   161
    /* Don't actually unload the library, since it may have registered
slouken@3057
   162
     * X11 shutdown hooks, per the notes at:
slouken@3057
   163
     * http://dri.sourceforge.net/doc/DRIuserguide.html
slouken@3057
   164
     */
slouken@3057
   165
#if 0
slouken@3057
   166
    GL_UnloadObject(_this->gl_config.dll_handle);
slouken@3057
   167
    _this->gl_config.dll_handle = NULL;
slouken@3057
   168
#endif
slouken@3057
   169
slouken@3057
   170
    /* Free OpenGL memory */
slouken@3057
   171
    SDL_free(_this->gl_data);
slouken@3057
   172
    _this->gl_data = NULL;
slouken@1952
   173
}
slouken@1952
   174
slouken@1952
   175
static SDL_bool
slouken@1952
   176
HasExtension(const char *extension, const char *extensions)
slouken@1952
   177
{
slouken@1952
   178
    const char *start;
slouken@1952
   179
    const char *where, *terminator;
slouken@1952
   180
slouken@1952
   181
    /* Extension names should not have spaces. */
slouken@1952
   182
    where = SDL_strchr(extension, ' ');
slouken@1952
   183
    if (where || *extension == '\0')
slouken@1952
   184
        return SDL_FALSE;
slouken@1952
   185
slouken@1952
   186
    if (!extensions)
slouken@1952
   187
        return SDL_FALSE;
slouken@1952
   188
slouken@1952
   189
    /* It takes a bit of care to be fool-proof about parsing the
slouken@1952
   190
     * OpenGL extensions string. Don't be fooled by sub-strings,
slouken@1952
   191
     * etc. */
slouken@1952
   192
slouken@1952
   193
    start = extensions;
slouken@1952
   194
slouken@1952
   195
    for (;;) {
slouken@1952
   196
        where = SDL_strstr(start, extension);
slouken@1952
   197
        if (!where)
slouken@1952
   198
            break;
slouken@1952
   199
slouken@1952
   200
        terminator = where + SDL_strlen(extension);
slouken@1952
   201
        if (where == start || *(where - 1) == ' ')
slouken@1952
   202
            if (*terminator == ' ' || *terminator == '\0')
slouken@1952
   203
                return SDL_TRUE;
slouken@1952
   204
slouken@1952
   205
        start = terminator;
slouken@1952
   206
    }
slouken@1952
   207
    return SDL_FALSE;
slouken@1952
   208
}
slouken@1952
   209
slouken@1952
   210
static void
slouken@1952
   211
X11_GL_InitExtensions(_THIS)
slouken@1952
   212
{
slouken@1952
   213
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@1952
   214
    int screen = ((SDL_DisplayData *) SDL_CurrentDisplay.driverdata)->screen;
slouken@1952
   215
    XVisualInfo *vinfo;
slouken@1952
   216
    XSetWindowAttributes xattr;
slouken@1952
   217
    Window w;
slouken@1952
   218
    GLXContext context;
slouken@1952
   219
    const char *(*glXQueryExtensionsStringFunc) (Display *, int);
slouken@1952
   220
    const char *extensions;
slouken@1952
   221
slouken@1952
   222
    vinfo = X11_GL_GetVisual(_this, display, screen);
slouken@1952
   223
    if (!vinfo) {
slouken@1952
   224
        return;
slouken@1952
   225
    }
slouken@1952
   226
    xattr.background_pixel = 0;
slouken@1952
   227
    xattr.border_pixel = 0;
slouken@1952
   228
    xattr.colormap =
slouken@1952
   229
        XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
slouken@1952
   230
                        AllocNone);
slouken@1952
   231
    w = XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
slouken@1952
   232
                      vinfo->depth, InputOutput, vinfo->visual,
slouken@1952
   233
                      (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
slouken@1952
   234
    context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
slouken@1952
   235
    if (context) {
slouken@1952
   236
        _this->gl_data->glXMakeCurrent(display, w, context);
slouken@1952
   237
    }
slouken@1952
   238
    XFree(vinfo);
slouken@1952
   239
slouken@1952
   240
    glXQueryExtensionsStringFunc =
slouken@1952
   241
        (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
slouken@1952
   242
                                                                "glXQueryExtensionsString");
slouken@1952
   243
    if (glXQueryExtensionsStringFunc) {
slouken@1952
   244
        extensions = glXQueryExtensionsStringFunc(display, screen);
slouken@1952
   245
    } else {
slouken@1952
   246
        extensions = NULL;
slouken@1952
   247
    }
slouken@1952
   248
slouken@1952
   249
    /* Check for SGI_swap_control */
icculus@2105
   250
    if (HasExtension("GLX_SGI_swap_control", extensions)) {
slouken@1952
   251
        _this->gl_data->glXSwapIntervalSGI =
slouken@1952
   252
            (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
slouken@1952
   253
    }
slouken@1952
   254
slouken@1952
   255
    /* Check for GLX_MESA_swap_control */
slouken@1952
   256
    if (HasExtension("GLX_MESA_swap_control", extensions)) {
slouken@1952
   257
        _this->gl_data->glXSwapIntervalMESA =
slouken@1952
   258
            (GLint(*)(unsigned)) X11_GL_GetProcAddress(_this,
slouken@1952
   259
                                                       "glXSwapIntervalMESA");
slouken@1952
   260
        _this->gl_data->glXGetSwapIntervalMESA =
slouken@1952
   261
            (GLint(*)(void)) X11_GL_GetProcAddress(_this,
slouken@1952
   262
                                                   "glXGetSwapIntervalMESA");
slouken@1952
   263
    }
slouken@1952
   264
slouken@1952
   265
    /* Check for GLX_EXT_visual_rating */
slouken@1952
   266
    if (HasExtension("GLX_EXT_visual_rating", extensions)) {
slouken@1952
   267
        _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
slouken@1952
   268
    }
slouken@1952
   269
slouken@1952
   270
    if (context) {
slouken@1952
   271
        _this->gl_data->glXMakeCurrent(display, None, NULL);
slouken@1952
   272
        _this->gl_data->glXDestroyContext(display, context);
slouken@1952
   273
    }
slouken@1952
   274
    XDestroyWindow(display, w);
bob@2323
   275
    X11_PumpEvents(_this);
slouken@1952
   276
}
slouken@1952
   277
slouken@1952
   278
XVisualInfo *
slouken@1952
   279
X11_GL_GetVisual(_THIS, Display * display, int screen)
slouken@1952
   280
{
slouken@1952
   281
    XVisualInfo *vinfo;
slouken@1952
   282
slouken@1952
   283
    /* 64 seems nice. */
slouken@1952
   284
    int attribs[64];
slouken@3100
   285
    int i = 0;
slouken@3100
   286
    
slouken@1952
   287
    /* Setup our GLX attributes according to the gl_config. */
slouken@1952
   288
    attribs[i++] = GLX_RGBA;
slouken@1952
   289
    attribs[i++] = GLX_RED_SIZE;
slouken@1952
   290
    attribs[i++] = _this->gl_config.red_size;
slouken@1952
   291
    attribs[i++] = GLX_GREEN_SIZE;
slouken@1952
   292
    attribs[i++] = _this->gl_config.green_size;
slouken@1952
   293
    attribs[i++] = GLX_BLUE_SIZE;
slouken@1952
   294
    attribs[i++] = _this->gl_config.blue_size;
slouken@1952
   295
slouken@1952
   296
    if (_this->gl_config.alpha_size) {
slouken@1952
   297
        attribs[i++] = GLX_ALPHA_SIZE;
slouken@1952
   298
        attribs[i++] = _this->gl_config.alpha_size;
slouken@1952
   299
    }
slouken@1952
   300
slouken@1952
   301
    if (_this->gl_config.buffer_size) {
slouken@1952
   302
        attribs[i++] = GLX_BUFFER_SIZE;
slouken@1952
   303
        attribs[i++] = _this->gl_config.buffer_size;
slouken@1952
   304
    }
slouken@1952
   305
slouken@1952
   306
    if (_this->gl_config.double_buffer) {
slouken@1952
   307
        attribs[i++] = GLX_DOUBLEBUFFER;
slouken@1952
   308
    }
slouken@1952
   309
slouken@1952
   310
    attribs[i++] = GLX_DEPTH_SIZE;
slouken@1952
   311
    attribs[i++] = _this->gl_config.depth_size;
slouken@1952
   312
slouken@1952
   313
    if (_this->gl_config.stencil_size) {
slouken@1952
   314
        attribs[i++] = GLX_STENCIL_SIZE;
slouken@1952
   315
        attribs[i++] = _this->gl_config.stencil_size;
slouken@1952
   316
    }
slouken@1952
   317
slouken@1952
   318
    if (_this->gl_config.accum_red_size) {
slouken@1952
   319
        attribs[i++] = GLX_ACCUM_RED_SIZE;
slouken@1952
   320
        attribs[i++] = _this->gl_config.accum_red_size;
slouken@1952
   321
    }
slouken@1952
   322
slouken@1952
   323
    if (_this->gl_config.accum_green_size) {
slouken@1952
   324
        attribs[i++] = GLX_ACCUM_GREEN_SIZE;
slouken@1952
   325
        attribs[i++] = _this->gl_config.accum_green_size;
slouken@1952
   326
    }
slouken@1952
   327
slouken@1952
   328
    if (_this->gl_config.accum_blue_size) {
slouken@1952
   329
        attribs[i++] = GLX_ACCUM_BLUE_SIZE;
slouken@1952
   330
        attribs[i++] = _this->gl_config.accum_blue_size;
slouken@1952
   331
    }
slouken@1952
   332
slouken@1952
   333
    if (_this->gl_config.accum_alpha_size) {
slouken@1952
   334
        attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
slouken@1952
   335
        attribs[i++] = _this->gl_config.accum_alpha_size;
slouken@1952
   336
    }
slouken@1952
   337
slouken@1952
   338
    if (_this->gl_config.stereo) {
slouken@1952
   339
        attribs[i++] = GLX_STEREO;
slouken@1952
   340
    }
slouken@1952
   341
slouken@1952
   342
    if (_this->gl_config.multisamplebuffers) {
slouken@1952
   343
        attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
slouken@1952
   344
        attribs[i++] = _this->gl_config.multisamplebuffers;
slouken@1952
   345
    }
slouken@1952
   346
slouken@1952
   347
    if (_this->gl_config.multisamplesamples) {
slouken@1952
   348
        attribs[i++] = GLX_SAMPLES_ARB;
slouken@1952
   349
        attribs[i++] = _this->gl_config.multisamplesamples;
slouken@1952
   350
    }
slouken@1952
   351
slouken@1952
   352
    if (_this->gl_config.accelerated >= 0
slouken@1952
   353
        && _this->gl_data->HAS_GLX_EXT_visual_rating) {
slouken@1952
   354
        attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
slouken@1952
   355
        attribs[i++] = GLX_NONE_EXT;
slouken@1952
   356
    }
slouken@1952
   357
#ifdef GLX_DIRECT_COLOR         /* Try for a DirectColor visual for gamma support */
slouken@2963
   358
    if (X11_UseDirectColorVisuals()) {
slouken@1952
   359
        attribs[i++] = GLX_X_VISUAL_TYPE;
slouken@1952
   360
        attribs[i++] = GLX_DIRECT_COLOR;
slouken@1952
   361
    }
slouken@1952
   362
#endif
slouken@1952
   363
    attribs[i++] = None;
slouken@1952
   364
slouken@1952
   365
    vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
slouken@1952
   366
#ifdef GLX_DIRECT_COLOR
slouken@2963
   367
    if (!vinfo && X11_UseDirectColorVisuals()) {        /* No DirectColor visual?  Try again.. */
slouken@1952
   368
        attribs[i - 3] = None;
slouken@1952
   369
        vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
slouken@1952
   370
    }
slouken@1952
   371
#endif
slouken@1952
   372
    if (!vinfo) {
slouken@1952
   373
        SDL_SetError("Couldn't find matching GLX visual");
slouken@1952
   374
    }
slouken@1952
   375
    return vinfo;
slouken@1952
   376
}
slouken@1952
   377
slouken@1952
   378
SDL_GLContext
slouken@1952
   379
X11_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1952
   380
{
slouken@1952
   381
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1952
   382
    Display *display = data->videodata->display;
slouken@1952
   383
    int screen =
slouken@3013
   384
        ((SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->
slouken@3013
   385
         driverdata)->screen;
slouken@1952
   386
    XWindowAttributes xattr;
slouken@1952
   387
    XVisualInfo v, *vinfo;
slouken@1952
   388
    int n;
slouken@1952
   389
    GLXContext context = NULL;
slouken@1952
   390
slouken@1955
   391
    /* We do this to create a clean separation between X and GLX errors. */
slouken@1952
   392
    XSync(display, False);
slouken@1952
   393
    XGetWindowAttributes(display, data->window, &xattr);
slouken@1952
   394
    v.screen = screen;
slouken@1952
   395
    v.visualid = XVisualIDFromVisual(xattr.visual);
slouken@1952
   396
    vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
slouken@1952
   397
    if (vinfo) {
slouken@3100
   398
        if (_this->gl_config.major_version < 3) {        
slouken@3100
   399
            context =
slouken@3100
   400
                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
slouken@3100
   401
        } else {
slouken@3100
   402
            /* If we want a GL 3.0 context or later we need to get a temporary
slouken@3100
   403
               context to grab the new context creation function */
slouken@3100
   404
            GLXContext temp_context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
slouken@3100
   405
            if (!temp_context) {
slouken@3100
   406
                SDL_SetError("Could not create GL context");        
slouken@3100
   407
                return NULL;
slouken@3100
   408
            } else {
slouken@3100
   409
                int attribs[] = {
slouken@3100
   410
                    GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
slouken@3100
   411
                    GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
slouken@3100
   412
                    0 
slouken@3100
   413
                };
slouken@3100
   414
                                
slouken@3100
   415
                /* Get a pointer to the context creation function for GL 3.0 */
slouken@3100
   416
                PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");
slouken@3100
   417
                if (!glXCreateContextAttribs) {
slouken@3100
   418
                    SDL_SetError("GL 3.x is not supported");
slouken@3100
   419
                    context = temp_context;
slouken@3100
   420
                } else {
slouken@3100
   421
                    /* Create a GL 3.0 context */
slouken@3100
   422
                    GLXFBConfig *framebuffer_config = NULL;
slouken@3100
   423
                    int fbcount = 0;                
slouken@3100
   424
                    framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display), NULL, &fbcount);
slouken@3100
   425
                    if (!framebuffer_config) {
slouken@3100
   426
                        SDL_SetError("No good framebuffers found. GL 3.0 disabled");
slouken@3100
   427
                        context = temp_context;
slouken@3100
   428
                    } else {                                    
slouken@3100
   429
                        context = glXCreateContextAttribs(display, framebuffer_config[0], NULL, True, attribs);
slouken@3100
   430
                        glXDestroyContext(display, temp_context);
slouken@3100
   431
                    }
slouken@3100
   432
                }
slouken@3100
   433
            }
slouken@3100
   434
        }
slouken@1952
   435
        XFree(vinfo);
slouken@1952
   436
    }
slouken@1952
   437
    XSync(display, False);
slouken@1952
   438
slouken@1952
   439
    if (!context) {
slouken@1952
   440
        SDL_SetError("Could not create GL context");
slouken@2178
   441
        return NULL;
slouken@1952
   442
    }
slouken@2178
   443
slouken@2178
   444
    if (X11_GL_MakeCurrent(_this, window, context) < 0) {
slouken@2178
   445
        X11_GL_DeleteContext(_this, context);
slouken@2178
   446
        return NULL;
slouken@2178
   447
    }
slouken@2178
   448
slouken@2178
   449
    return context;
slouken@1952
   450
}
slouken@1952
   451
slouken@1952
   452
int
slouken@1952
   453
X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1952
   454
{
slouken@1952
   455
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@1952
   456
    Window drawable =
slouken@1952
   457
        (window ? ((SDL_WindowData *) window->driverdata)->window : None);
slouken@1952
   458
    GLXContext glx_context = (GLXContext) context;
slouken@1952
   459
    int status;
slouken@1952
   460
slouken@1952
   461
    status = 0;
slouken@1952
   462
    if (!_this->gl_data->glXMakeCurrent(display, drawable, glx_context)) {
slouken@1952
   463
        SDL_SetError("Unable to make GL context current");
slouken@1952
   464
        status = -1;
slouken@1952
   465
    }
slouken@1952
   466
    XSync(display, False);
slouken@1952
   467
slouken@1952
   468
    return (status);
slouken@1952
   469
}
slouken@1952
   470
bob@2327
   471
/* 
bob@2327
   472
   0 is a valid argument to glxSwapIntervalMESA and setting it to 0
bob@2327
   473
   with the MESA version of the extension will undo the effect of a
bob@2327
   474
   previous call with a value that is greater than zero (or at least
bob@2327
   475
   that is what the FM says. OTOH, 0 is an invalid argument to
bob@2327
   476
   glxSwapIntervalSGI and it returns an error if you call it with 0 as
bob@2327
   477
   an argument.
bob@2327
   478
*/
bob@2327
   479
bob@2327
   480
static int swapinterval = -1;
slouken@1952
   481
int
slouken@1952
   482
X11_GL_SetSwapInterval(_THIS, int interval)
slouken@1952
   483
{
slouken@1952
   484
    int status;
slouken@1952
   485
slouken@1952
   486
    if (_this->gl_data->glXSwapIntervalMESA) {
slouken@1952
   487
        status = _this->gl_data->glXSwapIntervalMESA(interval);
slouken@1952
   488
        if (status != 0) {
slouken@1952
   489
            SDL_SetError("glxSwapIntervalMESA failed");
slouken@1952
   490
            status = -1;
bob@2327
   491
        } else {
bob@2327
   492
            swapinterval = interval;
slouken@1952
   493
        }
slouken@1952
   494
    } else if (_this->gl_data->glXSwapIntervalSGI) {
slouken@1952
   495
        status = _this->gl_data->glXSwapIntervalSGI(interval);
slouken@1952
   496
        if (status != 0) {
slouken@1952
   497
            SDL_SetError("glxSwapIntervalSGI failed");
slouken@1952
   498
            status = -1;
bob@2327
   499
        } else {
bob@2327
   500
            swapinterval = interval;
slouken@1952
   501
        }
slouken@1952
   502
    } else {
slouken@1952
   503
        SDL_Unsupported();
slouken@1952
   504
        status = -1;
slouken@1952
   505
    }
slouken@1952
   506
    return status;
slouken@1952
   507
}
slouken@1952
   508
slouken@1952
   509
int
slouken@1952
   510
X11_GL_GetSwapInterval(_THIS)
slouken@1952
   511
{
slouken@1952
   512
    if (_this->gl_data->glXGetSwapIntervalMESA) {
slouken@1952
   513
        return _this->gl_data->glXGetSwapIntervalMESA();
slouken@1952
   514
    } else {
bob@2327
   515
        return swapinterval;
slouken@1952
   516
    }
slouken@1952
   517
}
slouken@1952
   518
slouken@1952
   519
void
slouken@1952
   520
X11_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1952
   521
{
slouken@1952
   522
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1952
   523
    Display *display = data->videodata->display;
slouken@1952
   524
slouken@1952
   525
    _this->gl_data->glXSwapBuffers(display, data->window);
slouken@1952
   526
}
slouken@1952
   527
slouken@1952
   528
void
slouken@1952
   529
X11_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1952
   530
{
slouken@1952
   531
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@1952
   532
    GLXContext glx_context = (GLXContext) context;
slouken@1952
   533
slouken@1952
   534
    _this->gl_data->glXDestroyContext(display, glx_context);
bob@2324
   535
    XSync(display, False);
slouken@1952
   536
}
slouken@1952
   537
slouken@1952
   538
#endif /* SDL_VIDEO_OPENGL_GLX */
slouken@1952
   539
slouken@1952
   540
/* vi: set ts=4 sw=4 expandtab: */