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