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