src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6885 700f1b25f77f
child 7191 75360622e65f
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


Fixes Bugzilla #1778.
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;
slouken@1913
   428
    float fAttribs[1] = { 0 };
slouken@1913
   429
slouken@1913
   430
    WIN_GL_SetupPixelFormat(_this, &pfd);
slouken@1913
   431
slouken@1913
   432
    /* setup WGL_ARB_pixel_format attribs */
slouken@1913
   433
    iAttr = &iAttribs[0];
slouken@1913
   434
slouken@1913
   435
    *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
slouken@1913
   436
    *iAttr++ = GL_TRUE;
slouken@1913
   437
    *iAttr++ = WGL_RED_BITS_ARB;
slouken@1913
   438
    *iAttr++ = _this->gl_config.red_size;
slouken@1913
   439
    *iAttr++ = WGL_GREEN_BITS_ARB;
slouken@1913
   440
    *iAttr++ = _this->gl_config.green_size;
slouken@1913
   441
    *iAttr++ = WGL_BLUE_BITS_ARB;
slouken@1913
   442
    *iAttr++ = _this->gl_config.blue_size;
slouken@1913
   443
slouken@1913
   444
    if (_this->gl_config.alpha_size) {
slouken@1913
   445
        *iAttr++ = WGL_ALPHA_BITS_ARB;
slouken@1913
   446
        *iAttr++ = _this->gl_config.alpha_size;
slouken@1913
   447
    }
slouken@1913
   448
slouken@1913
   449
    *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
slouken@1913
   450
    *iAttr++ = _this->gl_config.double_buffer;
slouken@1913
   451
slouken@1913
   452
    *iAttr++ = WGL_DEPTH_BITS_ARB;
slouken@1913
   453
    *iAttr++ = _this->gl_config.depth_size;
slouken@1913
   454
slouken@1913
   455
    if (_this->gl_config.stencil_size) {
slouken@1913
   456
        *iAttr++ = WGL_STENCIL_BITS_ARB;
slouken@1913
   457
        *iAttr++ = _this->gl_config.stencil_size;
slouken@1913
   458
    }
slouken@1913
   459
slouken@1913
   460
    if (_this->gl_config.accum_red_size) {
slouken@1913
   461
        *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
slouken@1913
   462
        *iAttr++ = _this->gl_config.accum_red_size;
slouken@1913
   463
    }
slouken@1913
   464
slouken@1913
   465
    if (_this->gl_config.accum_green_size) {
slouken@1913
   466
        *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
slouken@1913
   467
        *iAttr++ = _this->gl_config.accum_green_size;
slouken@1913
   468
    }
slouken@1913
   469
slouken@1913
   470
    if (_this->gl_config.accum_blue_size) {
slouken@1913
   471
        *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
slouken@1913
   472
        *iAttr++ = _this->gl_config.accum_blue_size;
slouken@1913
   473
    }
slouken@1913
   474
slouken@1913
   475
    if (_this->gl_config.accum_alpha_size) {
slouken@1913
   476
        *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
slouken@1913
   477
        *iAttr++ = _this->gl_config.accum_alpha_size;
slouken@1913
   478
    }
slouken@1913
   479
slouken@1913
   480
    if (_this->gl_config.stereo) {
slouken@1913
   481
        *iAttr++ = WGL_STEREO_ARB;
slouken@1913
   482
        *iAttr++ = GL_TRUE;
slouken@1913
   483
    }
slouken@1913
   484
slouken@1913
   485
    if (_this->gl_config.multisamplebuffers) {
slouken@1913
   486
        *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
slouken@1913
   487
        *iAttr++ = _this->gl_config.multisamplebuffers;
slouken@1913
   488
    }
slouken@1913
   489
slouken@1913
   490
    if (_this->gl_config.multisamplesamples) {
slouken@1913
   491
        *iAttr++ = WGL_SAMPLES_ARB;
slouken@1913
   492
        *iAttr++ = _this->gl_config.multisamplesamples;
slouken@1913
   493
    }
slouken@1913
   494
slouken@6296
   495
    *iAttr++ = WGL_ACCELERATION_ARB;
slouken@6296
   496
    *iAttr++ = WGL_FULL_ACCELERATION_ARB;
slouken@1913
   497
slouken@1913
   498
    *iAttr = 0;
slouken@1913
   499
slouken@1913
   500
    /* Choose and set the closest available pixel format */
slouken@6296
   501
    if (_this->gl_config.accelerated != 0) {
slouken@6296
   502
        pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
slouken@6296
   503
    }
slouken@6296
   504
    if (!pixel_format && _this->gl_config.accelerated != 1) {
slouken@6296
   505
        iAttr[-1] = WGL_NO_ACCELERATION_ARB;
slouken@6296
   506
	pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
slouken@6296
   507
    }
slouken@2178
   508
    if (!pixel_format) {
slouken@2150
   509
        pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
slouken@1913
   510
    }
slouken@1913
   511
    if (!pixel_format) {
icculus@7037
   512
        return SDL_SetError("No matching GL pixel format available");
slouken@1913
   513
    }
slouken@1913
   514
    if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
icculus@7037
   515
        return WIN_SetError("SetPixelFormat()");
slouken@1913
   516
    }
slouken@1913
   517
    return 0;
slouken@1913
   518
}
slouken@1913
   519
slouken@1913
   520
SDL_GLContext
slouken@1913
   521
WIN_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1913
   522
{
slouken@1913
   523
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@6393
   524
    HGLRC context, share_context;
slouken@1913
   525
slouken@6393
   526
    if (_this->gl_config.share_with_current_context) {
slouken@6393
   527
        share_context = (HGLRC)(_this->current_glctx);
slouken@6393
   528
    } else {
slouken@6393
   529
        share_context = 0;
slouken@6393
   530
    }
slouken@6393
   531
slouken@6393
   532
    if (_this->gl_config.major_version < 3 &&
slouken@6393
   533
	_this->gl_config.profile_mask == 0 &&
slouken@6393
   534
	_this->gl_config.flags == 0) {
slouken@6393
   535
        /* Create legacy context */
slouken@3100
   536
        context = _this->gl_data->wglCreateContext(hdc);
slouken@6393
   537
	if( share_context != 0 ) {
icculus@6406
   538
            _this->gl_data->wglShareLists(share_context, context);
slouken@6393
   539
	}
slouken@3100
   540
    } else {
slouken@3100
   541
        PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
slouken@3100
   542
        HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
slouken@3100
   543
        if (!temp_context) {
slouken@3139
   544
            SDL_SetError("Could not create GL context");
slouken@3100
   545
            return NULL;
slouken@3100
   546
        }
slouken@3139
   547
slouken@3100
   548
        /* Make the context current */
slouken@3100
   549
        if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
slouken@3100
   550
            WIN_GL_DeleteContext(_this, temp_context);
slouken@3100
   551
            return NULL;
slouken@3100
   552
        }
slouken@3139
   553
slouken@3139
   554
        wglCreateContextAttribsARB =
slouken@3139
   555
            (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
slouken@3139
   556
            wglGetProcAddress("wglCreateContextAttribsARB");
slouken@3100
   557
        if (!wglCreateContextAttribsARB) {
slouken@3100
   558
            SDL_SetError("GL 3.x is not supported");
slouken@3100
   559
            context = temp_context;
slouken@3100
   560
        } else {
slouken@6296
   561
	    /* max 8 attributes plus terminator */
slouken@6296
   562
            int attribs[9] = {
slouken@3100
   563
                WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
slouken@3100
   564
                WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
slouken@3139
   565
                0
slouken@3100
   566
            };
slouken@6296
   567
	    int iattr = 4;
slouken@6296
   568
slouken@6296
   569
	    /* SDL profile bits match WGL profile bits */
slouken@6296
   570
	    if( _this->gl_config.profile_mask != 0 ) {
slouken@6296
   571
	        attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
slouken@6296
   572
		attribs[iattr++] = _this->gl_config.profile_mask;
slouken@6296
   573
	    }
slouken@6296
   574
slouken@6296
   575
	    /* SDL flags match WGL flags */
slouken@6296
   576
	    if( _this->gl_config.flags != 0 ) {
slouken@6296
   577
	        attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
slouken@6296
   578
		attribs[iattr++] = _this->gl_config.flags;
slouken@6296
   579
	    }
slouken@6296
   580
slouken@6296
   581
	    attribs[iattr++] = 0;
slouken@6296
   582
slouken@3100
   583
            /* Create the GL 3.x context */
slouken@6393
   584
            context = wglCreateContextAttribsARB(hdc, share_context, attribs);
slouken@3100
   585
            /* Delete the GL 2.x context */
slouken@3105
   586
            _this->gl_data->wglDeleteContext(temp_context);
slouken@3100
   587
        }
slouken@3100
   588
    }
slouken@3139
   589
slouken@2178
   590
    if (!context) {
slouken@3565
   591
        WIN_SetError("Could not create GL context");
slouken@2178
   592
        return NULL;
slouken@2178
   593
    }
slouken@2178
   594
slouken@2178
   595
    if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
slouken@2178
   596
        WIN_GL_DeleteContext(_this, context);
slouken@2178
   597
        return NULL;
slouken@2178
   598
    }
slouken@2178
   599
slouken@2178
   600
    WIN_GL_InitExtensions(_this, hdc);
slouken@2178
   601
slouken@2178
   602
    return context;
slouken@1913
   603
}
slouken@1913
   604
slouken@1913
   605
int
slouken@1913
   606
WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1913
   607
{
slouken@1913
   608
    HDC hdc;
slouken@1913
   609
slouken@6522
   610
    if (!_this->gl_data) {
icculus@7037
   611
        return SDL_SetError("OpenGL not initialized");
slouken@6522
   612
    }
slouken@6522
   613
slouken@1913
   614
    if (window) {
slouken@1913
   615
        hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   616
    } else {
slouken@1913
   617
        hdc = NULL;
slouken@1913
   618
    }
slouken@1913
   619
    if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
icculus@7037
   620
        return WIN_SetError("wglMakeCurrent()");
slouken@1913
   621
    }
icculus@7037
   622
    return 0;
slouken@1913
   623
}
slouken@1913
   624
slouken@1913
   625
int
slouken@1913
   626
WIN_GL_SetSwapInterval(_THIS, int interval)
slouken@1913
   627
{
icculus@6382
   628
    if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
icculus@7037
   629
        return SDL_SetError("Negative swap interval unsupported in this GL");
icculus@6382
   630
    } else if (_this->gl_data->wglSwapIntervalEXT) {
icculus@7037
   631
        if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
icculus@7037
   632
            return WIN_SetError("wglSwapIntervalEXT()");
icculus@6383
   633
        }
slouken@1913
   634
    } else {
icculus@7037
   635
        return SDL_Unsupported();
slouken@1913
   636
    }
icculus@7037
   637
    return 0;
slouken@1913
   638
}
slouken@1913
   639
slouken@1913
   640
int
slouken@1913
   641
WIN_GL_GetSwapInterval(_THIS)
slouken@1913
   642
{
icculus@6383
   643
    int retval = 0;
slouken@1913
   644
    if (_this->gl_data->wglGetSwapIntervalEXT) {
icculus@6383
   645
        retval = _this->gl_data->wglGetSwapIntervalEXT();
slouken@1913
   646
    }
icculus@6383
   647
    return retval;
slouken@1913
   648
}
slouken@1913
   649
slouken@1913
   650
void
slouken@1913
   651
WIN_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1913
   652
{
slouken@1913
   653
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   654
slouken@1913
   655
    SwapBuffers(hdc);
slouken@1913
   656
}
slouken@1913
   657
slouken@1913
   658
void
slouken@1913
   659
WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1913
   660
{
slouken@6522
   661
    if (!_this->gl_data) {
slouken@6522
   662
        return;
slouken@6522
   663
    }
slouken@1936
   664
    _this->gl_data->wglDeleteContext((HGLRC) context);
slouken@1913
   665
}
slouken@1913
   666
slouken@1952
   667
#endif /* SDL_VIDEO_OPENGL_WGL */
slouken@1913
   668
slouken@6044
   669
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   670
slouken@1913
   671
/* vi: set ts=4 sw=4 expandtab: */