src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 01 Aug 2013 00:27:22 -0400
changeset 7559 0dd3b05797f9
parent 7553 f0091f8eae33
child 7853 4861edda71d1
permissions -rw-r--r--
Move the fix for Bugzilla #1395 into WIN_GL_SetupWindow() directly.

It's a cleaner solution.
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
icculus@7559
   421
/* actual work of WIN_GL_SetupWindow() happens here. */
icculus@7559
   422
static int
icculus@7559
   423
WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window)
slouken@1913
   424
{
slouken@1913
   425
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   426
    PIXELFORMATDESCRIPTOR pfd;
slouken@6296
   427
    int pixel_format = 0;
slouken@1913
   428
    int iAttribs[64];
slouken@1913
   429
    int *iAttr;
icculus@7401
   430
    int *iAccelAttr;
slouken@1913
   431
    float fAttribs[1] = { 0 };
slouken@1913
   432
slouken@1913
   433
    WIN_GL_SetupPixelFormat(_this, &pfd);
slouken@1913
   434
slouken@1913
   435
    /* setup WGL_ARB_pixel_format attribs */
slouken@1913
   436
    iAttr = &iAttribs[0];
slouken@1913
   437
slouken@1913
   438
    *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
slouken@1913
   439
    *iAttr++ = GL_TRUE;
slouken@1913
   440
    *iAttr++ = WGL_RED_BITS_ARB;
slouken@1913
   441
    *iAttr++ = _this->gl_config.red_size;
slouken@1913
   442
    *iAttr++ = WGL_GREEN_BITS_ARB;
slouken@1913
   443
    *iAttr++ = _this->gl_config.green_size;
slouken@1913
   444
    *iAttr++ = WGL_BLUE_BITS_ARB;
slouken@1913
   445
    *iAttr++ = _this->gl_config.blue_size;
slouken@1913
   446
slouken@1913
   447
    if (_this->gl_config.alpha_size) {
slouken@1913
   448
        *iAttr++ = WGL_ALPHA_BITS_ARB;
slouken@1913
   449
        *iAttr++ = _this->gl_config.alpha_size;
slouken@1913
   450
    }
slouken@1913
   451
slouken@1913
   452
    *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
slouken@1913
   453
    *iAttr++ = _this->gl_config.double_buffer;
slouken@1913
   454
slouken@1913
   455
    *iAttr++ = WGL_DEPTH_BITS_ARB;
slouken@1913
   456
    *iAttr++ = _this->gl_config.depth_size;
slouken@1913
   457
slouken@1913
   458
    if (_this->gl_config.stencil_size) {
slouken@1913
   459
        *iAttr++ = WGL_STENCIL_BITS_ARB;
slouken@1913
   460
        *iAttr++ = _this->gl_config.stencil_size;
slouken@1913
   461
    }
slouken@1913
   462
slouken@1913
   463
    if (_this->gl_config.accum_red_size) {
slouken@1913
   464
        *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
slouken@1913
   465
        *iAttr++ = _this->gl_config.accum_red_size;
slouken@1913
   466
    }
slouken@1913
   467
slouken@1913
   468
    if (_this->gl_config.accum_green_size) {
slouken@1913
   469
        *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
slouken@1913
   470
        *iAttr++ = _this->gl_config.accum_green_size;
slouken@1913
   471
    }
slouken@1913
   472
slouken@1913
   473
    if (_this->gl_config.accum_blue_size) {
slouken@1913
   474
        *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
slouken@1913
   475
        *iAttr++ = _this->gl_config.accum_blue_size;
slouken@1913
   476
    }
slouken@1913
   477
slouken@1913
   478
    if (_this->gl_config.accum_alpha_size) {
slouken@1913
   479
        *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
slouken@1913
   480
        *iAttr++ = _this->gl_config.accum_alpha_size;
slouken@1913
   481
    }
slouken@1913
   482
slouken@1913
   483
    if (_this->gl_config.stereo) {
slouken@1913
   484
        *iAttr++ = WGL_STEREO_ARB;
slouken@1913
   485
        *iAttr++ = GL_TRUE;
slouken@1913
   486
    }
slouken@1913
   487
slouken@1913
   488
    if (_this->gl_config.multisamplebuffers) {
slouken@1913
   489
        *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
slouken@1913
   490
        *iAttr++ = _this->gl_config.multisamplebuffers;
slouken@1913
   491
    }
slouken@1913
   492
slouken@1913
   493
    if (_this->gl_config.multisamplesamples) {
slouken@1913
   494
        *iAttr++ = WGL_SAMPLES_ARB;
slouken@1913
   495
        *iAttr++ = _this->gl_config.multisamplesamples;
slouken@1913
   496
    }
slouken@1913
   497
icculus@7401
   498
    /* We always choose either FULL or NO accel on Windows, because of flaky
icculus@7401
   499
       drivers. If the app didn't specify, we use FULL, because that's
icculus@7401
   500
       probably what they wanted (and if you didn't care and got FULL, that's
icculus@7401
   501
       a perfectly valid result in any case). */
slouken@6296
   502
    *iAttr++ = WGL_ACCELERATION_ARB;
icculus@7401
   503
    iAccelAttr = iAttr;
icculus@7401
   504
    if (_this->gl_config.accelerated) {
icculus@7401
   505
        *iAttr++ = WGL_FULL_ACCELERATION_ARB;
icculus@7401
   506
    } else {
icculus@7401
   507
        *iAttr++ = WGL_NO_ACCELERATION_ARB;
icculus@7401
   508
    }
slouken@1913
   509
slouken@1913
   510
    *iAttr = 0;
slouken@1913
   511
slouken@1913
   512
    /* Choose and set the closest available pixel format */
icculus@7401
   513
    pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
icculus@7401
   514
icculus@7401
   515
    /* App said "don't care about accel" and FULL accel failed. Try NO. */
icculus@7401
   516
    if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
icculus@7401
   517
        *iAccelAttr = WGL_NO_ACCELERATION_ARB;
slouken@6296
   518
        pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
icculus@7401
   519
        *iAccelAttr = WGL_FULL_ACCELERATION_ARB;  /* if we try again. */
slouken@6296
   520
    }
slouken@2178
   521
    if (!pixel_format) {
slouken@2150
   522
        pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
slouken@1913
   523
    }
slouken@1913
   524
    if (!pixel_format) {
icculus@7037
   525
        return SDL_SetError("No matching GL pixel format available");
slouken@1913
   526
    }
slouken@1913
   527
    if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
icculus@7037
   528
        return WIN_SetError("SetPixelFormat()");
slouken@1913
   529
    }
slouken@1913
   530
    return 0;
slouken@1913
   531
}
slouken@1913
   532
icculus@7559
   533
int
icculus@7559
   534
WIN_GL_SetupWindow(_THIS, SDL_Window * window)
icculus@7559
   535
{
icculus@7559
   536
    /* The current context is lost in here; save it and reset it. */
icculus@7559
   537
    SDL_Window *current_win = SDL_GL_GetCurrentWindow();
icculus@7559
   538
    SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
icculus@7559
   539
    const int retval = WIN_GL_SetupWindowInternal(_this, window);
icculus@7559
   540
    WIN_GL_MakeCurrent(_this, current_win, current_ctx);
icculus@7559
   541
    return retval;
icculus@7559
   542
}
icculus@7559
   543
slouken@1913
   544
SDL_GLContext
slouken@1913
   545
WIN_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1913
   546
{
slouken@1913
   547
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@6393
   548
    HGLRC context, share_context;
slouken@1913
   549
slouken@6393
   550
    if (_this->gl_config.share_with_current_context) {
slouken@7412
   551
        share_context = (HGLRC)SDL_GL_GetCurrentContext();
slouken@6393
   552
    } else {
slouken@6393
   553
        share_context = 0;
slouken@6393
   554
    }
slouken@6393
   555
slouken@6393
   556
    if (_this->gl_config.major_version < 3 &&
slouken@7191
   557
    _this->gl_config.profile_mask == 0 &&
slouken@7191
   558
    _this->gl_config.flags == 0) {
slouken@6393
   559
        /* Create legacy context */
slouken@3100
   560
        context = _this->gl_data->wglCreateContext(hdc);
slouken@7191
   561
    if( share_context != 0 ) {
icculus@6406
   562
            _this->gl_data->wglShareLists(share_context, context);
slouken@7191
   563
    }
slouken@3100
   564
    } else {
slouken@3100
   565
        PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
slouken@3100
   566
        HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
slouken@3100
   567
        if (!temp_context) {
slouken@3139
   568
            SDL_SetError("Could not create GL context");
slouken@3100
   569
            return NULL;
slouken@3100
   570
        }
slouken@3139
   571
slouken@3100
   572
        /* Make the context current */
slouken@3100
   573
        if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
slouken@3100
   574
            WIN_GL_DeleteContext(_this, temp_context);
slouken@3100
   575
            return NULL;
slouken@3100
   576
        }
slouken@3139
   577
slouken@3139
   578
        wglCreateContextAttribsARB =
slouken@3139
   579
            (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
slouken@3139
   580
            wglGetProcAddress("wglCreateContextAttribsARB");
slouken@3100
   581
        if (!wglCreateContextAttribsARB) {
slouken@3100
   582
            SDL_SetError("GL 3.x is not supported");
slouken@3100
   583
            context = temp_context;
slouken@3100
   584
        } else {
slouken@7191
   585
        /* max 8 attributes plus terminator */
slouken@6296
   586
            int attribs[9] = {
slouken@3100
   587
                WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
slouken@3100
   588
                WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
slouken@3139
   589
                0
slouken@3100
   590
            };
slouken@7191
   591
        int iattr = 4;
slouken@6296
   592
slouken@7191
   593
        /* SDL profile bits match WGL profile bits */
slouken@7191
   594
        if( _this->gl_config.profile_mask != 0 ) {
slouken@7191
   595
            attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
slouken@7191
   596
        attribs[iattr++] = _this->gl_config.profile_mask;
slouken@7191
   597
        }
slouken@6296
   598
slouken@7191
   599
        /* SDL flags match WGL flags */
slouken@7191
   600
        if( _this->gl_config.flags != 0 ) {
slouken@7191
   601
            attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
slouken@7191
   602
        attribs[iattr++] = _this->gl_config.flags;
slouken@7191
   603
        }
slouken@6296
   604
slouken@7191
   605
        attribs[iattr++] = 0;
slouken@6296
   606
slouken@3100
   607
            /* Create the GL 3.x context */
slouken@6393
   608
            context = wglCreateContextAttribsARB(hdc, share_context, attribs);
slouken@3100
   609
            /* Delete the GL 2.x context */
slouken@3105
   610
            _this->gl_data->wglDeleteContext(temp_context);
slouken@3100
   611
        }
slouken@3100
   612
    }
slouken@3139
   613
slouken@2178
   614
    if (!context) {
slouken@3565
   615
        WIN_SetError("Could not create GL context");
slouken@2178
   616
        return NULL;
slouken@2178
   617
    }
slouken@2178
   618
slouken@2178
   619
    if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
slouken@2178
   620
        WIN_GL_DeleteContext(_this, context);
slouken@2178
   621
        return NULL;
slouken@2178
   622
    }
slouken@2178
   623
slouken@2178
   624
    WIN_GL_InitExtensions(_this, hdc);
slouken@2178
   625
slouken@2178
   626
    return context;
slouken@1913
   627
}
slouken@1913
   628
slouken@1913
   629
int
slouken@1913
   630
WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1913
   631
{
slouken@1913
   632
    HDC hdc;
slouken@1913
   633
slouken@6522
   634
    if (!_this->gl_data) {
icculus@7037
   635
        return SDL_SetError("OpenGL not initialized");
slouken@6522
   636
    }
slouken@6522
   637
icculus@7553
   638
    /* sanity check that higher level handled this. */
icculus@7553
   639
    SDL_assert(window || (!window && !context));
icculus@7553
   640
icculus@7553
   641
    /* Some Windows drivers freak out if hdc is NULL, even when context is
icculus@7553
   642
       NULL, against spec. Since hdc is _supposed_ to be ignored if context
icculus@7553
   643
       is NULL, we either use the current GL window, or do nothing if we
icculus@7553
   644
       already have no current context. */
icculus@7553
   645
    if (!window) {
icculus@7553
   646
        window = SDL_GL_GetCurrentWindow();
icculus@7553
   647
        if (!window) {
icculus@7553
   648
            SDL_assert(SDL_GL_GetCurrentContext() == NULL);
icculus@7553
   649
            return 0;  /* already done. */
icculus@7553
   650
        }
slouken@1913
   651
    }
icculus@7553
   652
icculus@7553
   653
    hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   654
    if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
icculus@7037
   655
        return WIN_SetError("wglMakeCurrent()");
slouken@1913
   656
    }
icculus@7037
   657
    return 0;
slouken@1913
   658
}
slouken@1913
   659
slouken@1913
   660
int
slouken@1913
   661
WIN_GL_SetSwapInterval(_THIS, int interval)
slouken@1913
   662
{
icculus@6382
   663
    if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
icculus@7037
   664
        return SDL_SetError("Negative swap interval unsupported in this GL");
icculus@6382
   665
    } else if (_this->gl_data->wglSwapIntervalEXT) {
icculus@7037
   666
        if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
icculus@7037
   667
            return WIN_SetError("wglSwapIntervalEXT()");
icculus@6383
   668
        }
slouken@1913
   669
    } else {
icculus@7037
   670
        return SDL_Unsupported();
slouken@1913
   671
    }
icculus@7037
   672
    return 0;
slouken@1913
   673
}
slouken@1913
   674
slouken@1913
   675
int
slouken@1913
   676
WIN_GL_GetSwapInterval(_THIS)
slouken@1913
   677
{
icculus@6383
   678
    int retval = 0;
slouken@1913
   679
    if (_this->gl_data->wglGetSwapIntervalEXT) {
icculus@6383
   680
        retval = _this->gl_data->wglGetSwapIntervalEXT();
slouken@1913
   681
    }
icculus@6383
   682
    return retval;
slouken@1913
   683
}
slouken@1913
   684
slouken@1913
   685
void
slouken@1913
   686
WIN_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1913
   687
{
slouken@1913
   688
    HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
slouken@1913
   689
slouken@1913
   690
    SwapBuffers(hdc);
slouken@1913
   691
}
slouken@1913
   692
slouken@1913
   693
void
slouken@1913
   694
WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1913
   695
{
slouken@6522
   696
    if (!_this->gl_data) {
slouken@6522
   697
        return;
slouken@6522
   698
    }
slouken@1936
   699
    _this->gl_data->wglDeleteContext((HGLRC) context);
slouken@1913
   700
}
slouken@1913
   701
slouken@1952
   702
#endif /* SDL_VIDEO_OPENGL_WGL */
slouken@1913
   703
slouken@6044
   704
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
slouken@6044
   705
slouken@1913
   706
/* vi: set ts=4 sw=4 expandtab: */