src/video/wincommon/SDL_wingl.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 07 Nov 2011 16:01:03 -0500
branchSDL-1.2
changeset 6059 a04171d6fa11
parent 6057 d0b7c45e982e
child 6137 4720145f848b
permissions -rw-r--r--
Windows: If we don't care about OpenGL accel and FULL fails, try NO accel.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* WGL implementation of SDL OpenGL support */
    25 
    26 #if SDL_VIDEO_OPENGL
    27 #include "SDL_opengl.h"
    28 #endif
    29 #include "SDL_lowvideo.h"
    30 #include "SDL_wingl_c.h"
    31 
    32 #if SDL_VIDEO_OPENGL
    33 #define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL"
    34 #endif
    35 
    36 /* If setting the HDC fails, we may need to recreate the window (MSDN) */
    37 static int WIN_GL_ResetWindow(_THIS)
    38 {
    39 	int status = 0;
    40 
    41 #ifndef _WIN32_WCE /* FIXME WinCE needs the UNICODE version of CreateWindow() */
    42 	/* This doesn't work with DirectX code (see CVS comments) */
    43 	/* If we were passed a window, then we can't create a new one */
    44 	if ( !SDL_windowid && SDL_strcmp(this->name, "windib") == 0 ) {
    45 		/* Save the existing window attributes */
    46 		LONG style;
    47 		RECT rect = { 0, 0, 0, 0 };
    48 		style = GetWindowLong(SDL_Window, GWL_STYLE);
    49 		GetWindowRect(SDL_Window, &rect);
    50 		DestroyWindow(SDL_Window);
    51 		WIN_FlushMessageQueue();
    52 
    53 		SDL_resizing = 1;
    54 		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
    55 		                          style,
    56 		                          rect.left, rect.top,
    57 		                          (rect.right-rect.left)+1,
    58 		                          (rect.bottom-rect.top)+1,
    59 		                          NULL, NULL, SDL_Instance, NULL);
    60 		WIN_FlushMessageQueue();
    61 		SDL_resizing = 0;
    62 
    63 		if ( SDL_Window ) {
    64 			this->SetCaption(this, this->wm_title, this->wm_icon);
    65 		} else {
    66 			SDL_SetError("Couldn't create window");
    67 			status = -1;
    68 		}
    69 	} else
    70 #endif /* !_WIN32_WCE */
    71 	{
    72 		SDL_SetError("Unable to reset window for OpenGL context");
    73 		status = -1;
    74 	}
    75 	return(status);
    76 }
    77 
    78 #if SDL_VIDEO_OPENGL
    79 
    80 static int ExtensionSupported(const char *extension, const char *extensions)
    81 {
    82 	const char *start;
    83 	const char *where, *terminator;
    84 
    85 	/* Extension names should not have spaces. */
    86 	where = SDL_strchr(extension, ' ');
    87 	if ( where || *extension == '\0' )
    88 	      return 0;
    89 	
    90 	if ( ! extensions )
    91 		return 0;
    92 
    93 	/* It takes a bit of care to be fool-proof about parsing the
    94 	 *      OpenGL extensions string. Don't be fooled by sub-strings,
    95 	 *           etc. */
    96 	
    97 	start = extensions;
    98 	
    99 	for (;;)
   100 	{
   101 		where = SDL_strstr(start, extension);
   102 		if (!where) break;
   103 		
   104 		terminator = where + SDL_strlen(extension);
   105 		if (where == start || *(where - 1) == ' ')
   106 	        if (*terminator == ' ' || *terminator == '\0') return 1;
   107 
   108 		start = terminator;
   109 	}
   110 	
   111 	return 0;
   112 }
   113 
   114 static int ChoosePixelFormatARB(_THIS, const int *iAttribs, const FLOAT *fAttribs)
   115 {
   116 	HWND hwnd;
   117 	HDC hdc;
   118 	HGLRC hglrc;
   119 	const char * (WINAPI *wglGetExtensionsStringARB)(HDC) = 0;
   120 	const char *extensions;
   121 	int pformat = 0;
   122 	UINT matches = 0;
   123 
   124 	hwnd = CreateWindow(SDL_Appname, SDL_Appname, WS_POPUP | WS_DISABLED,
   125 	                    0, 0, 10, 10,
   126 	                    NULL, NULL, SDL_Instance, NULL);
   127 	WIN_FlushMessageQueue();
   128 
   129 	hdc = GetDC(hwnd);
   130 
   131 	SetPixelFormat(hdc, ChoosePixelFormat(hdc, &GL_pfd), &GL_pfd);
   132 
   133 	hglrc = this->gl_data->wglCreateContext(hdc);
   134 	if ( hglrc ) {
   135 		this->gl_data->wglMakeCurrent(hdc, hglrc);
   136 	}
   137 
   138 	wglGetExtensionsStringARB = (const char * (WINAPI *)(HDC))
   139 		this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
   140 
   141 	if( wglGetExtensionsStringARB ) {
   142 		extensions = wglGetExtensionsStringARB(hdc);
   143 	} else {
   144 		extensions = NULL;
   145 	}
   146 
   147 	this->gl_data->WGL_ARB_pixel_format = 0;
   148 	if( ExtensionSupported("WGL_ARB_pixel_format", extensions) ) {
   149 		BOOL (WINAPI *wglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
   150 		wglChoosePixelFormatARB =
   151 			(BOOL (WINAPI *)(HDC, const int *, const FLOAT *, UINT, int *, UINT *))
   152 			this->gl_data->wglGetProcAddress("wglChoosePixelFormatARB");
   153 		if( wglChoosePixelFormatARB &&
   154 		    wglChoosePixelFormatARB(hdc, iAttribs, fAttribs, 1, &pformat, &matches) && pformat ) {
   155 			this->gl_data->WGL_ARB_pixel_format = 1;
   156 		}
   157 	}
   158 	
   159 	if ( hglrc ) {
   160 		this->gl_data->wglMakeCurrent(NULL, NULL);
   161 		this->gl_data->wglDeleteContext(hglrc);
   162 	}
   163 	ReleaseDC(hwnd, hdc);
   164 	DestroyWindow(hwnd);
   165 	WIN_FlushMessageQueue();
   166 
   167 	return pformat;
   168 }
   169 
   170 #endif /* SDL_VIDEO_OPENGL */
   171 
   172 int WIN_GL_SetupWindow(_THIS)
   173 {
   174 	int retval;
   175 #if SDL_VIDEO_OPENGL
   176 	int i;
   177 	int iAttribs[64];
   178 	int *iAttr;
   179 	int *iAccelAttr = NULL;
   180 	float fAttribs[1] = { 0 };
   181 	const GLubyte *(WINAPI *glGetStringFunc)(GLenum);
   182 	const char *wglext;
   183 
   184 	/* load the gl driver from a default path */
   185 	if ( ! this->gl_config.driver_loaded ) {
   186 		/* no driver has been loaded, use default (ourselves) */
   187 		if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) {
   188 			return(-1);
   189 		}
   190 	}
   191 
   192 	/* Set up the pixel format descriptor with our needed format */
   193 	SDL_memset(&GL_pfd, 0, sizeof(GL_pfd));
   194 	GL_pfd.nSize = sizeof(GL_pfd);
   195 	GL_pfd.nVersion = 1;
   196 	GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
   197 	if ( this->gl_config.double_buffer ) {
   198 		GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
   199 	}
   200 	if ( this->gl_config.stereo ) {
   201 		GL_pfd.dwFlags |= PFD_STEREO;
   202 	}
   203 	GL_pfd.iPixelType = PFD_TYPE_RGBA;
   204 	GL_pfd.cColorBits = this->gl_config.buffer_size;
   205 	GL_pfd.cRedBits = this->gl_config.red_size;
   206 	GL_pfd.cGreenBits = this->gl_config.green_size;
   207 	GL_pfd.cBlueBits = this->gl_config.blue_size;
   208 	GL_pfd.cAlphaBits = this->gl_config.alpha_size;
   209 	GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
   210 	GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
   211 	GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
   212 	GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
   213 	GL_pfd.cAccumBits =
   214 		(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
   215 		 GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
   216 	GL_pfd.cDepthBits = this->gl_config.depth_size;
   217 	GL_pfd.cStencilBits = this->gl_config.stencil_size;
   218 
   219 	/* setup WGL_ARB_pixel_format attribs */
   220 	iAttr = &iAttribs[0];
   221 
   222 	*iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
   223 	*iAttr++ = GL_TRUE;
   224 	*iAttr++ = WGL_RED_BITS_ARB;
   225 	*iAttr++ = this->gl_config.red_size;
   226 	*iAttr++ = WGL_GREEN_BITS_ARB;
   227 	*iAttr++ = this->gl_config.green_size;
   228 	*iAttr++ = WGL_BLUE_BITS_ARB;
   229 	*iAttr++ = this->gl_config.blue_size;
   230 
   231 	/* We always choose either FULL or NO accel on Windows, because of flaky
   232 	   drivers. If the app didn't specify, we use FULL, because that's
   233 	   probably what they wanted (and if you didn't care and got FULL, that's
   234 	   a perfectly valid result in any case. */
   235 	*iAttr++ = WGL_ACCELERATION_ARB;
   236 	iAccelAttr = iAttr;
   237 	if (this->gl_config.accelerated) {
   238 		*iAttr++ = WGL_FULL_ACCELERATION_ARB;
   239 	} else {
   240 		*iAttr++ = WGL_NO_ACCELERATION_ARB;
   241 	}
   242 
   243 	if ( this->gl_config.alpha_size ) {
   244 		*iAttr++ = WGL_ALPHA_BITS_ARB;
   245 		*iAttr++ = this->gl_config.alpha_size;
   246 	}
   247 
   248 	*iAttr++ = WGL_DOUBLE_BUFFER_ARB;
   249 	*iAttr++ = this->gl_config.double_buffer;
   250 
   251 	*iAttr++ = WGL_DEPTH_BITS_ARB;
   252 	*iAttr++ = this->gl_config.depth_size;
   253 
   254 	if ( this->gl_config.stencil_size ) {
   255 		*iAttr++ = WGL_STENCIL_BITS_ARB;
   256 		*iAttr++ = this->gl_config.stencil_size;
   257 	}
   258 
   259 	if ( this->gl_config.accum_red_size ) {
   260 		*iAttr++ = WGL_ACCUM_RED_BITS_ARB;
   261 		*iAttr++ = this->gl_config.accum_red_size;
   262 	}
   263 
   264 	if ( this->gl_config.accum_green_size ) {
   265 		*iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
   266 		*iAttr++ = this->gl_config.accum_green_size;
   267 	}
   268 
   269 	if ( this->gl_config.accum_blue_size ) {
   270 		*iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
   271 		*iAttr++ = this->gl_config.accum_blue_size;
   272 	}
   273 
   274 	if ( this->gl_config.accum_alpha_size ) {
   275 		*iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
   276 		*iAttr++ = this->gl_config.accum_alpha_size;
   277 	}
   278 
   279 	if ( this->gl_config.stereo ) {
   280 		*iAttr++ = WGL_STEREO_ARB;
   281 		*iAttr++ = GL_TRUE;
   282 	}
   283 
   284 	if ( this->gl_config.multisamplebuffers ) {
   285 		*iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
   286 		*iAttr++ = this->gl_config.multisamplebuffers;
   287 	}
   288 
   289 	if ( this->gl_config.multisamplesamples ) {
   290 		*iAttr++ = WGL_SAMPLES_ARB;
   291 		*iAttr++ = this->gl_config.multisamplesamples;
   292 	}
   293 
   294 	*iAttr = 0;
   295 
   296 	for ( i=0; ; ++i ) {
   297 		/* Get the window device context for our OpenGL drawing */
   298 		GL_hdc = GetDC(SDL_Window);
   299 		if ( GL_hdc == NULL ) {
   300 			SDL_SetError("Unable to get DC for SDL_Window");
   301 			return(-1);
   302 		}
   303 
   304 		/* Choose and set the closest available pixel format */
   305 		pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs);
   306 		/* App said "don't care about accel" and FULL accel failed. Try NO. */
   307 		if ( ( !pixel_format ) && ( this->gl_config.accelerated < 0 ) ) {
   308 			*iAccelAttr = WGL_NO_ACCELERATION_ARB;
   309 			pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs);
   310 			*iAccelAttr = WGL_FULL_ACCELERATION_ARB;  /* if we try again. */
   311 		}
   312 		if ( !pixel_format ) {
   313 			pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
   314 		}
   315 		if ( !pixel_format ) {
   316 			SDL_SetError("No matching GL pixel format available");
   317 			return(-1);
   318 		}
   319 		if ( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) {
   320 			if ( i == 0 ) {
   321 				/* First time through, try resetting the window */
   322 				if ( WIN_GL_ResetWindow(this) < 0 ) {
   323 					return(-1);
   324 				}
   325 				continue;
   326 			}
   327 			SDL_SetError("Unable to set HDC pixel format");
   328 			return(-1);
   329 		}
   330 		/* We either succeeded or failed by this point */
   331 		break;
   332 	}
   333 	DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
   334 
   335 	GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
   336 	if ( GL_hrc == NULL ) {
   337 		SDL_SetError("Unable to create GL context");
   338 		return(-1);
   339 	}
   340 	if ( WIN_GL_MakeCurrent(this) < 0 ) {
   341 		return(-1);
   342 	}
   343 	gl_active = 1;
   344 
   345 	/* Get the wglGetPixelFormatAttribivARB pointer for the context */
   346 	if ( this->gl_data->WGL_ARB_pixel_format ) {
   347 		this->gl_data->wglGetPixelFormatAttribivARB =
   348 			(BOOL (WINAPI *)(HDC, int, int, UINT, const int *, int *))
   349 			this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB");
   350 	} else {
   351 		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
   352 	}
   353 
   354 	/* Vsync control under Windows.  Checking glGetString here is
   355 	 * somewhat a documented and reliable hack - it was originally
   356 	 * as a feature added by mistake, but since so many people rely
   357 	 * on it, it will not be removed.  strstr should be safe here.*/
   358 	glGetStringFunc = WIN_GL_GetProcAddress(this, "glGetString");
   359 	if ( glGetStringFunc ) {
   360 		wglext = (const char *)glGetStringFunc(GL_EXTENSIONS);
   361 	} else {
   362 		/* Uh oh, something is seriously wrong here... */
   363 		wglext = NULL;
   364 	}
   365 	if ( wglext && SDL_strstr(wglext, "WGL_EXT_swap_control") ) {
   366 		this->gl_data->wglSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglSwapIntervalEXT");
   367 		this->gl_data->wglGetSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglGetSwapIntervalEXT");
   368 	} else {
   369 		this->gl_data->wglSwapIntervalEXT = NULL;
   370 		this->gl_data->wglGetSwapIntervalEXT = NULL;
   371 	}
   372 	if ( this->gl_config.swap_control >= 0 ) {
   373 		if ( this->gl_data->wglSwapIntervalEXT ) {
   374 			this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control);
   375 		}
   376 	}
   377 #else
   378 	SDL_SetError("WIN driver not configured with OpenGL");
   379 #endif
   380 	if ( gl_active ) {
   381 		retval = 0;
   382 	} else {
   383 		retval = -1;
   384 	}
   385 	return(retval);
   386 }
   387 
   388 void WIN_GL_ShutDown(_THIS)
   389 {
   390 #if SDL_VIDEO_OPENGL
   391 	/* Clean up OpenGL */
   392 	if ( GL_hrc ) {
   393 		this->gl_data->wglMakeCurrent(NULL, NULL);
   394 		this->gl_data->wglDeleteContext(GL_hrc);
   395 		GL_hrc = NULL;
   396 	}
   397 	if ( GL_hdc ) {
   398 		ReleaseDC(SDL_Window, GL_hdc);
   399 		GL_hdc = NULL;
   400 	}
   401 	gl_active = 0;
   402 
   403 	WIN_GL_UnloadLibrary(this);
   404 #endif /* SDL_VIDEO_OPENGL */
   405 }
   406 
   407 #if SDL_VIDEO_OPENGL
   408 
   409 /* Make the current context active */
   410 int WIN_GL_MakeCurrent(_THIS)
   411 {
   412 	int retval;
   413 
   414 	retval = 0;
   415 	if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) {
   416 		SDL_SetError("Unable to make GL context current");
   417 		retval = -1;
   418 	}
   419 	return(retval);
   420 }
   421 
   422 /* Get attribute data from wgl. */
   423 int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
   424 {
   425 	int retval;
   426 
   427 	if (attrib == SDL_GL_SWAP_CONTROL) {
   428 		if ( this->gl_data->wglGetSwapIntervalEXT ) {
   429 			*value = this->gl_data->wglGetSwapIntervalEXT();
   430 			return 0;
   431 		}
   432 		return -1;
   433 	}
   434 
   435 	if ( this->gl_data->wglGetPixelFormatAttribivARB ) {
   436 		int wgl_attrib;
   437 
   438 		switch(attrib) {
   439 		    case SDL_GL_RED_SIZE:
   440 			wgl_attrib = WGL_RED_BITS_ARB;
   441 			break;
   442 		    case SDL_GL_GREEN_SIZE:
   443 			wgl_attrib = WGL_GREEN_BITS_ARB;
   444 			break;
   445 		    case SDL_GL_BLUE_SIZE:
   446 			wgl_attrib = WGL_BLUE_BITS_ARB;
   447 			break;
   448 		    case SDL_GL_ALPHA_SIZE:
   449 			wgl_attrib = WGL_ALPHA_BITS_ARB;
   450 			break;
   451 		    case SDL_GL_DOUBLEBUFFER:
   452 			wgl_attrib = WGL_DOUBLE_BUFFER_ARB;
   453 			break;
   454 		    case SDL_GL_BUFFER_SIZE:
   455 			wgl_attrib = WGL_COLOR_BITS_ARB;
   456 			break;
   457 		    case SDL_GL_DEPTH_SIZE:
   458 			wgl_attrib = WGL_DEPTH_BITS_ARB;
   459 			break;
   460 		    case SDL_GL_STENCIL_SIZE:
   461 			wgl_attrib = WGL_STENCIL_BITS_ARB;
   462 			break;
   463 		    case SDL_GL_ACCUM_RED_SIZE:
   464 			wgl_attrib = WGL_ACCUM_RED_BITS_ARB;
   465 			break;
   466 		    case SDL_GL_ACCUM_GREEN_SIZE:
   467 			wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB;
   468 			break;
   469 		    case SDL_GL_ACCUM_BLUE_SIZE:
   470 			wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB;
   471 			break;
   472 		    case SDL_GL_ACCUM_ALPHA_SIZE:
   473 			wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB;
   474 			break;
   475 		    case SDL_GL_STEREO:
   476 			wgl_attrib = WGL_STEREO_ARB;
   477 			break;
   478 		    case SDL_GL_MULTISAMPLEBUFFERS:
   479 			wgl_attrib = WGL_SAMPLE_BUFFERS_ARB;
   480 			break;
   481 		    case SDL_GL_MULTISAMPLESAMPLES:
   482 			wgl_attrib = WGL_SAMPLES_ARB;
   483 			break;
   484 		    case SDL_GL_ACCELERATED_VISUAL:
   485 			wgl_attrib = WGL_ACCELERATION_ARB;
   486 			this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
   487 			if ( *value == WGL_NO_ACCELERATION_ARB ) {
   488 				*value = SDL_FALSE;
   489 			} else {
   490 				*value = SDL_TRUE;
   491 			}
   492 			return 0;
   493 		    default:
   494 			return(-1);
   495 		}
   496 		this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
   497 
   498 		return 0;
   499 	}
   500 
   501 	retval = 0;
   502 	switch ( attrib ) {
   503 	    case SDL_GL_RED_SIZE:
   504 		*value = GL_pfd.cRedBits;
   505 		break;
   506 	    case SDL_GL_GREEN_SIZE:
   507 		*value = GL_pfd.cGreenBits;
   508 		break;
   509 	    case SDL_GL_BLUE_SIZE:
   510 		*value = GL_pfd.cBlueBits;
   511 		break;
   512 	    case SDL_GL_ALPHA_SIZE:
   513 		*value = GL_pfd.cAlphaBits;
   514 		break;
   515 	    case SDL_GL_DOUBLEBUFFER:
   516 		if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) {
   517 			*value = 1;
   518 		} else {
   519 			*value = 0;
   520 		}
   521 		break;
   522 	    case SDL_GL_BUFFER_SIZE:
   523 		*value = GL_pfd.cColorBits;
   524 		break;
   525 	    case SDL_GL_DEPTH_SIZE:
   526 		*value = GL_pfd.cDepthBits;
   527 		break;
   528 	    case SDL_GL_STENCIL_SIZE:
   529 		*value = GL_pfd.cStencilBits;
   530 		break;
   531 	    case SDL_GL_ACCUM_RED_SIZE:
   532 		*value = GL_pfd.cAccumRedBits;
   533 		break;
   534 	    case SDL_GL_ACCUM_GREEN_SIZE:
   535 		*value = GL_pfd.cAccumGreenBits;
   536 		break;
   537 	    case SDL_GL_ACCUM_BLUE_SIZE:
   538 		*value = GL_pfd.cAccumBlueBits;
   539 		break;
   540 	    case SDL_GL_ACCUM_ALPHA_SIZE:
   541 		*value = GL_pfd.cAccumAlphaBits;
   542 		break;
   543 	    case SDL_GL_STEREO:
   544 		if ( GL_pfd.dwFlags & PFD_STEREO ) {
   545 			*value = 1;
   546 		} else {
   547 			*value = 0;
   548 		}
   549 		break;
   550 	    case SDL_GL_MULTISAMPLEBUFFERS:
   551 		*value = 0;
   552 		break;
   553 	    case SDL_GL_MULTISAMPLESAMPLES:
   554 		*value = 1;
   555 		break;
   556 	    case SDL_GL_SWAP_CONTROL:
   557 		if ( this->gl_data->wglGetSwapIntervalEXT ) {
   558 			*value = this->gl_data->wglGetSwapIntervalEXT();
   559 			return 0;
   560 		} else {
   561 			return -1;
   562 		}
   563 		break;
   564 	    default:
   565 		retval = -1;
   566 		break;
   567 	}
   568 	return retval;
   569 }
   570 
   571 void WIN_GL_SwapBuffers(_THIS)
   572 {
   573 	SwapBuffers(GL_hdc);
   574 }
   575 
   576 void WIN_GL_UnloadLibrary(_THIS)
   577 {
   578 	if ( this->gl_config.driver_loaded ) {
   579 		FreeLibrary((HMODULE)this->gl_config.dll_handle);
   580 
   581 		this->gl_data->wglGetProcAddress = NULL;
   582 		this->gl_data->wglCreateContext = NULL;
   583 		this->gl_data->wglDeleteContext = NULL;
   584 		this->gl_data->wglMakeCurrent = NULL;
   585 		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
   586 		this->gl_data->wglSwapIntervalEXT = NULL;
   587 		this->gl_data->wglGetSwapIntervalEXT = NULL;
   588 
   589 		this->gl_config.dll_handle = NULL;
   590 		this->gl_config.driver_loaded = 0;
   591 	}
   592 }
   593 
   594 /* Passing a NULL path means load pointers from the application */
   595 int WIN_GL_LoadLibrary(_THIS, const char* path) 
   596 {
   597 	HMODULE handle;
   598 
   599  	if ( gl_active ) {
   600  		SDL_SetError("OpenGL context already created");
   601  		return -1;
   602  	}
   603 
   604 	if ( path == NULL ) {
   605 		path = DEFAULT_GL_DRIVER_PATH;
   606 	}
   607 	handle = LoadLibrary(path);
   608 	if ( handle == NULL ) {
   609 		SDL_SetError("Could not load OpenGL library");
   610 		return -1;
   611 	}
   612 
   613 	/* Unload the old driver and reset the pointers */
   614 	WIN_GL_UnloadLibrary(this);
   615 
   616 	/* Load new function pointers */
   617 	SDL_memset(this->gl_data, 0, sizeof(*this->gl_data));
   618 	this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *))
   619 		GetProcAddress(handle, "wglGetProcAddress");
   620 	this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC))
   621 		GetProcAddress(handle, "wglCreateContext");
   622 	this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC))
   623 		GetProcAddress(handle, "wglDeleteContext");
   624 	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
   625 		GetProcAddress(handle, "wglMakeCurrent");
   626 	this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int))
   627 		GetProcAddress(handle, "wglSwapIntervalEXT");
   628 	this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void))
   629 		GetProcAddress(handle, "wglGetSwapIntervalEXT");
   630 
   631 	if ( (this->gl_data->wglGetProcAddress == NULL) ||
   632 	     (this->gl_data->wglCreateContext == NULL) ||
   633 	     (this->gl_data->wglDeleteContext == NULL) ||
   634 	     (this->gl_data->wglMakeCurrent == NULL) ) {
   635 		SDL_SetError("Could not retrieve OpenGL functions");
   636 		FreeLibrary(handle);
   637 		return -1;
   638 	}
   639 
   640 	this->gl_config.dll_handle = handle;
   641 	SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path));
   642 	this->gl_config.driver_loaded = 1;
   643 	return 0;
   644 }
   645 
   646 void *WIN_GL_GetProcAddress(_THIS, const char* proc)
   647 {
   648 	void *func;
   649 
   650 	/* This is to pick up extensions */
   651 	func = this->gl_data->wglGetProcAddress(proc);
   652 	if ( ! func ) {
   653 		/* This is probably a normal GL function */
   654 		func = GetProcAddress(this->gl_config.dll_handle, proc);
   655 	}
   656 	return func;
   657 }
   658 
   659 #endif /* SDL_VIDEO_OPENGL */