src/video/windows/SDL_windowsopengl.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 01 Aug 2012 20:29:36 -0400
changeset 6382 64d54101773a
parent 6380 3990b7d564d7
child 6383 869effc44c41
permissions -rwxr-xr-x
Add support for (GLX|WGL)_EXT_swap_control_tear.

This required a small public API change: SDL_GL_SetSwapInterval() now accepts
negative values, and SDL_GL_GetSwapInterval() doesn't report errors anymore
(if it can't work, it'll return zero as a reasonable default).

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