sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_windowsopengl.c (29846B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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_loadso.h"
     26 #include "SDL_windowsvideo.h"
     27 #include "SDL_windowsopengles.h"
     28 #include "SDL_hints.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 
     77 #ifndef WGL_ARB_context_flush_control
     78 #define WGL_ARB_context_flush_control
     79 #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB   0x2097
     80 #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB           0x0000
     81 #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB          0x2098
     82 #endif
     83 
     84 #ifndef WGL_ARB_create_context_no_error
     85 #define WGL_ARB_create_context_no_error
     86 #define WGL_CONTEXT_OPENGL_NO_ERROR_ARB                 0x31B3
     87 #endif
     88 
     89 typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
     90                                                             HGLRC
     91                                                             hShareContext,
     92                                                             const int
     93                                                             *attribList);
     94 
     95 int
     96 WIN_GL_LoadLibrary(_THIS, const char *path)
     97 {
     98     void *handle;
     99 
    100     if (path == NULL) {
    101         path = SDL_getenv("SDL_OPENGL_LIBRARY");
    102     }
    103     if (path == NULL) {
    104         path = DEFAULT_OPENGL;
    105     }
    106     _this->gl_config.dll_handle = SDL_LoadObject(path);
    107     if (!_this->gl_config.dll_handle) {
    108         return -1;
    109     }
    110     SDL_strlcpy(_this->gl_config.driver_path, path,
    111                 SDL_arraysize(_this->gl_config.driver_path));
    112 
    113     /* Allocate OpenGL memory */
    114     _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData));
    115     if (!_this->gl_data) {
    116         return SDL_OutOfMemory();
    117     }
    118 
    119     /* Load function pointers */
    120     handle = _this->gl_config.dll_handle;
    121     _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
    122         SDL_LoadFunction(handle, "wglGetProcAddress");
    123     _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
    124         SDL_LoadFunction(handle, "wglCreateContext");
    125     _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
    126         SDL_LoadFunction(handle, "wglDeleteContext");
    127     _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
    128         SDL_LoadFunction(handle, "wglMakeCurrent");
    129     _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
    130         SDL_LoadFunction(handle, "wglShareLists");
    131 
    132     if (!_this->gl_data->wglGetProcAddress ||
    133         !_this->gl_data->wglCreateContext ||
    134         !_this->gl_data->wglDeleteContext ||
    135         !_this->gl_data->wglMakeCurrent) {
    136         return SDL_SetError("Could not retrieve OpenGL functions");
    137     }
    138 
    139     /* XXX Too sleazy? WIN_GL_InitExtensions looks for certain OpenGL
    140        extensions via SDL_GL_DeduceMaxSupportedESProfile. This uses
    141        SDL_GL_ExtensionSupported which in turn calls SDL_GL_GetProcAddress.
    142        However SDL_GL_GetProcAddress will fail if the library is not
    143        loaded; it checks for gl_config.driver_loaded > 0. To avoid this
    144        test failing, increment driver_loaded around the call to
    145        WIN_GLInitExtensions.
    146 
    147        Successful loading of the library is normally indicated by
    148        SDL_GL_LoadLibrary incrementing driver_loaded immediately after
    149        this function returns 0 to it.
    150 
    151        Alternatives to this are:
    152        - moving SDL_GL_DeduceMaxSupportedESProfile to both the WIN and
    153          X11 platforms while adding a function equivalent to
    154          SDL_GL_ExtensionSupported but which directly calls
    155          glGetProcAddress(). Having 3 copies of the
    156          SDL_GL_ExtensionSupported makes this alternative unattractive.
    157        - moving SDL_GL_DeduceMaxSupportedESProfile to a new file shared
    158          by the WIN and X11 platforms while adding a function equivalent
    159          to SDL_GL_ExtensionSupported. This is unattractive due to the
    160          number of project files that will need updating, plus there
    161          will be 2 copies of the SDL_GL_ExtensionSupported code.
    162        - Add a private equivalent of SDL_GL_ExtensionSupported to
    163          SDL_video.c.
    164        - Move the call to WIN_GL_InitExtensions back to WIN_CreateWindow
    165          and add a flag to gl_data to avoid multiple calls to this
    166          expensive function. This is probably the least objectionable
    167          alternative if this increment/decrement trick is unacceptable.
    168 
    169        Note that the driver_loaded > 0 check needs to remain in
    170        SDL_GL_ExtensionSupported and SDL_GL_GetProcAddress as they are
    171        public API functions.
    172     */
    173     ++_this->gl_config.driver_loaded;
    174     WIN_GL_InitExtensions(_this);
    175     --_this->gl_config.driver_loaded;
    176 
    177     return 0;
    178 }
    179 
    180 void *
    181 WIN_GL_GetProcAddress(_THIS, const char *proc)
    182 {
    183     void *func;
    184 
    185     /* This is to pick up extensions */
    186     func = _this->gl_data->wglGetProcAddress(proc);
    187     if (!func) {
    188         /* This is probably a normal GL function */
    189         func = GetProcAddress(_this->gl_config.dll_handle, proc);
    190     }
    191     return func;
    192 }
    193 
    194 void
    195 WIN_GL_UnloadLibrary(_THIS)
    196 {
    197     SDL_UnloadObject(_this->gl_config.dll_handle);
    198     _this->gl_config.dll_handle = NULL;
    199 
    200     /* Free OpenGL memory */
    201     SDL_free(_this->gl_data);
    202     _this->gl_data = NULL;
    203 }
    204 
    205 static void
    206 WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd)
    207 {
    208     SDL_zerop(pfd);
    209     pfd->nSize = sizeof(*pfd);
    210     pfd->nVersion = 1;
    211     pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
    212     if (_this->gl_config.double_buffer) {
    213         pfd->dwFlags |= PFD_DOUBLEBUFFER;
    214     }
    215     if (_this->gl_config.stereo) {
    216         pfd->dwFlags |= PFD_STEREO;
    217     }
    218     pfd->iLayerType = PFD_MAIN_PLANE;
    219     pfd->iPixelType = PFD_TYPE_RGBA;
    220     pfd->cRedBits = _this->gl_config.red_size;
    221     pfd->cGreenBits = _this->gl_config.green_size;
    222     pfd->cBlueBits = _this->gl_config.blue_size;
    223     pfd->cAlphaBits = _this->gl_config.alpha_size;
    224     if (_this->gl_config.buffer_size) {
    225         pfd->cColorBits =
    226             _this->gl_config.buffer_size - _this->gl_config.alpha_size;
    227     } else {
    228         pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits);
    229     }
    230     pfd->cAccumRedBits = _this->gl_config.accum_red_size;
    231     pfd->cAccumGreenBits = _this->gl_config.accum_green_size;
    232     pfd->cAccumBlueBits = _this->gl_config.accum_blue_size;
    233     pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size;
    234     pfd->cAccumBits =
    235         (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits +
    236          pfd->cAccumAlphaBits);
    237     pfd->cDepthBits = _this->gl_config.depth_size;
    238     pfd->cStencilBits = _this->gl_config.stencil_size;
    239 }
    240 
    241 /* Choose the closest pixel format that meets or exceeds the target.
    242    FIXME: Should we weight any particular attribute over any other?
    243 */
    244 static int
    245 WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target)
    246 {
    247     PIXELFORMATDESCRIPTOR pfd;
    248     int count, index, best = 0;
    249     unsigned int dist, best_dist = ~0U;
    250 
    251     count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL);
    252 
    253     for (index = 1; index <= count; index++) {
    254 
    255         if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) {
    256             continue;
    257         }
    258 
    259         if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) {
    260             continue;
    261         }
    262 
    263         if (pfd.iLayerType != target->iLayerType) {
    264             continue;
    265         }
    266         if (pfd.iPixelType != target->iPixelType) {
    267             continue;
    268         }
    269 
    270         dist = 0;
    271 
    272         if (pfd.cColorBits < target->cColorBits) {
    273             continue;
    274         } else {
    275             dist += (pfd.cColorBits - target->cColorBits);
    276         }
    277         if (pfd.cRedBits < target->cRedBits) {
    278             continue;
    279         } else {
    280             dist += (pfd.cRedBits - target->cRedBits);
    281         }
    282         if (pfd.cGreenBits < target->cGreenBits) {
    283             continue;
    284         } else {
    285             dist += (pfd.cGreenBits - target->cGreenBits);
    286         }
    287         if (pfd.cBlueBits < target->cBlueBits) {
    288             continue;
    289         } else {
    290             dist += (pfd.cBlueBits - target->cBlueBits);
    291         }
    292         if (pfd.cAlphaBits < target->cAlphaBits) {
    293             continue;
    294         } else {
    295             dist += (pfd.cAlphaBits - target->cAlphaBits);
    296         }
    297         if (pfd.cAccumBits < target->cAccumBits) {
    298             continue;
    299         } else {
    300             dist += (pfd.cAccumBits - target->cAccumBits);
    301         }
    302         if (pfd.cAccumRedBits < target->cAccumRedBits) {
    303             continue;
    304         } else {
    305             dist += (pfd.cAccumRedBits - target->cAccumRedBits);
    306         }
    307         if (pfd.cAccumGreenBits < target->cAccumGreenBits) {
    308             continue;
    309         } else {
    310             dist += (pfd.cAccumGreenBits - target->cAccumGreenBits);
    311         }
    312         if (pfd.cAccumBlueBits < target->cAccumBlueBits) {
    313             continue;
    314         } else {
    315             dist += (pfd.cAccumBlueBits - target->cAccumBlueBits);
    316         }
    317         if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) {
    318             continue;
    319         } else {
    320             dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits);
    321         }
    322         if (pfd.cDepthBits < target->cDepthBits) {
    323             continue;
    324         } else {
    325             dist += (pfd.cDepthBits - target->cDepthBits);
    326         }
    327         if (pfd.cStencilBits < target->cStencilBits) {
    328             continue;
    329         } else {
    330             dist += (pfd.cStencilBits - target->cStencilBits);
    331         }
    332 
    333         if (dist < best_dist) {
    334             best = index;
    335             best_dist = dist;
    336         }
    337     }
    338 
    339     return best;
    340 }
    341 
    342 static SDL_bool
    343 HasExtension(const char *extension, const char *extensions)
    344 {
    345     const char *start;
    346     const char *where, *terminator;
    347 
    348     /* Extension names should not have spaces. */
    349     where = SDL_strchr(extension, ' ');
    350     if (where || *extension == '\0')
    351         return SDL_FALSE;
    352 
    353     if (!extensions)
    354         return SDL_FALSE;
    355 
    356     /* It takes a bit of care to be fool-proof about parsing the
    357      * OpenGL extensions string. Don't be fooled by sub-strings,
    358      * etc. */
    359 
    360     start = extensions;
    361 
    362     for (;;) {
    363         where = SDL_strstr(start, extension);
    364         if (!where)
    365             break;
    366 
    367         terminator = where + SDL_strlen(extension);
    368         if (where == start || *(where - 1) == ' ')
    369             if (*terminator == ' ' || *terminator == '\0')
    370                 return SDL_TRUE;
    371 
    372         start = terminator;
    373     }
    374     return SDL_FALSE;
    375 }
    376 
    377 void
    378 WIN_GL_InitExtensions(_THIS)
    379 {
    380     const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
    381     const char *extensions;
    382     HWND hwnd;
    383     HDC hdc;
    384     HGLRC hglrc;
    385     PIXELFORMATDESCRIPTOR pfd;
    386 
    387     if (!_this->gl_data) {
    388         return;
    389     }
    390 
    391     hwnd =
    392         CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
    393         10, 10, NULL, NULL, SDL_Instance, NULL);
    394     if (!hwnd) {
    395         return;
    396     }
    397     WIN_PumpEvents(_this);
    398 
    399     hdc = GetDC(hwnd);
    400 
    401     WIN_GL_SetupPixelFormat(_this, &pfd);
    402 
    403     SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
    404 
    405     hglrc = _this->gl_data->wglCreateContext(hdc);
    406     if (!hglrc) {
    407         return;
    408     }
    409     _this->gl_data->wglMakeCurrent(hdc, hglrc);
    410 
    411     wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
    412         _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
    413     if (wglGetExtensionsStringARB) {
    414         extensions = wglGetExtensionsStringARB(hdc);
    415     } else {
    416         extensions = NULL;
    417     }
    418 
    419     /* Check for WGL_ARB_pixel_format */
    420     _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE;
    421     if (HasExtension("WGL_ARB_pixel_format", extensions)) {
    422         _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
    423                                                    (HDC, const int *,
    424                                                     const FLOAT *, UINT,
    425                                                     int *, UINT *))
    426             WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB");
    427         _this->gl_data->wglGetPixelFormatAttribivARB =
    428             (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
    429             WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB");
    430 
    431         if ((_this->gl_data->wglChoosePixelFormatARB != NULL) &&
    432             (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
    433             _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE;
    434         }
    435     }
    436 
    437     /* Check for WGL_EXT_swap_control */
    438     _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE;
    439     if (HasExtension("WGL_EXT_swap_control", extensions)) {
    440         _this->gl_data->wglSwapIntervalEXT =
    441             WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
    442         _this->gl_data->wglGetSwapIntervalEXT =
    443             WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
    444         if (HasExtension("WGL_EXT_swap_control_tear", extensions)) {
    445             _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE;
    446         }
    447     } else {
    448         _this->gl_data->wglSwapIntervalEXT = NULL;
    449         _this->gl_data->wglGetSwapIntervalEXT = NULL;
    450     }
    451 
    452     /* Check for WGL_EXT_create_context_es2_profile */
    453     if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) {
    454         SDL_GL_DeduceMaxSupportedESProfile(
    455             &_this->gl_data->es_profile_max_supported_version.major,
    456             &_this->gl_data->es_profile_max_supported_version.minor
    457         );
    458     }
    459 
    460     /* Check for WGL_ARB_context_flush_control */
    461     if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
    462         _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
    463     }
    464 
    465     /* Check for WGL_ARB_create_context_robustness */
    466     if (HasExtension("WGL_ARB_create_context_robustness", extensions)) {
    467         _this->gl_data->HAS_WGL_ARB_create_context_robustness = SDL_TRUE;
    468     }
    469 
    470     /* Check for WGL_ARB_create_context_no_error */
    471     if (HasExtension("WGL_ARB_create_context_no_error", extensions)) {
    472         _this->gl_data->HAS_WGL_ARB_create_context_no_error = SDL_TRUE;
    473     }
    474 
    475     _this->gl_data->wglMakeCurrent(hdc, NULL);
    476     _this->gl_data->wglDeleteContext(hglrc);
    477     ReleaseDC(hwnd, hdc);
    478     DestroyWindow(hwnd);
    479     WIN_PumpEvents(_this);
    480 }
    481 
    482 static int
    483 WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
    484 {
    485     HWND hwnd;
    486     HDC hdc;
    487     PIXELFORMATDESCRIPTOR pfd;
    488     HGLRC hglrc;
    489     int pixel_format = 0;
    490     unsigned int matching;
    491 
    492     hwnd =
    493         CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
    494                      10, 10, NULL, NULL, SDL_Instance, NULL);
    495     WIN_PumpEvents(_this);
    496 
    497     hdc = GetDC(hwnd);
    498 
    499     WIN_GL_SetupPixelFormat(_this, &pfd);
    500 
    501     SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
    502 
    503     hglrc = _this->gl_data->wglCreateContext(hdc);
    504     if (hglrc) {
    505         _this->gl_data->wglMakeCurrent(hdc, hglrc);
    506 
    507         if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
    508             _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
    509                                                     1, &pixel_format,
    510                                                     &matching);
    511         }
    512 
    513         _this->gl_data->wglMakeCurrent(hdc, NULL);
    514         _this->gl_data->wglDeleteContext(hglrc);
    515     }
    516     ReleaseDC(hwnd, hdc);
    517     DestroyWindow(hwnd);
    518     WIN_PumpEvents(_this);
    519 
    520     return pixel_format;
    521 }
    522 
    523 /* actual work of WIN_GL_SetupWindow() happens here. */
    524 static int
    525 WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window)
    526 {
    527     HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
    528     PIXELFORMATDESCRIPTOR pfd;
    529     int pixel_format = 0;
    530     int iAttribs[64];
    531     int *iAttr;
    532     int *iAccelAttr;
    533     float fAttribs[1] = { 0 };
    534 
    535     WIN_GL_SetupPixelFormat(_this, &pfd);
    536 
    537     /* setup WGL_ARB_pixel_format attribs */
    538     iAttr = &iAttribs[0];
    539 
    540     *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
    541     *iAttr++ = GL_TRUE;
    542     *iAttr++ = WGL_RED_BITS_ARB;
    543     *iAttr++ = _this->gl_config.red_size;
    544     *iAttr++ = WGL_GREEN_BITS_ARB;
    545     *iAttr++ = _this->gl_config.green_size;
    546     *iAttr++ = WGL_BLUE_BITS_ARB;
    547     *iAttr++ = _this->gl_config.blue_size;
    548 
    549     if (_this->gl_config.alpha_size) {
    550         *iAttr++ = WGL_ALPHA_BITS_ARB;
    551         *iAttr++ = _this->gl_config.alpha_size;
    552     }
    553 
    554     *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
    555     *iAttr++ = _this->gl_config.double_buffer;
    556 
    557     *iAttr++ = WGL_DEPTH_BITS_ARB;
    558     *iAttr++ = _this->gl_config.depth_size;
    559 
    560     if (_this->gl_config.stencil_size) {
    561         *iAttr++ = WGL_STENCIL_BITS_ARB;
    562         *iAttr++ = _this->gl_config.stencil_size;
    563     }
    564 
    565     if (_this->gl_config.accum_red_size) {
    566         *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
    567         *iAttr++ = _this->gl_config.accum_red_size;
    568     }
    569 
    570     if (_this->gl_config.accum_green_size) {
    571         *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
    572         *iAttr++ = _this->gl_config.accum_green_size;
    573     }
    574 
    575     if (_this->gl_config.accum_blue_size) {
    576         *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
    577         *iAttr++ = _this->gl_config.accum_blue_size;
    578     }
    579 
    580     if (_this->gl_config.accum_alpha_size) {
    581         *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
    582         *iAttr++ = _this->gl_config.accum_alpha_size;
    583     }
    584 
    585     if (_this->gl_config.stereo) {
    586         *iAttr++ = WGL_STEREO_ARB;
    587         *iAttr++ = GL_TRUE;
    588     }
    589 
    590     if (_this->gl_config.multisamplebuffers) {
    591         *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
    592         *iAttr++ = _this->gl_config.multisamplebuffers;
    593     }
    594 
    595     if (_this->gl_config.multisamplesamples) {
    596         *iAttr++ = WGL_SAMPLES_ARB;
    597         *iAttr++ = _this->gl_config.multisamplesamples;
    598     }
    599 
    600     if (_this->gl_config.framebuffer_srgb_capable) {
    601         *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
    602         *iAttr++ = _this->gl_config.framebuffer_srgb_capable;
    603     }
    604 
    605     /* We always choose either FULL or NO accel on Windows, because of flaky
    606        drivers. If the app didn't specify, we use FULL, because that's
    607        probably what they wanted (and if you didn't care and got FULL, that's
    608        a perfectly valid result in any case). */
    609     *iAttr++ = WGL_ACCELERATION_ARB;
    610     iAccelAttr = iAttr;
    611     if (_this->gl_config.accelerated) {
    612         *iAttr++ = WGL_FULL_ACCELERATION_ARB;
    613     } else {
    614         *iAttr++ = WGL_NO_ACCELERATION_ARB;
    615     }
    616 
    617     *iAttr = 0;
    618 
    619     /* Choose and set the closest available pixel format */
    620     pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
    621 
    622     /* App said "don't care about accel" and FULL accel failed. Try NO. */
    623     if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
    624         *iAccelAttr = WGL_NO_ACCELERATION_ARB;
    625         pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
    626         *iAccelAttr = WGL_FULL_ACCELERATION_ARB;  /* if we try again. */
    627     }
    628     if (!pixel_format) {
    629         pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
    630     }
    631     if (!pixel_format) {
    632         return SDL_SetError("No matching GL pixel format available");
    633     }
    634     if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
    635         return WIN_SetError("SetPixelFormat()");
    636     }
    637     return 0;
    638 }
    639 
    640 int
    641 WIN_GL_SetupWindow(_THIS, SDL_Window * window)
    642 {
    643     /* The current context is lost in here; save it and reset it. */
    644     SDL_Window *current_win = SDL_GL_GetCurrentWindow();
    645     SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
    646     const int retval = WIN_GL_SetupWindowInternal(_this, window);
    647     WIN_GL_MakeCurrent(_this, current_win, current_ctx);
    648     return retval;
    649 }
    650 
    651 SDL_bool
    652 WIN_GL_UseEGL(_THIS)
    653 {
    654     SDL_assert(_this->gl_data != NULL);
    655     SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
    656 
    657     return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE)
    658             || _this->gl_config.major_version == 1 /* No WGL extension for OpenGL ES 1.x profiles. */
    659             || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
    660             || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
    661                 && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
    662 }
    663 
    664 SDL_GLContext
    665 WIN_GL_CreateContext(_THIS, SDL_Window * window)
    666 {
    667     HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
    668     HGLRC context, share_context;
    669 
    670     if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && WIN_GL_UseEGL(_this)) {
    671 #if SDL_VIDEO_OPENGL_EGL        
    672         /* Switch to EGL based functions */
    673         WIN_GL_UnloadLibrary(_this);
    674         _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
    675         _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
    676         _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
    677         _this->GL_CreateContext = WIN_GLES_CreateContext;
    678         _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
    679         _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
    680         _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
    681         _this->GL_SwapWindow = WIN_GLES_SwapWindow;
    682         _this->GL_DeleteContext = WIN_GLES_DeleteContext;
    683         
    684         if (WIN_GLES_LoadLibrary(_this, NULL) != 0) {
    685             return NULL;
    686         }
    687         
    688         return WIN_GLES_CreateContext(_this, window);
    689 #else
    690         SDL_SetError("SDL not configured with EGL support");
    691         return NULL;
    692 #endif
    693     }
    694 
    695     if (_this->gl_config.share_with_current_context) {
    696         share_context = (HGLRC)SDL_GL_GetCurrentContext();
    697     } else {
    698         share_context = 0;
    699     }
    700 
    701     if (_this->gl_config.major_version < 3 &&
    702         _this->gl_config.profile_mask == 0 &&
    703         _this->gl_config.flags == 0) {
    704         /* Create legacy context */
    705         context = _this->gl_data->wglCreateContext(hdc);
    706         if( share_context != 0 ) {
    707             _this->gl_data->wglShareLists(share_context, context);
    708         }
    709     } else {
    710         PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
    711         HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
    712         if (!temp_context) {
    713             SDL_SetError("Could not create GL context");
    714             return NULL;
    715         }
    716 
    717         /* Make the context current */
    718         if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
    719             WIN_GL_DeleteContext(_this, temp_context);
    720             return NULL;
    721         }
    722 
    723         wglCreateContextAttribsARB =
    724             (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
    725             wglGetProcAddress("wglCreateContextAttribsARB");
    726         if (!wglCreateContextAttribsARB) {
    727             SDL_SetError("GL 3.x is not supported");
    728             context = temp_context;
    729         } else {
    730             int attribs[15];  /* max 14 attributes plus terminator */
    731             int iattr = 0;
    732 
    733             attribs[iattr++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
    734             attribs[iattr++] = _this->gl_config.major_version;
    735             attribs[iattr++] = WGL_CONTEXT_MINOR_VERSION_ARB;
    736             attribs[iattr++] = _this->gl_config.minor_version;
    737 
    738             /* SDL profile bits match WGL profile bits */
    739             if (_this->gl_config.profile_mask != 0) {
    740                 attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
    741                 attribs[iattr++] = _this->gl_config.profile_mask;
    742             }
    743 
    744             /* SDL flags match WGL flags */
    745             if (_this->gl_config.flags != 0) {
    746                 attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
    747                 attribs[iattr++] = _this->gl_config.flags;
    748             }
    749 
    750             /* only set if wgl extension is available */
    751             if (_this->gl_data->HAS_WGL_ARB_context_flush_control) {
    752                 attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
    753                 attribs[iattr++] = _this->gl_config.release_behavior ?
    754                                     WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
    755                                     WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
    756             }
    757 
    758             /* only set if wgl extension is available */
    759             if (_this->gl_data->HAS_WGL_ARB_create_context_robustness) {
    760                 attribs[iattr++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
    761                 attribs[iattr++] = _this->gl_config.reset_notification ?
    762                                     WGL_LOSE_CONTEXT_ON_RESET_ARB :
    763                                     WGL_NO_RESET_NOTIFICATION_ARB;
    764             }
    765 
    766             /* only set if wgl extension is available */
    767             if (_this->gl_data->HAS_WGL_ARB_create_context_no_error) {
    768                 attribs[iattr++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB;
    769                 attribs[iattr++] = _this->gl_config.no_error;
    770             }
    771 
    772             attribs[iattr++] = 0;
    773 
    774             /* Create the GL 3.x context */
    775             context = wglCreateContextAttribsARB(hdc, share_context, attribs);
    776             /* Delete the GL 2.x context */
    777             _this->gl_data->wglDeleteContext(temp_context);
    778         }
    779     }
    780 
    781     if (!context) {
    782         WIN_SetError("Could not create GL context");
    783         return NULL;
    784     }
    785 
    786     if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
    787         WIN_GL_DeleteContext(_this, context);
    788         return NULL;
    789     }
    790 
    791     return context;
    792 }
    793 
    794 int
    795 WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
    796 {
    797     HDC hdc;
    798 
    799     if (!_this->gl_data) {
    800         return SDL_SetError("OpenGL not initialized");
    801     }
    802 
    803     /* sanity check that higher level handled this. */
    804     SDL_assert(window || (!window && !context));
    805 
    806     /* Some Windows drivers freak out if hdc is NULL, even when context is
    807        NULL, against spec. Since hdc is _supposed_ to be ignored if context
    808        is NULL, we either use the current GL window, or do nothing if we
    809        already have no current context. */
    810     if (!window) {
    811         window = SDL_GL_GetCurrentWindow();
    812         if (!window) {
    813             SDL_assert(SDL_GL_GetCurrentContext() == NULL);
    814             return 0;  /* already done. */
    815         }
    816     }
    817 
    818     hdc = ((SDL_WindowData *) window->driverdata)->hdc;
    819     if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
    820         return WIN_SetError("wglMakeCurrent()");
    821     }
    822     return 0;
    823 }
    824 
    825 int
    826 WIN_GL_SetSwapInterval(_THIS, int interval)
    827 {
    828     if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
    829         return SDL_SetError("Negative swap interval unsupported in this GL");
    830     } else if (_this->gl_data->wglSwapIntervalEXT) {
    831         if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
    832             return WIN_SetError("wglSwapIntervalEXT()");
    833         }
    834     } else {
    835         return SDL_Unsupported();
    836     }
    837     return 0;
    838 }
    839 
    840 int
    841 WIN_GL_GetSwapInterval(_THIS)
    842 {
    843     int retval = 0;
    844     if (_this->gl_data->wglGetSwapIntervalEXT) {
    845         retval = _this->gl_data->wglGetSwapIntervalEXT();
    846     }
    847     return retval;
    848 }
    849 
    850 int
    851 WIN_GL_SwapWindow(_THIS, SDL_Window * window)
    852 {
    853     HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
    854 
    855     if (!SwapBuffers(hdc)) {
    856         return WIN_SetError("SwapBuffers()");
    857     }
    858     return 0;
    859 }
    860 
    861 void
    862 WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
    863 {
    864     if (!_this->gl_data) {
    865         return;
    866     }
    867     _this->gl_data->wglDeleteContext((HGLRC) context);
    868 }
    869 
    870 
    871 SDL_bool
    872 WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
    873 {
    874     HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
    875     HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
    876     BOOL result;
    877 
    878     /* get the pixel format of the fromWindow */
    879     int pixel_format = GetPixelFormat(hfromdc);
    880     PIXELFORMATDESCRIPTOR pfd;
    881     SDL_memset(&pfd, 0, sizeof(pfd));
    882     DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
    883 
    884     /* set the pixel format of the toWindow */
    885     result = SetPixelFormat(htodc, pixel_format, &pfd);
    886 
    887     return result ? SDL_TRUE : SDL_FALSE;
    888 }
    889 
    890 #endif /* SDL_VIDEO_OPENGL_WGL */
    891 
    892 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
    893 
    894 /* vi: set ts=4 sw=4 expandtab: */