src/video/windows/SDL_windowsopengl.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 11 Jul 2013 22:59:20 -0700
changeset 7412 50211a1fd557
parent 7401 698995795574
child 7553 f0091f8eae33
permissions -rw-r--r--
Fixed bug 1946 - OpenGL contexts in threads

The SDL OpenGL context code is now properly thread aware. There are two new functions which return the current OpenGL window and context for the current thread.

There are still places in the cocoa driver where the OpenGL context needs to be updated when the view changes. These will need a different solution and still use the last globally set context to avoid changing behavior.
slouken@1913
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@1913
     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@1913
     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@1913
    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@1913
    20
*/
slouken@1913
    21
#include "SDL_config.h"
slouken@1913
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_WINDOWS
slouken@6044
    24
slouken@5062
    25
#include "SDL_windowsvideo.h"
slouken@1913
    26
slouken@1913
    27
/* WGL implementation of SDL OpenGL support */
slouken@1913
    28
slouken@1952
    29
#if SDL_VIDEO_OPENGL_WGL
slouken@1913
    30
#include "SDL_opengl.h"
slouken@1913
    31
slouken@1952
    32
#define DEFAULT_OPENGL "OPENGL32.DLL"
slouken@1913
    33
slouken@3100
    34
#ifndef WGL_ARB_create_context
slouken@3100
    35
#define WGL_ARB_create_context
slouken@3100
    36
#define WGL_CONTEXT_MAJOR_VERSION_ARB   0x2091
slouken@3100
    37
#define WGL_CONTEXT_MINOR_VERSION_ARB   0x2092
slouken@3100
    38
#define WGL_CONTEXT_LAYER_PLANE_ARB     0x2093
kajetan@6380
    39
#define WGL_CONTEXT_FLAGS_ARB           0x2094
slouken@3100
    40
#define WGL_CONTEXT_DEBUG_BIT_ARB       0x0001
slouken@3100
    41
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
slouken@6296
    42
slouken@6296
    43
#ifndef WGL_ARB_create_context_profile
slouken@6296
    44
#define WGL_ARB_create_context_profile
slouken@6296
    45
#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
slouken@6296
    46
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
slouken@6296
    47
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
slouken@6296
    48
#endif
slouken@6296
    49
slouken@6296
    50
#ifndef WGL_ARB_create_context_robustness
slouken@6296
    51
#define WGL_ARB_create_context_robustness
slouken@6296
    52
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB         0x00000004
slouken@6296
    53
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB     0x8256
slouken@6296
    54
#define WGL_NO_RESET_NOTIFICATION_ARB                   0x8261
slouken@6296
    55
#define WGL_LOSE_CONTEXT_ON_RESET_ARB                   0x8252
slouken@6296
    56
#endif
slouken@6296
    57
#endif
slouken@6296
    58
slouken@6296
    59
#ifndef WGL_EXT_create_context_es2_profile
slouken@6296
    60
#define WGL_EXT_create_context_es2_profile
slouken@6296
    61
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT           0x00000004
slouken@3100
    62
#endif
slouken@3100
    63
slouken@6393
    64
#ifndef WGL_EXT_create_context_es_profile
slouken@6393
    65
#define WGL_EXT_create_context_es_profile
slouken@6393
    66
#define WGL_CONTEXT_ES_PROFILE_BIT_EXT            0x00000004
slouken@6393
    67
#endif
slouken@6393
    68
slouken@3139
    69
typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
slouken@3139
    70
                                                            HGLRC
slouken@3139
    71
                                                            hShareContext,
slouken@3139
    72
                                                            const int
slouken@3139
    73
                                                            *attribList);
slouken@1913
    74
slouken@1913
    75
int
slouken@1913
    76
WIN_GL_LoadLibrary(_THIS, const char *path)
slouken@1913
    77
{
slouken@1913
    78
    LPTSTR wpath;
slouken@1913
    79
    HANDLE handle;
slouken@1913
    80
slouken@1913
    81
    if (path == NULL) {
slouken@1952
    82
        path = SDL_getenv("SDL_OPENGL_LIBRARY");
slouken@1952
    83
    }
slouken@1952
    84
    if (path == NULL) {
slouken@1952
    85
        path = DEFAULT_OPENGL;
slouken@1913
    86
    }
slouken@1913
    87
    wpath = WIN_UTF8ToString(path);
slouken@3057
    88
    _this->gl_config.dll_handle = LoadLibrary(wpath);
slouken@1913
    89
    SDL_free(wpath);
slouken@3057
    90
    if (!_this->gl_config.dll_handle) {
slouken@1913
    91
        char message[1024];
slouken@1913
    92
        SDL_snprintf(message, SDL_arraysize(message), "LoadLibrary(\"%s\")",
slouken@1913
    93
                     path);
icculus@7037
    94
        return WIN_SetError(message);
slouken@1913
    95
    }
slouken@3057
    96
    SDL_strlcpy(_this->gl_config.driver_path, path,
slouken@3057
    97
                SDL_arraysize(_this->gl_config.driver_path));
slouken@3057
    98
slouken@3057
    99
    /* Allocate OpenGL memory */
slouken@3057
   100
    _this->gl_data =
slouken@3057
   101
        (struct SDL_GLDriverData *) SDL_calloc(1,
slouken@3057
   102
                                               sizeof(struct
slouken@3057
   103
                                                      SDL_GLDriverData));
slouken@3057
   104
    if (!_this->gl_data) {
icculus@7037
   105
        return SDL_OutOfMemory();
slouken@3057
   106
    }
slouken@1913
   107
slouken@1913
   108
    /* Load function pointers */
slouken@3057
   109
    handle = _this->gl_config.dll_handle;
slouken@1913
   110
    _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
slouken@1913
   111
        GetProcAddress(handle, "wglGetProcAddress");
slouken@1913
   112
    _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
slouken@1913
   113
        GetProcAddress(handle, "wglCreateContext");
slouken@1913
   114
    _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
slouken@1913
   115
        GetProcAddress(handle, "wglDeleteContext");
slouken@1913
   116
    _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
slouken@1913
   117
        GetProcAddress(handle, "wglMakeCurrent");
slouken@6393
   118
    _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
slouken@6393
   119
        GetProcAddress(handle, "wglShareLists");
slouken@1913
   120
slouken@1913
   121
    if (!_this->gl_data->wglGetProcAddress ||
slouken@1913
   122
        !_this->gl_data->wglCreateContext ||
slouken@1913
   123
        !_this->gl_data->wglDeleteContext ||
slouken@1913
   124
        !_this->gl_data->wglMakeCurrent) {
slouken@5090
   125
        SDL_UnloadObject(handle);
icculus@7037
   126
        return SDL_SetError("Could not retrieve OpenGL functions");
slouken@1913
   127
    }
slouken@1913
   128
slouken@1913
   129
    return 0;
slouken@1913
   130
}
slouken@1913
   131
slouken@1913
   132
void *
slouken@1913
   133
WIN_GL_GetProcAddress(_THIS, const char *proc)
slouken@1913
   134
{
slouken@1913
   135
    void *func;
slouken@1913
   136
slouken@1913
   137
    /* This is to pick up extensions */
slouken@1913
   138
    func = _this->gl_data->wglGetProcAddress(proc);
slouken@1913
   139
    if (!func) {
slouken@1913
   140
        /* This is probably a normal GL function */
slouken@1913
   141
        func = GetProcAddress(_this->gl_config.dll_handle, proc);
slouken@1913
   142
    }
slouken@1913
   143
    return func;
slouken@1913
   144
}
slouken@1913
   145
slouken@3057
   146
void
slouken@1913
   147
WIN_GL_UnloadLibrary(_THIS)
slouken@1913
   148
{
slouken@3057
   149
    FreeLibrary((HMODULE) _this->gl_config.dll_handle);
slouken@3057
   150
    _this->gl_config.dll_handle = NULL;
slouken@3057
   151
slouken@3057
   152
    /* Free OpenGL memory */
slouken@3057
   153
    SDL_free(_this->gl_data);
slouken@3057
   154
    _this->gl_data = NULL;
slouken@1913
   155
}
slouken@1913
   156
slouken@1913
   157
static void
slouken@1913
   158
WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd)
slouken@1913
   159
{
slouken@1913
   160
    SDL_zerop(pfd);
slouken@1913
   161
    pfd->nSize = sizeof(*pfd);
slouken@1913
   162
    pfd->nVersion = 1;
slouken@1913
   163
    pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
slouken@1913
   164
    if (_this->gl_config.double_buffer) {
slouken@1913
   165
        pfd->dwFlags |= PFD_DOUBLEBUFFER;
slouken@1913
   166
    }
slouken@1913
   167
    if (_this->gl_config.stereo) {
slouken@1913
   168
        pfd->dwFlags |= PFD_STEREO;
slouken@1913
   169
    }
slouken@1913
   170
    pfd->iLayerType = PFD_MAIN_PLANE;
slouken@1913
   171
    pfd->iPixelType = PFD_TYPE_RGBA;
slouken@1913
   172
    pfd->cRedBits = _this->gl_config.red_size;
slouken@1913
   173
    pfd->cGreenBits = _this->gl_config.green_size;
slouken@1913
   174
    pfd->cBlueBits = _this->gl_config.blue_size;
slouken@1913
   175
    pfd->cAlphaBits = _this->gl_config.alpha_size;
slouken@1913
   176
    if (_this->gl_config.buffer_size) {
slouken@1913
   177
        pfd->cColorBits =
slouken@1913
   178
            _this->gl_config.buffer_size - _this->gl_config.alpha_size;
slouken@1913
   179
    } else {
slouken@1913
   180
        pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits);
slouken@1913
   181
    }
slouken@1913
   182
    pfd->cAccumRedBits = _this->gl_config.accum_red_size;
slouken@1913
   183
    pfd->cAccumGreenBits = _this->gl_config.accum_green_size;
slouken@1913
   184
    pfd->cAccumBlueBits = _this->gl_config.accum_blue_size;
slouken@1913
   185
    pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size;
slouken@1913
   186
    pfd->cAccumBits =
slouken@1913
   187
        (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits +
slouken@1913
   188
         pfd->cAccumAlphaBits);
slouken@1913
   189
    pfd->cDepthBits = _this->gl_config.depth_size;
slouken@1913
   190
    pfd->cStencilBits = _this->gl_config.stencil_size;
slouken@1913
   191
}
slouken@1913
   192
slouken@2150
   193
/* Choose the closest pixel format that meets or exceeds the target.
slouken@2150
   194
   FIXME: Should we weight any particular attribute over any other?
slouken@2150
   195
*/
slouken@2150
   196
static int
slouken@2150
   197
WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target)
slouken@2150
   198
{
slouken@2150
   199
    PIXELFORMATDESCRIPTOR pfd;
slouken@2150
   200
    int count, index, best = 0;
slouken@2150
   201
    unsigned int dist, best_dist = ~0U;
slouken@2150
   202
slouken@2150
   203
    count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL);
slouken@2150
   204
slouken@2150
   205
    for (index = 1; index <= count; index++) {
slouken@2150
   206
slouken@2150
   207
        if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) {
slouken@2150
   208
            continue;
slouken@2150
   209
        }
slouken@2150
   210
slouken@2150
   211
        if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) {
slouken@2150
   212
            continue;
slouken@2150
   213
        }
slouken@2150
   214
slouken@2150
   215
        if (pfd.iLayerType != target->iLayerType) {
slouken@2150
   216
            continue;
slouken@2150
   217
        }
slouken@2150
   218
        if (pfd.iPixelType != target->iPixelType) {
slouken@2150
   219
            continue;
slouken@2150
   220
        }
slouken@2150
   221
slouken@2150
   222
        dist = 0;
slouken@2150
   223
slouken@2150
   224
        if (pfd.cColorBits < target->cColorBits) {
slouken@2150
   225
            continue;
slouken@2150
   226
        } else {
slouken@2150
   227
            dist += (pfd.cColorBits - target->cColorBits);
slouken@2150
   228
        }
slouken@2150
   229
        if (pfd.cRedBits < target->cRedBits) {
slouken@2150
   230
            continue;
slouken@2150
   231
        } else {
slouken@2150
   232
            dist += (pfd.cRedBits - target->cRedBits);
slouken@2150
   233
        }
slouken@2150
   234
        if (pfd.cGreenBits < target->cGreenBits) {
slouken@2150
   235
            continue;
slouken@2150
   236
        } else {
slouken@2150
   237
            dist += (pfd.cGreenBits - target->cGreenBits);
slouken@2150
   238
        }
slouken@2150
   239
        if (pfd.cBlueBits < target->cBlueBits) {
slouken@2150
   240
            continue;
slouken@2150
   241
        } else {
slouken@2150
   242
            dist += (pfd.cBlueBits - target->cBlueBits);
slouken@2150
   243
        }
slouken@2150
   244
        if (pfd.cAlphaBits < target->cAlphaBits) {
slouken@2150
   245
            continue;
slouken@2150
   246
        } else {
slouken@2150
   247
            dist += (pfd.cAlphaBits - target->cAlphaBits);
slouken@2150
   248
        }
slouken@2150
   249
        if (pfd.cAccumBits < target->cAccumBits) {
slouken@2150
   250
            continue;
slouken@2150
   251
        } else {
slouken@2150
   252
            dist += (pfd.cAccumBits - target->cAccumBits);
slouken@2150
   253
        }
slouken@2150
   254
        if (pfd.cAccumRedBits < target->cAccumRedBits) {
slouken@2150
   255
            continue;
slouken@2150
   256
        } else {
slouken@2150
   257
            dist += (pfd.cAccumRedBits - target->cAccumRedBits);
slouken@2150
   258
        }
slouken@2150
   259
        if (pfd.cAccumGreenBits < target->cAccumGreenBits) {
slouken@2150
   260
            continue;
slouken@2150
   261
        } else {
slouken@2150
   262
            dist += (pfd.cAccumGreenBits - target->cAccumGreenBits);
slouken@2150
   263
        }
slouken@2150
   264
        if (pfd.cAccumBlueBits < target->cAccumBlueBits) {
slouken@2150
   265
            continue;
slouken@2150
   266
        } else {
slouken@2150
   267
            dist += (pfd.cAccumBlueBits - target->cAccumBlueBits);
slouken@2150
   268
        }
slouken@2150
   269
        if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) {
slouken@2150
   270
            continue;
slouken@2150
   271
        } else {
slouken@2150
   272
            dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits);
slouken@2150
   273
        }
slouken@2150
   274
        if (pfd.cDepthBits < target->cDepthBits) {
slouken@2150
   275
            continue;
slouken@2150
   276
        } else {
slouken@2150
   277
            dist += (pfd.cDepthBits - target->cDepthBits);
slouken@2150
   278
        }
slouken@2150
   279
        if (pfd.cStencilBits < target->cStencilBits) {
slouken@2150
   280
            continue;
slouken@2150
   281
        } else {
slouken@2150
   282
            dist += (pfd.cStencilBits - target->cStencilBits);
slouken@2150
   283
        }
slouken@2150
   284
slouken@2150
   285
        if (dist < best_dist) {
slouken@2150
   286
            best = index;
slouken@2150
   287
            best_dist = dist;
slouken@2150
   288
        }
slouken@2150
   289
    }
slouken@2150
   290
slouken@2150
   291
    return best;
slouken@2150
   292
}
slouken@2150
   293
slouken@1913
   294
static SDL_bool
slouken@1913
   295
HasExtension(const char *extension, const char *extensions)
slouken@1913
   296
{
slouken@1913
   297
    const char *start;
slouken@1913
   298
    const char *where, *terminator;
slouken@1913
   299
slouken@1913
   300
    /* Extension names should not have spaces. */
slouken@1913
   301
    where = SDL_strchr(extension, ' ');
slouken@1913
   302
    if (where || *extension == '\0')
slouken@1913
   303
        return SDL_FALSE;
slouken@1913
   304
slouken@1913
   305
    if (!extensions)
slouken@1913
   306
        return SDL_FALSE;
slouken@1913
   307
slouken@1913
   308
    /* It takes a bit of care to be fool-proof about parsing the
slouken@1913
   309
     * OpenGL extensions string. Don't be fooled by sub-strings,
slouken@1913
   310
     * etc. */
slouken@1913
   311
slouken@1913
   312
    start = extensions;
slouken@1913
   313
slouken@1913
   314
    for (;;) {
slouken@1913
   315
        where = SDL_strstr(start, extension);
slouken@1913
   316
        if (!where)
slouken@1913
   317
            break;
slouken@1913
   318
slouken@1913
   319
        terminator = where + SDL_strlen(extension);
slouken@1913
   320
        if (where == start || *(where - 1) == ' ')
slouken@1913
   321
            if (*terminator == ' ' || *terminator == '\0')
slouken@1913
   322
                return SDL_TRUE;
slouken@1913
   323
slouken@1913
   324
        start = terminator;
slouken@1913
   325
    }
slouken@1913
   326
    return SDL_FALSE;
slouken@1913
   327
}
slouken@1913
   328
slouken@1913
   329
static void
slouken@2178
   330
WIN_GL_InitExtensions(_THIS, HDC hdc)
slouken@1913
   331
{
slouken@1913
   332
    const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
slouken@1913
   333
    const char *extensions;
slouken@1913
   334
slouken@1913
   335
    wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
slouken@1913
   336
        _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
slouken@1913
   337
    if (wglGetExtensionsStringARB) {
slouken@1913
   338
        extensions = wglGetExtensionsStringARB(hdc);
slouken@1913
   339
    } else {
slouken@1913
   340
        extensions = NULL;
slouken@1913
   341
    }
slouken@1913
   342
slouken@1913
   343
    /* Check for WGL_ARB_pixel_format */
icculus@6382
   344
    _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE;
slouken@1913
   345
    if (HasExtension("WGL_ARB_pixel_format", extensions)) {
slouken@1913
   346
        _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
slouken@1913
   347
                                                   (HDC, const int *,
slouken@1913
   348
                                                    const FLOAT *, UINT,
slouken@1913
   349
                                                    int *, UINT *))
slouken@1913
   350
            WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB");
slouken@1913
   351
        _this->gl_data->wglGetPixelFormatAttribivARB =
slouken@1913
   352
            (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
slouken@1913
   353
            WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB");
slouken@1913
   354
slouken@1913
   355
        if ((_this->gl_data->wglChoosePixelFormatARB != NULL) &&
slouken@1913
   356
            (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
icculus@6382
   357
            _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE;
slouken@1913
   358
        }
slouken@1913
   359
    }
slouken@1913
   360
slouken@1913
   361
    /* Check for WGL_EXT_swap_control */
icculus@6382
   362
    _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE;
slouken@1913
   363
    if (HasExtension("WGL_EXT_swap_control", extensions)) {
slouken@1913
   364
        _this->gl_data->wglSwapIntervalEXT =
slouken@1913
   365
            WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
slouken@1913
   366
        _this->gl_data->wglGetSwapIntervalEXT =
slouken@1913
   367
            WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
icculus@6382
   368
        if (HasExtension("WGL_EXT_swap_control_tear", extensions)) {
icculus@6382
   369
            _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE;
icculus@6382
   370
        }
slouken@2178
   371
    } else {
slouken@2178
   372
        _this->gl_data->wglSwapIntervalEXT = NULL;
slouken@2178
   373
        _this->gl_data->wglGetSwapIntervalEXT = NULL;
slouken@1913
   374
    }
slouken@2178
   375
}
slouken@1913
   376
slouken@2178
   377
static int
slouken@2178
   378
WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
slouken@2178
   379
{
slouken@2178
   380
    HWND hwnd;
slouken@2178
   381
    HDC hdc;
slouken@2180
   382
    PIXELFORMATDESCRIPTOR pfd;
slouken@2178
   383
    HGLRC hglrc;
slouken@2178
   384
    int pixel_format = 0;
slouken@2178
   385
    unsigned int matching;
slouken@2178
   386
slouken@2178
   387
    hwnd =
slouken@2178
   388
        CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
slouken@2178
   389
                     10, 10, NULL, NULL, SDL_Instance, NULL);
slouken@2178
   390
    WIN_PumpEvents(_this);
slouken@2178
   391
slouken@2178
   392
    hdc = GetDC(hwnd);
slouken@2178
   393
slouken@2180
   394
    WIN_GL_SetupPixelFormat(_this, &pfd);
slouken@2180
   395
slouken@2180
   396
    SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
slouken@2180
   397
slouken@2178
   398
    hglrc = _this->gl_data->wglCreateContext(hdc);
slouken@1913
   399
    if (hglrc) {
slouken@2178
   400
        _this->gl_data->wglMakeCurrent(hdc, hglrc);
slouken@2178
   401
slouken@2178
   402
        WIN_GL_InitExtensions(_this, hdc);
slouken@2178
   403
icculus@6382
   404
        if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
slouken@2178
   405
            _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
slouken@2178
   406
                                                    1, &pixel_format,
slouken@2178
   407
                                                    &matching);
slouken@2178
   408
        }
slouken@2178
   409
slouken@1913
   410
        _this->gl_data->wglMakeCurrent(NULL, NULL);
slouken@1913
   411
        _this->gl_data->wglDeleteContext(hglrc);
slouken@1913
   412
    }
slouken@1913
   413
    ReleaseDC(hwnd, hdc);
slouken@1913
   414
    DestroyWindow(hwnd);
slouken@1913
   415
    WIN_PumpEvents(_this);
slouken@2178
   416
slouken@2178
   417
    return pixel_format;
slouken@1913
   418
}
slouken@1913
   419
slouken@1913
   420
int
slouken@1913
   421
WIN_GL_SetupWindow(_THIS, SDL_Window * window)
slouken@1913
   422
{
slouken@1913
   423
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   424
    PIXELFORMATDESCRIPTOR pfd;
slouken@6296
   425
    int pixel_format = 0;
slouken@1913
   426
    int iAttribs[64];
slouken@1913
   427
    int *iAttr;
icculus@7401
   428
    int *iAccelAttr;
slouken@1913
   429
    float fAttribs[1] = { 0 };
slouken@1913
   430
slouken@1913
   431
    WIN_GL_SetupPixelFormat(_this, &pfd);
slouken@1913
   432
slouken@1913
   433
    /* setup WGL_ARB_pixel_format attribs */
slouken@1913
   434
    iAttr = &iAttribs[0];
slouken@1913
   435
slouken@1913
   436
    *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
slouken@1913
   437
    *iAttr++ = GL_TRUE;
slouken@1913
   438
    *iAttr++ = WGL_RED_BITS_ARB;
slouken@1913
   439
    *iAttr++ = _this->gl_config.red_size;
slouken@1913
   440
    *iAttr++ = WGL_GREEN_BITS_ARB;
slouken@1913
   441
    *iAttr++ = _this->gl_config.green_size;
slouken@1913
   442
    *iAttr++ = WGL_BLUE_BITS_ARB;
slouken@1913
   443
    *iAttr++ = _this->gl_config.blue_size;
slouken@1913
   444
slouken@1913
   445
    if (_this->gl_config.alpha_size) {
slouken@1913
   446
        *iAttr++ = WGL_ALPHA_BITS_ARB;
slouken@1913
   447
        *iAttr++ = _this->gl_config.alpha_size;
slouken@1913
   448
    }
slouken@1913
   449
slouken@1913
   450
    *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
slouken@1913
   451
    *iAttr++ = _this->gl_config.double_buffer;
slouken@1913
   452
slouken@1913
   453
    *iAttr++ = WGL_DEPTH_BITS_ARB;
slouken@1913
   454
    *iAttr++ = _this->gl_config.depth_size;
slouken@1913
   455
slouken@1913
   456
    if (_this->gl_config.stencil_size) {
slouken@1913
   457
        *iAttr++ = WGL_STENCIL_BITS_ARB;
slouken@1913
   458
        *iAttr++ = _this->gl_config.stencil_size;
slouken@1913
   459
    }
slouken@1913
   460
slouken@1913
   461
    if (_this->gl_config.accum_red_size) {
slouken@1913
   462
        *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
slouken@1913
   463
        *iAttr++ = _this->gl_config.accum_red_size;
slouken@1913
   464
    }
slouken@1913
   465
slouken@1913
   466
    if (_this->gl_config.accum_green_size) {
slouken@1913
   467
        *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
slouken@1913
   468
        *iAttr++ = _this->gl_config.accum_green_size;
slouken@1913
   469
    }
slouken@1913
   470
slouken@1913
   471
    if (_this->gl_config.accum_blue_size) {
slouken@1913
   472
        *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
slouken@1913
   473
        *iAttr++ = _this->gl_config.accum_blue_size;
slouken@1913
   474
    }
slouken@1913
   475
slouken@1913
   476
    if (_this->gl_config.accum_alpha_size) {
slouken@1913
   477
        *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
slouken@1913
   478
        *iAttr++ = _this->gl_config.accum_alpha_size;
slouken@1913
   479
    }
slouken@1913
   480
slouken@1913
   481
    if (_this->gl_config.stereo) {
slouken@1913
   482
        *iAttr++ = WGL_STEREO_ARB;
slouken@1913
   483
        *iAttr++ = GL_TRUE;
slouken@1913
   484
    }
slouken@1913
   485
slouken@1913
   486
    if (_this->gl_config.multisamplebuffers) {
slouken@1913
   487
        *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
slouken@1913
   488
        *iAttr++ = _this->gl_config.multisamplebuffers;
slouken@1913
   489
    }
slouken@1913
   490
slouken@1913
   491
    if (_this->gl_config.multisamplesamples) {
slouken@1913
   492
        *iAttr++ = WGL_SAMPLES_ARB;
slouken@1913
   493
        *iAttr++ = _this->gl_config.multisamplesamples;
slouken@1913
   494
    }
slouken@1913
   495
icculus@7401
   496
    /* We always choose either FULL or NO accel on Windows, because of flaky
icculus@7401
   497
       drivers. If the app didn't specify, we use FULL, because that's
icculus@7401
   498
       probably what they wanted (and if you didn't care and got FULL, that's
icculus@7401
   499
       a perfectly valid result in any case). */
slouken@6296
   500
    *iAttr++ = WGL_ACCELERATION_ARB;
icculus@7401
   501
    iAccelAttr = iAttr;
icculus@7401
   502
    if (_this->gl_config.accelerated) {
icculus@7401
   503
        *iAttr++ = WGL_FULL_ACCELERATION_ARB;
icculus@7401
   504
    } else {
icculus@7401
   505
        *iAttr++ = WGL_NO_ACCELERATION_ARB;
icculus@7401
   506
    }
slouken@1913
   507
slouken@1913
   508
    *iAttr = 0;
slouken@1913
   509
slouken@1913
   510
    /* Choose and set the closest available pixel format */
icculus@7401
   511
    pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
icculus@7401
   512
icculus@7401
   513
    /* App said "don't care about accel" and FULL accel failed. Try NO. */
icculus@7401
   514
    if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
icculus@7401
   515
        *iAccelAttr = WGL_NO_ACCELERATION_ARB;
slouken@6296
   516
        pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
icculus@7401
   517
        *iAccelAttr = WGL_FULL_ACCELERATION_ARB;  /* if we try again. */
slouken@6296
   518
    }
slouken@2178
   519
    if (!pixel_format) {
slouken@2150
   520
        pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
slouken@1913
   521
    }
slouken@1913
   522
    if (!pixel_format) {
icculus@7037
   523
        return SDL_SetError("No matching GL pixel format available");
slouken@1913
   524
    }
slouken@1913
   525
    if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
icculus@7037
   526
        return WIN_SetError("SetPixelFormat()");
slouken@1913
   527
    }
slouken@1913
   528
    return 0;
slouken@1913
   529
}
slouken@1913
   530
slouken@1913
   531
SDL_GLContext
slouken@1913
   532
WIN_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1913
   533
{
slouken@1913
   534
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@6393
   535
    HGLRC context, share_context;
slouken@1913
   536
slouken@6393
   537
    if (_this->gl_config.share_with_current_context) {
slouken@7412
   538
        share_context = (HGLRC)SDL_GL_GetCurrentContext();
slouken@6393
   539
    } else {
slouken@6393
   540
        share_context = 0;
slouken@6393
   541
    }
slouken@6393
   542
slouken@6393
   543
    if (_this->gl_config.major_version < 3 &&
slouken@7191
   544
    _this->gl_config.profile_mask == 0 &&
slouken@7191
   545
    _this->gl_config.flags == 0) {
slouken@6393
   546
        /* Create legacy context */
slouken@3100
   547
        context = _this->gl_data->wglCreateContext(hdc);
slouken@7191
   548
    if( share_context != 0 ) {
icculus@6406
   549
            _this->gl_data->wglShareLists(share_context, context);
slouken@7191
   550
    }
slouken@3100
   551
    } else {
slouken@3100
   552
        PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
slouken@3100
   553
        HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
slouken@3100
   554
        if (!temp_context) {
slouken@3139
   555
            SDL_SetError("Could not create GL context");
slouken@3100
   556
            return NULL;
slouken@3100
   557
        }
slouken@3139
   558
slouken@3100
   559
        /* Make the context current */
slouken@3100
   560
        if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
slouken@3100
   561
            WIN_GL_DeleteContext(_this, temp_context);
slouken@3100
   562
            return NULL;
slouken@3100
   563
        }
slouken@3139
   564
slouken@3139
   565
        wglCreateContextAttribsARB =
slouken@3139
   566
            (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
slouken@3139
   567
            wglGetProcAddress("wglCreateContextAttribsARB");
slouken@3100
   568
        if (!wglCreateContextAttribsARB) {
slouken@3100
   569
            SDL_SetError("GL 3.x is not supported");
slouken@3100
   570
            context = temp_context;
slouken@3100
   571
        } else {
slouken@7191
   572
        /* max 8 attributes plus terminator */
slouken@6296
   573
            int attribs[9] = {
slouken@3100
   574
                WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
slouken@3100
   575
                WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
slouken@3139
   576
                0
slouken@3100
   577
            };
slouken@7191
   578
        int iattr = 4;
slouken@6296
   579
slouken@7191
   580
        /* SDL profile bits match WGL profile bits */
slouken@7191
   581
        if( _this->gl_config.profile_mask != 0 ) {
slouken@7191
   582
            attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
slouken@7191
   583
        attribs[iattr++] = _this->gl_config.profile_mask;
slouken@7191
   584
        }
slouken@6296
   585
slouken@7191
   586
        /* SDL flags match WGL flags */
slouken@7191
   587
        if( _this->gl_config.flags != 0 ) {
slouken@7191
   588
            attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
slouken@7191
   589
        attribs[iattr++] = _this->gl_config.flags;
slouken@7191
   590
        }
slouken@6296
   591
slouken@7191
   592
        attribs[iattr++] = 0;
slouken@6296
   593
slouken@3100
   594
            /* Create the GL 3.x context */
slouken@6393
   595
            context = wglCreateContextAttribsARB(hdc, share_context, attribs);
slouken@3100
   596
            /* Delete the GL 2.x context */
slouken@3105
   597
            _this->gl_data->wglDeleteContext(temp_context);
slouken@3100
   598
        }
slouken@3100
   599
    }
slouken@3139
   600
slouken@2178
   601
    if (!context) {
slouken@3565
   602
        WIN_SetError("Could not create GL context");
slouken@2178
   603
        return NULL;
slouken@2178
   604
    }
slouken@2178
   605
slouken@2178
   606
    if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
slouken@2178
   607
        WIN_GL_DeleteContext(_this, context);
slouken@2178
   608
        return NULL;
slouken@2178
   609
    }
slouken@2178
   610
slouken@2178
   611
    WIN_GL_InitExtensions(_this, hdc);
slouken@2178
   612
slouken@2178
   613
    return context;
slouken@1913
   614
}
slouken@1913
   615
slouken@1913
   616
int
slouken@1913
   617
WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1913
   618
{
slouken@1913
   619
    HDC hdc;
slouken@1913
   620
slouken@6522
   621
    if (!_this->gl_data) {
icculus@7037
   622
        return SDL_SetError("OpenGL not initialized");
slouken@6522
   623
    }
slouken@6522
   624
slouken@1913
   625
    if (window) {
slouken@1913
   626
        hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   627
    } else {
slouken@1913
   628
        hdc = NULL;
slouken@1913
   629
    }
slouken@1913
   630
    if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
icculus@7037
   631
        return WIN_SetError("wglMakeCurrent()");
slouken@1913
   632
    }
icculus@7037
   633
    return 0;
slouken@1913
   634
}
slouken@1913
   635
slouken@1913
   636
int
slouken@1913
   637
WIN_GL_SetSwapInterval(_THIS, int interval)
slouken@1913
   638
{
icculus@6382
   639
    if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
icculus@7037
   640
        return SDL_SetError("Negative swap interval unsupported in this GL");
icculus@6382
   641
    } else if (_this->gl_data->wglSwapIntervalEXT) {
icculus@7037
   642
        if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
icculus@7037
   643
            return WIN_SetError("wglSwapIntervalEXT()");
icculus@6383
   644
        }
slouken@1913
   645
    } else {
icculus@7037
   646
        return SDL_Unsupported();
slouken@1913
   647
    }
icculus@7037
   648
    return 0;
slouken@1913
   649
}
slouken@1913
   650
slouken@1913
   651
int
slouken@1913
   652
WIN_GL_GetSwapInterval(_THIS)
slouken@1913
   653
{
icculus@6383
   654
    int retval = 0;
slouken@1913
   655
    if (_this->gl_data->wglGetSwapIntervalEXT) {
icculus@6383
   656
        retval = _this->gl_data->wglGetSwapIntervalEXT();
slouken@1913
   657
    }
icculus@6383
   658
    return retval;
slouken@1913
   659
}
slouken@1913
   660
slouken@1913
   661
void
slouken@1913
   662
WIN_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1913
   663
{
slouken@1913
   664
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   665
slouken@1913
   666
    SwapBuffers(hdc);
slouken@1913
   667
}
slouken@1913
   668
slouken@1913
   669
void
slouken@1913
   670
WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1913
   671
{
slouken@6522
   672
    if (!_this->gl_data) {
slouken@6522
   673
        return;
slouken@6522
   674
    }
slouken@1936
   675
    _this->gl_data->wglDeleteContext((HGLRC) context);
slouken@1913
   676
}
slouken@1913
   677
slouken@1952
   678
#endif /* SDL_VIDEO_OPENGL_WGL */
slouken@1913
   679
slouken@6044
   680
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   681
slouken@1913
   682
/* vi: set ts=4 sw=4 expandtab: */