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