src/video/windows/SDL_windowsopengl.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:53:27 -0800
changeset 8149 681eb46b8ac4
parent 8144 855b1d6d7d8e
child 8604 459bd7365e9d
permissions -rw-r--r--
Fixed bug 2374 - Update copyright for 2014...

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