cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_windowsopengl.c (24893B)


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