src/video/x11/SDL_x11opengl.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 24 Feb 2011 17:52:47 -0800
changeset 5395 f0e399961f3a
parent 5262 b530ef003506
child 5535 96594ac5fd1a
permissions -rw-r--r--
Fixed bug 1145 (GL Context creation fails for OpenGL 3.2 + Alpha buffer with X11 BadMatch)

Matthias 2011-02-23 09:37:51 PST

Please view the attached source file. Using this minimal program (as attached),
it creates an OpenGL 2.0 context with a cleared color buffer. If I set the
OpenGL version to 3.2, the function SDL_GL_CreateContext fails (or more
specifically, glXMakeCurrent fails) with an X11 BadMatch error:


X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 128 (GLX)
Minor opcode of failed request: 5 (X_GLXMakeCurrent)
Serial number of failed request: 153
Current serial number in output stream: 153


Also note that if I do not specify the alpha buffer size, the program works for
OpenGL 2.0 and OpenGL 3.2.

After some further analysis, I believe I have found the problem. The specific
issue is in:

SDL_x11opengl.c::X11_GL_CreateContext.

Note that for OpenGL 3.2 contexts, the GLXFBConfig to use is chosen as the best
match from glXChooseFBConfig. However, opengl attributes originally set with
SDL_GL_SetAttribute are not mapped to GLX attributes and then passed to the
glXChooseFBConfig function. According to the GLX 1.4 specification, if the
attributes are not specified, the function falls back to defaults (which, in
this particular case, prefer alpha channel size == 0).

For testing purposes, I modified the call to glXChooseFBConfig to look
something like this:


int glxAttribs[] =
{
GLX_RED_SIZE,8,
GLX_GREEN_SIZE,8,
GLX_BLUE_SIZE,8,
GLX_ALPHA_SIZE,8,
None
};

if (!glXChooseFBConfig ||
!(framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display),
glxAttribs, &fbcount)))
{
...
}


The best match GLXFBConfig then supports 8 bit alpha channel. The program then
works as intended.


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