src/video/x11/SDL_x11opengl.c
author Michael Sartain <mikesart@valvesoftware.com>
Thu, 11 Oct 2012 09:41:43 -0700
changeset 6570 45855398762c
parent 6522 edacce9402fb
child 6794 a0d42781fa92
permissions -rw-r--r--
Add GLX_X_VISUAL_TYPE_EXT so created window will use DirectColor if available (instead of TrueColor).
Our new X11 window was being created with the TrueColor attribute, and trying to set the gamma
on that would fail. This change checks for the visual_info extension, and uses that to ask for
DirectColor if available.
slouken@1952
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1952
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1952
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1952
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1952
    20
*/
slouken@1952
    21
#include "SDL_config.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_X11
slouken@6044
    24
slouken@1952
    25
#include "SDL_x11video.h"
icculus@5981
    26
#include "SDL_assert.h"
slouken@1952
    27
slouken@1952
    28
/* GLX implementation of SDL OpenGL support */
slouken@1952
    29
slouken@1952
    30
#if SDL_VIDEO_OPENGL_GLX
slouken@1952
    31
#include "SDL_loadso.h"
slouken@6370
    32
#include "SDL_x11opengles.h"
slouken@1952
    33
slouken@1952
    34
#if defined(__IRIX__)
slouken@1952
    35
/* IRIX doesn't have a GL library versioning system */
slouken@1952
    36
#define DEFAULT_OPENGL	"libGL.so"
slouken@1952
    37
#elif defined(__MACOSX__)
slouken@1952
    38
#define DEFAULT_OPENGL	"/usr/X11R6/lib/libGL.1.dylib"
slouken@1952
    39
#elif defined(__QNXNTO__)
slouken@1952
    40
#define DEFAULT_OPENGL	"libGL.so.3"
slouken@1952
    41
#else
slouken@1952
    42
#define DEFAULT_OPENGL	"libGL.so.1"
slouken@1952
    43
#endif
slouken@1952
    44
slouken@3241
    45
#ifndef GLX_NONE_EXT
slouken@3241
    46
#define GLX_NONE_EXT                       0x8000
slouken@3241
    47
#endif
slouken@3241
    48
slouken@1952
    49
#ifndef GLX_ARB_multisample
slouken@1952
    50
#define GLX_ARB_multisample
slouken@1952
    51
#define GLX_SAMPLE_BUFFERS_ARB             100000
slouken@1952
    52
#define GLX_SAMPLES_ARB                    100001
slouken@1952
    53
#endif
slouken@1952
    54
slouken@1952
    55
#ifndef GLX_EXT_visual_rating
slouken@1952
    56
#define GLX_EXT_visual_rating
slouken@1952
    57
#define GLX_VISUAL_CAVEAT_EXT              0x20
slouken@1952
    58
#define GLX_NONE_EXT                       0x8000
slouken@1952
    59
#define GLX_SLOW_VISUAL_EXT                0x8001
slouken@1952
    60
#define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
slouken@1952
    61
#endif
slouken@1952
    62
mikesart@6570
    63
#ifndef GLX_EXT_visual_info
mikesart@6570
    64
#define GLX_EXT_visual_info
mikesart@6570
    65
#define GLX_X_VISUAL_TYPE_EXT              0x22
mikesart@6570
    66
#define GLX_DIRECT_COLOR_EXT               0x8003
mikesart@6570
    67
#endif
mikesart@6570
    68
slouken@3100
    69
#ifndef GLX_ARB_create_context
slouken@3100
    70
#define GLX_ARB_create_context
slouken@3100
    71
#define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091
slouken@3100
    72
#define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092
slouken@3100
    73
#define GLX_CONTEXT_FLAGS_ARB              0x2094
slouken@3100
    74
#define GLX_CONTEXT_DEBUG_BIT_ARB          0x0001
slouken@3100
    75
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
slouken@5021
    76
slouken@5021
    77
/* Typedef for the GL 3.0 context creation function */
slouken@5021
    78
typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
slouken@5021
    79
                                                        GLXFBConfig config,
slouken@5021
    80
                                                        GLXContext
slouken@5021
    81
                                                        share_context,
slouken@5021
    82
                                                        Bool direct,
slouken@5021
    83
                                                        const int
slouken@5021
    84
                                                        *attrib_list);
icculus@6360
    85
#endif
slouken@6296
    86
slouken@6296
    87
#ifndef GLX_ARB_create_context_profile
slouken@6296
    88
#define GLX_ARB_create_context_profile
slouken@6296
    89
#define GLX_CONTEXT_PROFILE_MASK_ARB       0x9126
slouken@6296
    90
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB   0x00000001
slouken@6296
    91
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
slouken@6296
    92
#endif
slouken@6296
    93
slouken@6296
    94
#ifndef GLX_ARB_create_context_robustness
slouken@6296
    95
#define GLX_ARB_create_context_robustness
slouken@6296
    96
#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB  0x00000004
slouken@6296
    97
#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB     0x8256
slouken@6296
    98
#define GLX_NO_RESET_NOTIFICATION_ARB                   0x8261
slouken@6296
    99
#define GLX_LOSE_CONTEXT_ON_RESET_ARB                   0x8252
slouken@6296
   100
#endif
slouken@6296
   101
slouken@6296
   102
#ifndef GLX_EXT_create_context_es2_profile
slouken@6296
   103
#define GLX_EXT_create_context_es2_profile
icculus@6375
   104
#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
slouken@6296
   105
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT    0x00000002
slouken@6296
   106
#endif
icculus@6375
   107
#endif
slouken@6296
   108
slouken@6296
   109
#ifndef GLX_EXT_swap_control
slouken@6296
   110
#define GLX_SWAP_INTERVAL_EXT              0x20F1
slouken@6296
   111
#define GLX_MAX_SWAP_INTERVAL_EXT          0x20F2
slouken@3100
   112
#endif
slouken@3100
   113
icculus@6382
   114
#ifndef GLX_EXT_swap_control_tear
icculus@6382
   115
#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
icculus@6382
   116
#endif
icculus@6382
   117
slouken@6183
   118
#define OPENGL_REQUIRES_DLOPEN
slouken@6183
   119
#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
slouken@1952
   120
#include <dlfcn.h>
slouken@1952
   121
#define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
slouken@1952
   122
#define GL_LoadFunction		dlsym
slouken@1952
   123
#define GL_UnloadObject		dlclose
slouken@1952
   124
#else
slouken@1952
   125
#define GL_LoadObject	SDL_LoadObject
slouken@1952
   126
#define GL_LoadFunction	SDL_LoadFunction
slouken@1952
   127
#define GL_UnloadObject	SDL_UnloadObject
slouken@1952
   128
#endif
slouken@1952
   129
slouken@3057
   130
static void X11_GL_InitExtensions(_THIS);
bob@2322
   131
slouken@3100
   132
slouken@1952
   133
int
slouken@1952
   134
X11_GL_LoadLibrary(_THIS, const char *path)
slouken@1952
   135
{
slouken@1952
   136
    void *handle;
slouken@1952
   137
slouken@6370
   138
    if (_this->gl_data) {
slouken@6370
   139
        SDL_SetError("OpenGL context already created");
slouken@6370
   140
        return -1;
slouken@6370
   141
    }
slouken@6370
   142
slouken@6370
   143
    /* If SDL_GL_CONTEXT_EGL has been changed to 1, switch over to X11_GLES functions  */
slouken@6370
   144
    if (_this->gl_config.use_egl == 1) {
slouken@6373
   145
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@6370
   146
        _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
slouken@6370
   147
        _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
slouken@6370
   148
        _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
slouken@6370
   149
        _this->GL_CreateContext = X11_GLES_CreateContext;
slouken@6370
   150
        _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
slouken@6370
   151
        _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
slouken@6370
   152
        _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
slouken@6370
   153
        _this->GL_SwapWindow = X11_GLES_SwapWindow;
slouken@6370
   154
        _this->GL_DeleteContext = X11_GLES_DeleteContext;
slouken@6370
   155
        return X11_GLES_LoadLibrary(_this, path);
slouken@6373
   156
#else
slouken@6373
   157
        SDL_SetError("SDL not configured with OpenGL ES/EGL support");
slouken@6373
   158
        return -1;
slouken@6373
   159
#endif
slouken@6370
   160
    }
slouken@6370
   161
slouken@6370
   162
slouken@3057
   163
    /* Load the OpenGL library */
slouken@3057
   164
    if (path == NULL) {
slouken@3057
   165
        path = SDL_getenv("SDL_OPENGL_LIBRARY");
slouken@3057
   166
    }
slouken@3057
   167
    if (path == NULL) {
slouken@3057
   168
        path = DEFAULT_OPENGL;
slouken@3057
   169
    }
slouken@6183
   170
    _this->gl_config.dll_handle = GL_LoadObject(path);
slouken@3057
   171
    if (!_this->gl_config.dll_handle) {
slouken@6183
   172
#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
slouken@6183
   173
        SDL_SetError("Failed loading %s: %s", path, dlerror());
slouken@6183
   174
#endif
slouken@3057
   175
        return -1;
slouken@1952
   176
    }
slouken@3057
   177
    SDL_strlcpy(_this->gl_config.driver_path, path,
slouken@3057
   178
                SDL_arraysize(_this->gl_config.driver_path));
slouken@2244
   179
slouken@3057
   180
    /* Allocate OpenGL memory */
slouken@3057
   181
    _this->gl_data =
slouken@3057
   182
        (struct SDL_GLDriverData *) SDL_calloc(1,
slouken@3057
   183
                                               sizeof(struct
slouken@3057
   184
                                                      SDL_GLDriverData));
slouken@3057
   185
    if (!_this->gl_data) {
slouken@3057
   186
        SDL_OutOfMemory();
slouken@3057
   187
        return -1;
slouken@3057
   188
    }
slouken@3057
   189
slouken@3057
   190
    /* Load function pointers */
slouken@3057
   191
    handle = _this->gl_config.dll_handle;
slouken@1952
   192
    _this->gl_data->glXGetProcAddress =
slouken@4550
   193
        (void *(*)(const GLubyte *))
slouken@4550
   194
            GL_LoadFunction(handle, "glXGetProcAddressARB");
slouken@1952
   195
    _this->gl_data->glXChooseVisual =
slouken@4550
   196
        (XVisualInfo * (*)(Display *, int, int *))
slouken@4550
   197
            X11_GL_GetProcAddress(_this, "glXChooseVisual");
slouken@1952
   198
    _this->gl_data->glXCreateContext =
slouken@1952
   199
        (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
slouken@4550
   200
            X11_GL_GetProcAddress(_this, "glXCreateContext");
slouken@1952
   201
    _this->gl_data->glXDestroyContext =
slouken@4550
   202
        (void (*)(Display *, GLXContext))
slouken@4550
   203
            X11_GL_GetProcAddress(_this, "glXDestroyContext");
slouken@1952
   204
    _this->gl_data->glXMakeCurrent =
slouken@4550
   205
        (int (*)(Display *, GLXDrawable, GLXContext))
slouken@4550
   206
            X11_GL_GetProcAddress(_this, "glXMakeCurrent");
slouken@1952
   207
    _this->gl_data->glXSwapBuffers =
slouken@4550
   208
        (void (*)(Display *, GLXDrawable))
slouken@4550
   209
            X11_GL_GetProcAddress(_this, "glXSwapBuffers");
icculus@5572
   210
    _this->gl_data->glXQueryDrawable =
icculus@5572
   211
        (void (*)(Display*,GLXDrawable,int,unsigned int*))
icculus@5572
   212
            X11_GL_GetProcAddress(_this, "glXQueryDrawable");
slouken@1952
   213
slouken@1952
   214
    if (!_this->gl_data->glXChooseVisual ||
slouken@1952
   215
        !_this->gl_data->glXCreateContext ||
slouken@1952
   216
        !_this->gl_data->glXDestroyContext ||
slouken@4550
   217
        !_this->gl_data->glXMakeCurrent ||
slouken@4550
   218
        !_this->gl_data->glXSwapBuffers) {
slouken@1952
   219
        SDL_SetError("Could not retrieve OpenGL functions");
slouken@1952
   220
        return -1;
slouken@1952
   221
    }
slouken@1952
   222
slouken@3057
   223
    /* Initialize extensions */
slouken@3057
   224
    X11_GL_InitExtensions(_this);
slouken@3057
   225
slouken@1952
   226
    return 0;
slouken@1952
   227
}
slouken@1952
   228
slouken@1952
   229
void *
slouken@1952
   230
X11_GL_GetProcAddress(_THIS, const char *proc)
slouken@1952
   231
{
slouken@1952
   232
    if (_this->gl_data->glXGetProcAddress) {
slouken@1952
   233
        return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
slouken@1952
   234
    }
slouken@4550
   235
    return GL_LoadFunction(_this->gl_config.dll_handle, proc);
slouken@1952
   236
}
slouken@1952
   237
slouken@3057
   238
void
slouken@1952
   239
X11_GL_UnloadLibrary(_THIS)
slouken@1952
   240
{
slouken@3057
   241
    /* Don't actually unload the library, since it may have registered
slouken@3057
   242
     * X11 shutdown hooks, per the notes at:
slouken@3057
   243
     * http://dri.sourceforge.net/doc/DRIuserguide.html
slouken@3057
   244
     */
slouken@3057
   245
#if 0
slouken@3057
   246
    GL_UnloadObject(_this->gl_config.dll_handle);
slouken@3057
   247
    _this->gl_config.dll_handle = NULL;
slouken@3057
   248
#endif
slouken@3057
   249
slouken@3057
   250
    /* Free OpenGL memory */
slouken@6181
   251
    if (_this->gl_data) {
slouken@6181
   252
        SDL_free(_this->gl_data);
slouken@6181
   253
        _this->gl_data = NULL;
slouken@6181
   254
    }
slouken@1952
   255
}
slouken@1952
   256
slouken@1952
   257
static SDL_bool
slouken@1952
   258
HasExtension(const char *extension, const char *extensions)
slouken@1952
   259
{
slouken@1952
   260
    const char *start;
slouken@1952
   261
    const char *where, *terminator;
slouken@1952
   262
slouken@1952
   263
    /* Extension names should not have spaces. */
slouken@1952
   264
    where = SDL_strchr(extension, ' ');
slouken@1952
   265
    if (where || *extension == '\0')
slouken@1952
   266
        return SDL_FALSE;
slouken@1952
   267
slouken@1952
   268
    if (!extensions)
slouken@1952
   269
        return SDL_FALSE;
slouken@1952
   270
slouken@1952
   271
    /* It takes a bit of care to be fool-proof about parsing the
slouken@1952
   272
     * OpenGL extensions string. Don't be fooled by sub-strings,
slouken@1952
   273
     * etc. */
slouken@1952
   274
slouken@1952
   275
    start = extensions;
slouken@1952
   276
slouken@1952
   277
    for (;;) {
slouken@1952
   278
        where = SDL_strstr(start, extension);
slouken@1952
   279
        if (!where)
slouken@1952
   280
            break;
slouken@1952
   281
slouken@1952
   282
        terminator = where + SDL_strlen(extension);
slouken@1952
   283
        if (where == start || *(where - 1) == ' ')
slouken@1952
   284
            if (*terminator == ' ' || *terminator == '\0')
slouken@1952
   285
                return SDL_TRUE;
slouken@1952
   286
slouken@1952
   287
        start = terminator;
slouken@1952
   288
    }
slouken@1952
   289
    return SDL_FALSE;
slouken@1952
   290
}
slouken@1952
   291
slouken@1952
   292
static void
slouken@1952
   293
X11_GL_InitExtensions(_THIS)
slouken@1952
   294
{
slouken@1952
   295
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@5244
   296
    int screen = DefaultScreen(display);
slouken@1952
   297
    XVisualInfo *vinfo;
slouken@1952
   298
    XSetWindowAttributes xattr;
slouken@1952
   299
    Window w;
slouken@1952
   300
    GLXContext context;
slouken@1952
   301
    const char *(*glXQueryExtensionsStringFunc) (Display *, int);
slouken@1952
   302
    const char *extensions;
slouken@1952
   303
slouken@1952
   304
    vinfo = X11_GL_GetVisual(_this, display, screen);
slouken@1952
   305
    if (!vinfo) {
slouken@1952
   306
        return;
slouken@1952
   307
    }
slouken@1952
   308
    xattr.background_pixel = 0;
slouken@1952
   309
    xattr.border_pixel = 0;
slouken@1952
   310
    xattr.colormap =
slouken@1952
   311
        XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
slouken@1952
   312
                        AllocNone);
slouken@1952
   313
    w = XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
slouken@1952
   314
                      vinfo->depth, InputOutput, vinfo->visual,
slouken@1952
   315
                      (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
slouken@1952
   316
    context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
slouken@1952
   317
    if (context) {
slouken@1952
   318
        _this->gl_data->glXMakeCurrent(display, w, context);
slouken@1952
   319
    }
slouken@1952
   320
    XFree(vinfo);
slouken@1952
   321
slouken@1952
   322
    glXQueryExtensionsStringFunc =
slouken@1952
   323
        (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
slouken@1952
   324
                                                                "glXQueryExtensionsString");
slouken@1952
   325
    if (glXQueryExtensionsStringFunc) {
slouken@1952
   326
        extensions = glXQueryExtensionsStringFunc(display, screen);
slouken@1952
   327
    } else {
slouken@1952
   328
        extensions = NULL;
slouken@1952
   329
    }
slouken@1952
   330
icculus@6382
   331
    /* Check for GLX_EXT_swap_control(_tear) */
icculus@6382
   332
    _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
icculus@5572
   333
    if (HasExtension("GLX_EXT_swap_control", extensions)) {
icculus@5572
   334
        _this->gl_data->glXSwapIntervalEXT =
icculus@5630
   335
            (int (*)(Display*,GLXDrawable,int))
icculus@5572
   336
                X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
icculus@6382
   337
        if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
icculus@6382
   338
            _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
icculus@6382
   339
        }
slouken@1952
   340
    }
slouken@1952
   341
slouken@1952
   342
    /* Check for GLX_MESA_swap_control */
slouken@1952
   343
    if (HasExtension("GLX_MESA_swap_control", extensions)) {
slouken@1952
   344
        _this->gl_data->glXSwapIntervalMESA =
icculus@5572
   345
            (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
slouken@1952
   346
        _this->gl_data->glXGetSwapIntervalMESA =
icculus@5572
   347
            (int(*)(void)) X11_GL_GetProcAddress(_this,
slouken@1952
   348
                                                   "glXGetSwapIntervalMESA");
slouken@1952
   349
    }
slouken@1952
   350
icculus@5572
   351
    /* Check for GLX_SGI_swap_control */
icculus@5572
   352
    if (HasExtension("GLX_SGI_swap_control", extensions)) {
icculus@5572
   353
        _this->gl_data->glXSwapIntervalSGI =
icculus@5572
   354
            (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
icculus@5572
   355
    }
icculus@5572
   356
slouken@1952
   357
    /* Check for GLX_EXT_visual_rating */
slouken@1952
   358
    if (HasExtension("GLX_EXT_visual_rating", extensions)) {
slouken@1952
   359
        _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
slouken@1952
   360
    }
slouken@1952
   361
mikesart@6570
   362
    /* Check for GLX_EXT_visual_info */
mikesart@6570
   363
    if (HasExtension("GLX_EXT_visual_info", extensions)) {
mikesart@6570
   364
        _this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
mikesart@6570
   365
    }
mikesart@6570
   366
slouken@1952
   367
    if (context) {
slouken@1952
   368
        _this->gl_data->glXMakeCurrent(display, None, NULL);
slouken@1952
   369
        _this->gl_data->glXDestroyContext(display, context);
slouken@1952
   370
    }
slouken@1952
   371
    XDestroyWindow(display, w);
bob@2323
   372
    X11_PumpEvents(_this);
slouken@1952
   373
}
slouken@1952
   374
slouken@6296
   375
/* glXChooseVisual and glXChooseFBConfig have some small differences in
slouken@6296
   376
 * the attribute encoding, it can be chosen with the for_FBConfig parameter. 
slouken@6296
   377
 */
slouken@5395
   378
int 
slouken@6296
   379
X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
slouken@1952
   380
{
slouken@5395
   381
    int i = 0;
mikesart@6570
   382
	const int MAX_ATTRIBUTES = 64;
slouken@1952
   383
slouken@5395
   384
    /* assert buffer is large enough to hold all SDL attributes. */ 
mikesart@6570
   385
    SDL_assert(size >= MAX_ATTRIBUTES);
slouken@3139
   386
slouken@1952
   387
    /* Setup our GLX attributes according to the gl_config. */
slouken@6296
   388
    if( for_FBConfig ) {
slouken@6296
   389
        attribs[i++] = GLX_RENDER_TYPE;
slouken@6296
   390
	attribs[i++] = GLX_RGBA_BIT;
slouken@6296
   391
    } else {
slouken@6296
   392
        attribs[i++] = GLX_RGBA;
slouken@6296
   393
    }
slouken@1952
   394
    attribs[i++] = GLX_RED_SIZE;
slouken@1952
   395
    attribs[i++] = _this->gl_config.red_size;
slouken@1952
   396
    attribs[i++] = GLX_GREEN_SIZE;
slouken@1952
   397
    attribs[i++] = _this->gl_config.green_size;
slouken@1952
   398
    attribs[i++] = GLX_BLUE_SIZE;
slouken@1952
   399
    attribs[i++] = _this->gl_config.blue_size;
slouken@1952
   400
slouken@1952
   401
    if (_this->gl_config.alpha_size) {
slouken@1952
   402
        attribs[i++] = GLX_ALPHA_SIZE;
slouken@1952
   403
        attribs[i++] = _this->gl_config.alpha_size;
slouken@1952
   404
    }
slouken@1952
   405
slouken@1952
   406
    if (_this->gl_config.double_buffer) {
slouken@1952
   407
        attribs[i++] = GLX_DOUBLEBUFFER;
slouken@6296
   408
	if( for_FBConfig )
slouken@6296
   409
	    attribs[i++] = True;
slouken@1952
   410
    }
slouken@1952
   411
slouken@1952
   412
    attribs[i++] = GLX_DEPTH_SIZE;
slouken@1952
   413
    attribs[i++] = _this->gl_config.depth_size;
slouken@1952
   414
slouken@1952
   415
    if (_this->gl_config.stencil_size) {
slouken@1952
   416
        attribs[i++] = GLX_STENCIL_SIZE;
slouken@1952
   417
        attribs[i++] = _this->gl_config.stencil_size;
slouken@1952
   418
    }
slouken@1952
   419
slouken@1952
   420
    if (_this->gl_config.accum_red_size) {
slouken@1952
   421
        attribs[i++] = GLX_ACCUM_RED_SIZE;
slouken@1952
   422
        attribs[i++] = _this->gl_config.accum_red_size;
slouken@1952
   423
    }
slouken@1952
   424
slouken@1952
   425
    if (_this->gl_config.accum_green_size) {
slouken@1952
   426
        attribs[i++] = GLX_ACCUM_GREEN_SIZE;
slouken@1952
   427
        attribs[i++] = _this->gl_config.accum_green_size;
slouken@1952
   428
    }
slouken@1952
   429
slouken@1952
   430
    if (_this->gl_config.accum_blue_size) {
slouken@1952
   431
        attribs[i++] = GLX_ACCUM_BLUE_SIZE;
slouken@1952
   432
        attribs[i++] = _this->gl_config.accum_blue_size;
slouken@1952
   433
    }
slouken@1952
   434
slouken@1952
   435
    if (_this->gl_config.accum_alpha_size) {
slouken@1952
   436
        attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
slouken@1952
   437
        attribs[i++] = _this->gl_config.accum_alpha_size;
slouken@1952
   438
    }
slouken@1952
   439
slouken@1952
   440
    if (_this->gl_config.stereo) {
slouken@1952
   441
        attribs[i++] = GLX_STEREO;
slouken@6296
   442
	if( for_FBConfig )
slouken@6296
   443
	    attribs[i++] = True;
slouken@1952
   444
    }
slouken@1952
   445
slouken@1952
   446
    if (_this->gl_config.multisamplebuffers) {
slouken@1952
   447
        attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
slouken@1952
   448
        attribs[i++] = _this->gl_config.multisamplebuffers;
slouken@1952
   449
    }
slouken@1952
   450
slouken@1952
   451
    if (_this->gl_config.multisamplesamples) {
slouken@1952
   452
        attribs[i++] = GLX_SAMPLES_ARB;
slouken@1952
   453
        attribs[i++] = _this->gl_config.multisamplesamples;
slouken@1952
   454
    }
slouken@1952
   455
slouken@3571
   456
    if (_this->gl_config.accelerated >= 0 &&
slouken@3571
   457
        _this->gl_data->HAS_GLX_EXT_visual_rating) {
slouken@1952
   458
        attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
slouken@3570
   459
        attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
slouken@3570
   460
                                                      GLX_SLOW_VISUAL_EXT;
slouken@1952
   461
    }
slouken@3570
   462
mikesart@6570
   463
    // If we're supposed to use DirectColor visuals, and we've got the EXT_visual_info
mikesart@6570
   464
    //  extension, then add GLX_X_VISUAL_TYPE_EXT.
mikesart@6570
   465
    if (X11_UseDirectColorVisuals() &&
mikesart@6570
   466
        _this->gl_data->HAS_GLX_EXT_visual_info) {
mikesart@6570
   467
        attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
mikesart@6570
   468
        attribs[i++] = GLX_DIRECT_COLOR_EXT;
mikesart@6570
   469
    }
mikesart@6570
   470
slouken@1952
   471
    attribs[i++] = None;
mikesart@6570
   472
mikesart@6570
   473
    SDL_assert(i <= MAX_ATTRIBUTES);
slouken@5395
   474
 
slouken@5395
   475
    return i;
slouken@5395
   476
}
slouken@5395
   477
slouken@5395
   478
XVisualInfo *
slouken@5395
   479
X11_GL_GetVisual(_THIS, Display * display, int screen)
slouken@5395
   480
{
slouken@5395
   481
    XVisualInfo *vinfo;
slouken@5395
   482
slouken@5395
   483
    /* 64 seems nice. */
slouken@6296
   484
    int attribs[64];
icculus@6359
   485
    X11_GL_GetAttributes(_this,display,screen,attribs,64,SDL_FALSE);
slouken@1952
   486
slouken@6181
   487
    if (!_this->gl_data) {
slouken@6181
   488
        /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
slouken@6181
   489
        return NULL;
slouken@6181
   490
    }
slouken@6181
   491
slouken@1952
   492
    vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
slouken@1952
   493
    if (!vinfo) {
slouken@1952
   494
        SDL_SetError("Couldn't find matching GLX visual");
slouken@1952
   495
    }
slouken@1952
   496
    return vinfo;
slouken@1952
   497
}
slouken@1952
   498
slouken@1952
   499
SDL_GLContext
slouken@1952
   500
X11_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1952
   501
{
slouken@1952
   502
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1952
   503
    Display *display = data->videodata->display;
slouken@1952
   504
    int screen =
slouken@5246
   505
        ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
slouken@1952
   506
    XWindowAttributes xattr;
slouken@1952
   507
    XVisualInfo v, *vinfo;
slouken@1952
   508
    int n;
slouken@6393
   509
    GLXContext context = NULL, share_context;
slouken@6393
   510
slouken@6393
   511
    if (_this->gl_config.share_with_current_context) {
slouken@6393
   512
        share_context = (GLXContext)(_this->current_glctx);
slouken@6393
   513
    } else {
slouken@6393
   514
        share_context = NULL;
slouken@6393
   515
    }
slouken@1952
   516
slouken@1955
   517
    /* We do this to create a clean separation between X and GLX errors. */
slouken@1952
   518
    XSync(display, False);
slouken@3685
   519
    XGetWindowAttributes(display, data->xwindow, &xattr);
slouken@1952
   520
    v.screen = screen;
slouken@1952
   521
    v.visualid = XVisualIDFromVisual(xattr.visual);
slouken@1952
   522
    vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
slouken@1952
   523
    if (vinfo) {
slouken@6393
   524
        if (_this->gl_config.major_version < 3 &&
slouken@6393
   525
            _this->gl_config.profile_mask == 0 &&
slouken@6393
   526
            _this->gl_config.flags == 0) {
slouken@6393
   527
            /* Create legacy context */
slouken@3100
   528
            context =
slouken@6393
   529
                _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
slouken@3100
   530
        } else {
slouken@3100
   531
            /* If we want a GL 3.0 context or later we need to get a temporary
slouken@3100
   532
               context to grab the new context creation function */
slouken@3139
   533
            GLXContext temp_context =
slouken@3139
   534
                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
slouken@3100
   535
            if (!temp_context) {
slouken@3139
   536
                SDL_SetError("Could not create GL context");
slouken@3100
   537
                return NULL;
slouken@3100
   538
            } else {
slouken@6393
   539
                /* max 8 attributes plus terminator */
slouken@6296
   540
                int attribs[9] = {
slouken@3139
   541
                    GLX_CONTEXT_MAJOR_VERSION_ARB,
slouken@3139
   542
                    _this->gl_config.major_version,
slouken@3139
   543
                    GLX_CONTEXT_MINOR_VERSION_ARB,
slouken@3139
   544
                    _this->gl_config.minor_version,
slouken@3139
   545
                    0
slouken@3100
   546
                };
slouken@6393
   547
                int iattr = 4;
slouken@6296
   548
slouken@6393
   549
                /* SDL profile bits match GLX profile bits */
slouken@6393
   550
                if( _this->gl_config.profile_mask != 0 ) {
slouken@6393
   551
                    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
slouken@6393
   552
                    attribs[iattr++] = _this->gl_config.profile_mask;
slouken@6393
   553
                }
slouken@6296
   554
slouken@6393
   555
                /* SDL flags match GLX flags */
slouken@6393
   556
                if( _this->gl_config.flags != 0 ) {
slouken@6393
   557
                    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
slouken@6393
   558
                    attribs[iattr++] = _this->gl_config.flags;
slouken@6393
   559
                }
slouken@6296
   560
slouken@6393
   561
                attribs[iattr++] = 0;
slouken@3139
   562
slouken@3100
   563
                /* Get a pointer to the context creation function for GL 3.0 */
slouken@3139
   564
                PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
slouken@3139
   565
                    (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
slouken@3139
   566
                    glXGetProcAddress((GLubyte *)
slouken@3139
   567
                                      "glXCreateContextAttribsARB");
slouken@3100
   568
                if (!glXCreateContextAttribs) {
slouken@3100
   569
                    SDL_SetError("GL 3.x is not supported");
slouken@3100
   570
                    context = temp_context;
slouken@3100
   571
                } else {
slouken@5395
   572
                    int glxAttribs[64];
slouken@5395
   573
slouken@3105
   574
                    /* Create a GL 3.x context */
slouken@3100
   575
                    GLXFBConfig *framebuffer_config = NULL;
slouken@3139
   576
                    int fbcount = 0;
slouken@3139
   577
                    GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
slouken@3139
   578
                                                       int screen,
slouken@3139
   579
                                                       const int *attrib_list,
slouken@3139
   580
                                                       int *nelements);
slouken@3105
   581
slouken@3139
   582
                    glXChooseFBConfig =
slouken@3139
   583
                        (GLXFBConfig *
slouken@3139
   584
                         (*)(Display *, int, const int *,
slouken@3139
   585
                             int *)) _this->gl_data->
slouken@3139
   586
                        glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
slouken@3105
   587
slouken@6296
   588
                    X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
slouken@5395
   589
slouken@3139
   590
                    if (!glXChooseFBConfig
slouken@3139
   591
                        || !(framebuffer_config =
slouken@3139
   592
                             glXChooseFBConfig(display,
slouken@5395
   593
                                               DefaultScreen(display), glxAttribs,
slouken@3139
   594
                                               &fbcount))) {
slouken@3139
   595
                        SDL_SetError
slouken@3139
   596
                            ("No good framebuffers found. GL 3.x disabled");
slouken@3100
   597
                        context = temp_context;
slouken@3139
   598
                    } else {
slouken@3139
   599
                        context =
slouken@3139
   600
                            glXCreateContextAttribs(display,
slouken@3139
   601
                                                    framebuffer_config[0],
slouken@6393
   602
                                                    share_context, True, attribs);
slouken@3139
   603
                        _this->gl_data->glXDestroyContext(display,
slouken@3139
   604
                                                          temp_context);
slouken@3100
   605
                    }
slouken@3100
   606
                }
slouken@3100
   607
            }
slouken@3100
   608
        }
slouken@1952
   609
        XFree(vinfo);
slouken@1952
   610
    }
slouken@1952
   611
    XSync(display, False);
slouken@1952
   612
slouken@1952
   613
    if (!context) {
slouken@1952
   614
        SDL_SetError("Could not create GL context");
slouken@2178
   615
        return NULL;
slouken@1952
   616
    }
slouken@2178
   617
slouken@2178
   618
    if (X11_GL_MakeCurrent(_this, window, context) < 0) {
slouken@2178
   619
        X11_GL_DeleteContext(_this, context);
slouken@2178
   620
        return NULL;
slouken@2178
   621
    }
slouken@2178
   622
slouken@2178
   623
    return context;
slouken@1952
   624
}
slouken@1952
   625
slouken@1952
   626
int
slouken@1952
   627
X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1952
   628
{
slouken@1952
   629
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@1952
   630
    Window drawable =
slouken@3685
   631
        (window ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
slouken@1952
   632
    GLXContext glx_context = (GLXContext) context;
slouken@1952
   633
    int status;
slouken@1952
   634
slouken@6522
   635
    if (!_this->gl_data) {
slouken@6522
   636
        SDL_SetError("OpenGL not initialized");
slouken@6522
   637
        return -1;
slouken@6522
   638
    }
slouken@6522
   639
slouken@1952
   640
    status = 0;
slouken@1952
   641
    if (!_this->gl_data->glXMakeCurrent(display, drawable, glx_context)) {
slouken@1952
   642
        SDL_SetError("Unable to make GL context current");
slouken@1952
   643
        status = -1;
slouken@1952
   644
    }
slouken@1952
   645
    XSync(display, False);
slouken@1952
   646
slouken@1952
   647
    return (status);
slouken@1952
   648
}
slouken@1952
   649
bob@2327
   650
/* 
icculus@5572
   651
   0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
icculus@5572
   652
   will undo the effect of a previous call with a value that is greater
icculus@5572
   653
   than zero (or at least that is what the docs say). OTOH, 0 is an invalid
icculus@5572
   654
   argument to glxSwapIntervalSGI and it returns an error if you call it
icculus@5572
   655
   with 0 as an argument.
bob@2327
   656
*/
bob@2327
   657
bob@2327
   658
static int swapinterval = -1;
slouken@1952
   659
int
slouken@1952
   660
X11_GL_SetSwapInterval(_THIS, int interval)
slouken@1952
   661
{
icculus@6382
   662
    int status = -1;
slouken@1952
   663
icculus@6382
   664
    if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) {
icculus@6382
   665
        SDL_SetError("Negative swap interval unsupported in this GL");
icculus@6382
   666
    } else if (_this->gl_data->glXSwapIntervalEXT) {
icculus@5572
   667
        Display *display = ((SDL_VideoData *) _this->driverdata)->display;
icculus@5572
   668
        const SDL_WindowData *windowdata = (SDL_WindowData *)
icculus@5572
   669
            _this->current_glwin->driverdata;
icculus@5572
   670
        Window drawable = windowdata->xwindow;
icculus@5630
   671
        status = _this->gl_data->glXSwapIntervalEXT(display,drawable,interval);
icculus@5630
   672
        if (status != 0) {
icculus@5630
   673
            SDL_SetError("glxSwapIntervalEXT failed");
icculus@5630
   674
        } else {
icculus@5630
   675
            swapinterval = interval;
icculus@5630
   676
        }
icculus@5572
   677
    } else if (_this->gl_data->glXSwapIntervalMESA) {
slouken@1952
   678
        status = _this->gl_data->glXSwapIntervalMESA(interval);
slouken@1952
   679
        if (status != 0) {
slouken@1952
   680
            SDL_SetError("glxSwapIntervalMESA failed");
bob@2327
   681
        } else {
bob@2327
   682
            swapinterval = interval;
slouken@1952
   683
        }
slouken@1952
   684
    } else if (_this->gl_data->glXSwapIntervalSGI) {
slouken@1952
   685
        status = _this->gl_data->glXSwapIntervalSGI(interval);
slouken@1952
   686
        if (status != 0) {
slouken@1952
   687
            SDL_SetError("glxSwapIntervalSGI failed");
bob@2327
   688
        } else {
bob@2327
   689
            swapinterval = interval;
slouken@1952
   690
        }
slouken@1952
   691
    } else {
slouken@1952
   692
        SDL_Unsupported();
slouken@1952
   693
    }
slouken@1952
   694
    return status;
slouken@1952
   695
}
slouken@1952
   696
slouken@1952
   697
int
slouken@1952
   698
X11_GL_GetSwapInterval(_THIS)
slouken@1952
   699
{
icculus@5572
   700
    if (_this->gl_data->glXSwapIntervalEXT) {
icculus@5572
   701
        Display *display = ((SDL_VideoData *) _this->driverdata)->display;
icculus@5572
   702
        const SDL_WindowData *windowdata = (SDL_WindowData *)
icculus@5572
   703
            _this->current_glwin->driverdata;
icculus@5572
   704
        Window drawable = windowdata->xwindow;
icculus@6382
   705
        unsigned int allow_late_swap_tearing = 0;
icculus@6382
   706
        unsigned int interval = 0;
icculus@6382
   707
icculus@6382
   708
        if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
icculus@6382
   709
            _this->gl_data->glXQueryDrawable(display, drawable,
icculus@6382
   710
                                            GLX_LATE_SWAPS_TEAR_EXT,
icculus@6382
   711
                                            &allow_late_swap_tearing);
icculus@6382
   712
        }
icculus@6382
   713
icculus@5572
   714
        _this->gl_data->glXQueryDrawable(display, drawable,
icculus@6382
   715
                                         GLX_SWAP_INTERVAL_EXT, &interval);
icculus@6382
   716
icculus@6382
   717
        if ((allow_late_swap_tearing) && (interval > 0)) {
icculus@6382
   718
            return -((int) interval);
icculus@6382
   719
        }
icculus@6382
   720
icculus@6382
   721
        return (int) interval;
icculus@5572
   722
    } else if (_this->gl_data->glXGetSwapIntervalMESA) {
slouken@1952
   723
        return _this->gl_data->glXGetSwapIntervalMESA();
slouken@1952
   724
    } else {
bob@2327
   725
        return swapinterval;
slouken@1952
   726
    }
slouken@1952
   727
}
slouken@1952
   728
slouken@1952
   729
void
slouken@1952
   730
X11_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1952
   731
{
slouken@1952
   732
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1952
   733
    Display *display = data->videodata->display;
slouken@1952
   734
slouken@3685
   735
    _this->gl_data->glXSwapBuffers(display, data->xwindow);
slouken@1952
   736
}
slouken@1952
   737
slouken@1952
   738
void
slouken@1952
   739
X11_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1952
   740
{
slouken@1952
   741
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@1952
   742
    GLXContext glx_context = (GLXContext) context;
slouken@1952
   743
slouken@6522
   744
    if (!_this->gl_data) {
slouken@6522
   745
        return;
slouken@6522
   746
    }
slouken@1952
   747
    _this->gl_data->glXDestroyContext(display, glx_context);
bob@2324
   748
    XSync(display, False);
slouken@1952
   749
}
slouken@1952
   750
slouken@1952
   751
#endif /* SDL_VIDEO_OPENGL_GLX */
slouken@1952
   752
slouken@6044
   753
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@6044
   754
slouken@1952
   755
/* vi: set ts=4 sw=4 expandtab: */