src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 31 Jul 2013 11:00:23 -0400
changeset 7553 f0091f8eae33
parent 7412 50211a1fd557
child 7559 0dd3b05797f9
permissions -rw-r--r--
Workaround some Windows OpenGL drivers mishandling wglMakeCurrent().

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