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