src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 20 Oct 2013 21:18:05 -0400
changeset 7853 4861edda71d1
parent 7559 0dd3b05797f9
child 7865 f2a42ca4ddf0
permissions -rw-r--r--
Added SDL_GL_FRAMEBUFFER_SRGB_CAPABLE (thanks, David!).

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