src/video/windows/SDL_windowsopengl.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 20 Feb 2012 23:37:57 -0500
changeset 6296 b42657486c0d
parent 6138 4c64952a58fb
child 6380 3990b7d564d7
permissions -rwxr-xr-x
Add OpenGL 3.X context creation support

Matthias Bentrup 2011-10-30 03:58:24 PDT

I've updated the context creation patch to include the bugfixes by Martin
Schreiber and also included a profile bit to request a ES2 compatible profile.

The wgl context creation may use 2 call to wglChoosePixelFormat if no
acceleration attribute is selected, this should work around a bug with buggy
AMD drivers (see #1254).
     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           0x2093
    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     _this->gl_data->wglSwapIntervalEXT = (void (WINAPI *) (int))
   116         GetProcAddress(handle, "wglSwapIntervalEXT");
   117     _this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *) (void))
   118         GetProcAddress(handle, "wglGetSwapIntervalEXT");
   119 
   120     if (!_this->gl_data->wglGetProcAddress ||
   121         !_this->gl_data->wglCreateContext ||
   122         !_this->gl_data->wglDeleteContext ||
   123         !_this->gl_data->wglMakeCurrent) {
   124         SDL_SetError("Could not retrieve OpenGL functions");
   125         SDL_UnloadObject(handle);
   126         return -1;
   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->WGL_ARB_pixel_format = 0;
   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->WGL_ARB_pixel_format = 1;
   358         }
   359     }
   360 
   361     /* Check for WGL_EXT_swap_control */
   362     if (HasExtension("WGL_EXT_swap_control", extensions)) {
   363         _this->gl_data->wglSwapIntervalEXT =
   364             WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
   365         _this->gl_data->wglGetSwapIntervalEXT =
   366             WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
   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->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 (_this->gl_data->wglSwapIntervalEXT) {
   615         _this->gl_data->wglSwapIntervalEXT(interval);
   616         return 0;
   617     } else {
   618         SDL_Unsupported();
   619         return -1;
   620     }
   621 }
   622 
   623 int
   624 WIN_GL_GetSwapInterval(_THIS)
   625 {
   626     if (_this->gl_data->wglGetSwapIntervalEXT) {
   627         return _this->gl_data->wglGetSwapIntervalEXT();
   628     } else {
   629         SDL_Unsupported();
   630         return -1;
   631     }
   632 }
   633 
   634 void
   635 WIN_GL_SwapWindow(_THIS, SDL_Window * window)
   636 {
   637     HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
   638 
   639     SwapBuffers(hdc);
   640 }
   641 
   642 void
   643 WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
   644 {
   645     _this->gl_data->wglDeleteContext((HGLRC) context);
   646 }
   647 
   648 #endif /* SDL_VIDEO_OPENGL_WGL */
   649 
   650 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   651 
   652 /* vi: set ts=4 sw=4 expandtab: */