src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 11 Jul 2013 12:17:13 -0400
changeset 7401 698995795574
parent 7191 75360622e65f
child 7412 50211a1fd557
permissions -rw-r--r--
Cleaned up WGL_ACCELERATION_ARB usage.

We now do FULL or NO accel based on the app's preference. If the app didn't
specify, we do FULL then fall back to NO.

(Not specifying anything--a true "don't care" scenario--breaks some ATI
drivers, so we try to keep to the spirit of it while forcing a specific
state.)

Previously, it would always do FULL, and try NO if it failed and the app
had requested NO or DONTCARE.

This is a transplant of hg changesets a04171d6fa11 and d0b7c45e982e from the
SDL-1.2 branch.

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