Home | History | Annotate | Download | only in wincommon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 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 (at) 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 	float fAttribs[1] = { 0 };
    180 	const GLubyte *(WINAPI *glGetStringFunc)(GLenum);
    181 	const char *wglext;
    182 
    183 	/* load the gl driver from a default path */
    184 	if ( ! this->gl_config.driver_loaded ) {
    185 		/* no driver has been loaded, use default (ourselves) */
    186 		if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) {
    187 			return(-1);
    188 		}
    189 	}
    190 
    191 	/* Set up the pixel format descriptor with our needed format */
    192 	SDL_memset(&GL_pfd, 0, sizeof(GL_pfd));
    193 	GL_pfd.nSize = sizeof(GL_pfd);
    194 	GL_pfd.nVersion = 1;
    195 	GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
    196 	if ( this->gl_config.double_buffer ) {
    197 		GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
    198 	}
    199 	if ( this->gl_config.stereo ) {
    200 		GL_pfd.dwFlags |= PFD_STEREO;
    201 	}
    202 	GL_pfd.iPixelType = PFD_TYPE_RGBA;
    203 	GL_pfd.cColorBits = this->gl_config.buffer_size;
    204 	GL_pfd.cRedBits = this->gl_config.red_size;
    205 	GL_pfd.cGreenBits = this->gl_config.green_size;
    206 	GL_pfd.cBlueBits = this->gl_config.blue_size;
    207 	GL_pfd.cAlphaBits = this->gl_config.alpha_size;
    208 	GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
    209 	GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
    210 	GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
    211 	GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
    212 	GL_pfd.cAccumBits =
    213 		(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
    214 		 GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
    215 	GL_pfd.cDepthBits = this->gl_config.depth_size;
    216 	GL_pfd.cStencilBits = this->gl_config.stencil_size;
    217 
    218 	/* setup WGL_ARB_pixel_format attribs */
    219 	iAttr = &iAttribs[0];
    220 
    221 	*iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
    222 	*iAttr++ = GL_TRUE;
    223 	*iAttr++ = WGL_ACCELERATION_ARB;
    224 	*iAttr++ = WGL_FULL_ACCELERATION_ARB;
    225 	*iAttr++ = WGL_RED_BITS_ARB;
    226 	*iAttr++ = this->gl_config.red_size;
    227 	*iAttr++ = WGL_GREEN_BITS_ARB;
    228 	*iAttr++ = this->gl_config.green_size;
    229 	*iAttr++ = WGL_BLUE_BITS_ARB;
    230 	*iAttr++ = this->gl_config.blue_size;
    231 
    232 	if ( this->gl_config.alpha_size ) {
    233 		*iAttr++ = WGL_ALPHA_BITS_ARB;
    234 		*iAttr++ = this->gl_config.alpha_size;
    235 	}
    236 
    237 	*iAttr++ = WGL_DOUBLE_BUFFER_ARB;
    238 	*iAttr++ = this->gl_config.double_buffer;
    239 
    240 	*iAttr++ = WGL_DEPTH_BITS_ARB;
    241 	*iAttr++ = this->gl_config.depth_size;
    242 
    243 	if ( this->gl_config.stencil_size ) {
    244 		*iAttr++ = WGL_STENCIL_BITS_ARB;
    245 		*iAttr++ = this->gl_config.stencil_size;
    246 	}
    247 
    248 	if ( this->gl_config.accum_red_size ) {
    249 		*iAttr++ = WGL_ACCUM_RED_BITS_ARB;
    250 		*iAttr++ = this->gl_config.accum_red_size;
    251 	}
    252 
    253 	if ( this->gl_config.accum_green_size ) {
    254 		*iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
    255 		*iAttr++ = this->gl_config.accum_green_size;
    256 	}
    257 
    258 	if ( this->gl_config.accum_blue_size ) {
    259 		*iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
    260 		*iAttr++ = this->gl_config.accum_blue_size;
    261 	}
    262 
    263 	if ( this->gl_config.accum_alpha_size ) {
    264 		*iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
    265 		*iAttr++ = this->gl_config.accum_alpha_size;
    266 	}
    267 
    268 	if ( this->gl_config.stereo ) {
    269 		*iAttr++ = WGL_STEREO_ARB;
    270 		*iAttr++ = GL_TRUE;
    271 	}
    272 
    273 	if ( this->gl_config.multisamplebuffers ) {
    274 		*iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
    275 		*iAttr++ = this->gl_config.multisamplebuffers;
    276 	}
    277 
    278 	if ( this->gl_config.multisamplesamples ) {
    279 		*iAttr++ = WGL_SAMPLES_ARB;
    280 		*iAttr++ = this->gl_config.multisamplesamples;
    281 	}
    282 
    283 	if ( this->gl_config.accelerated >= 0 ) {
    284 		*iAttr++ = WGL_ACCELERATION_ARB;
    285 		*iAttr++ = (this->gl_config.accelerated ? WGL_GENERIC_ACCELERATION_ARB : WGL_NO_ACCELERATION_ARB);
    286 	}
    287 
    288 	*iAttr = 0;
    289 
    290 	for ( i=0; ; ++i ) {
    291 		/* Get the window device context for our OpenGL drawing */
    292 		GL_hdc = GetDC(SDL_Window);
    293 		if ( GL_hdc == NULL ) {
    294 			SDL_SetError("Unable to get DC for SDL_Window");
    295 			return(-1);
    296 		}
    297 
    298 		/* Choose and set the closest available pixel format */
    299 		pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs);
    300 		if ( !pixel_format ) {
    301 			pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
    302 		}
    303 		if ( !pixel_format ) {
    304 			SDL_SetError("No matching GL pixel format available");
    305 			return(-1);
    306 		}
    307 		if ( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) {
    308 			if ( i == 0 ) {
    309 				/* First time through, try resetting the window */
    310 				if ( WIN_GL_ResetWindow(this) < 0 ) {
    311 					return(-1);
    312 				}
    313 				continue;
    314 			}
    315 			SDL_SetError("Unable to set HDC pixel format");
    316 			return(-1);
    317 		}
    318 		/* We either succeeded or failed by this point */
    319 		break;
    320 	}
    321 	DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
    322 
    323 	GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
    324 	if ( GL_hrc == NULL ) {
    325 		SDL_SetError("Unable to create GL context");
    326 		return(-1);
    327 	}
    328 	if ( WIN_GL_MakeCurrent(this) < 0 ) {
    329 		return(-1);
    330 	}
    331 	gl_active = 1;
    332 
    333 	/* Get the wglGetPixelFormatAttribivARB pointer for the context */
    334 	if ( this->gl_data->WGL_ARB_pixel_format ) {
    335 		this->gl_data->wglGetPixelFormatAttribivARB =
    336 			(BOOL (WINAPI *)(HDC, int, int, UINT, const int *, int *))
    337 			this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB");
    338 	} else {
    339 		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
    340 	}
    341 
    342 	/* Vsync control under Windows.  Checking glGetString here is
    343 	 * somewhat a documented and reliable hack - it was originally
    344 	 * as a feature added by mistake, but since so many people rely
    345 	 * on it, it will not be removed.  strstr should be safe here.*/
    346 	glGetStringFunc = WIN_GL_GetProcAddress(this, "glGetString");
    347 	if ( glGetStringFunc ) {
    348 		wglext = (const char *)glGetStringFunc(GL_EXTENSIONS);
    349 	} else {
    350 		/* Uh oh, something is seriously wrong here... */
    351 		wglext = NULL;
    352 	}
    353 	if ( wglext && SDL_strstr(wglext, "WGL_EXT_swap_control") ) {
    354 		this->gl_data->wglSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglSwapIntervalEXT");
    355 		this->gl_data->wglGetSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglGetSwapIntervalEXT");
    356 	} else {
    357 		this->gl_data->wglSwapIntervalEXT = NULL;
    358 		this->gl_data->wglGetSwapIntervalEXT = NULL;
    359 	}
    360 	if ( this->gl_config.swap_control >= 0 ) {
    361 		if ( this->gl_data->wglSwapIntervalEXT ) {
    362 			this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control);
    363 		}
    364 	}
    365 #else
    366 	SDL_SetError("WIN driver not configured with OpenGL");
    367 #endif
    368 	if ( gl_active ) {
    369 		retval = 0;
    370 	} else {
    371 		retval = -1;
    372 	}
    373 	return(retval);
    374 }
    375 
    376 void WIN_GL_ShutDown(_THIS)
    377 {
    378 #if SDL_VIDEO_OPENGL
    379 	/* Clean up OpenGL */
    380 	if ( GL_hrc ) {
    381 		this->gl_data->wglMakeCurrent(NULL, NULL);
    382 		this->gl_data->wglDeleteContext(GL_hrc);
    383 		GL_hrc = NULL;
    384 	}
    385 	if ( GL_hdc ) {
    386 		ReleaseDC(SDL_Window, GL_hdc);
    387 		GL_hdc = NULL;
    388 	}
    389 	gl_active = 0;
    390 
    391 	WIN_GL_UnloadLibrary(this);
    392 #endif /* SDL_VIDEO_OPENGL */
    393 }
    394 
    395 #if SDL_VIDEO_OPENGL
    396 
    397 /* Make the current context active */
    398 int WIN_GL_MakeCurrent(_THIS)
    399 {
    400 	int retval;
    401 
    402 	retval = 0;
    403 	if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) {
    404 		SDL_SetError("Unable to make GL context current");
    405 		retval = -1;
    406 	}
    407 	return(retval);
    408 }
    409 
    410 /* Get attribute data from wgl. */
    411 int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
    412 {
    413 	int retval;
    414 
    415 	if (attrib == SDL_GL_SWAP_CONTROL) {
    416 		if ( this->gl_data->wglGetSwapIntervalEXT ) {
    417 			*value = this->gl_data->wglGetSwapIntervalEXT();
    418 			return 0;
    419 		}
    420 		return -1;
    421 	}
    422 
    423 	if ( this->gl_data->wglGetPixelFormatAttribivARB ) {
    424 		int wgl_attrib;
    425 
    426 		switch(attrib) {
    427 		    case SDL_GL_RED_SIZE:
    428 			wgl_attrib = WGL_RED_BITS_ARB;
    429 			break;
    430 		    case SDL_GL_GREEN_SIZE:
    431 			wgl_attrib = WGL_GREEN_BITS_ARB;
    432 			break;
    433 		    case SDL_GL_BLUE_SIZE:
    434 			wgl_attrib = WGL_BLUE_BITS_ARB;
    435 			break;
    436 		    case SDL_GL_ALPHA_SIZE:
    437 			wgl_attrib = WGL_ALPHA_BITS_ARB;
    438 			break;
    439 		    case SDL_GL_DOUBLEBUFFER:
    440 			wgl_attrib = WGL_DOUBLE_BUFFER_ARB;
    441 			break;
    442 		    case SDL_GL_BUFFER_SIZE:
    443 			wgl_attrib = WGL_COLOR_BITS_ARB;
    444 			break;
    445 		    case SDL_GL_DEPTH_SIZE:
    446 			wgl_attrib = WGL_DEPTH_BITS_ARB;
    447 			break;
    448 		    case SDL_GL_STENCIL_SIZE:
    449 			wgl_attrib = WGL_STENCIL_BITS_ARB;
    450 			break;
    451 		    case SDL_GL_ACCUM_RED_SIZE:
    452 			wgl_attrib = WGL_ACCUM_RED_BITS_ARB;
    453 			break;
    454 		    case SDL_GL_ACCUM_GREEN_SIZE:
    455 			wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB;
    456 			break;
    457 		    case SDL_GL_ACCUM_BLUE_SIZE:
    458 			wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB;
    459 			break;
    460 		    case SDL_GL_ACCUM_ALPHA_SIZE:
    461 			wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB;
    462 			break;
    463 		    case SDL_GL_STEREO:
    464 			wgl_attrib = WGL_STEREO_ARB;
    465 			break;
    466 		    case SDL_GL_MULTISAMPLEBUFFERS:
    467 			wgl_attrib = WGL_SAMPLE_BUFFERS_ARB;
    468 			break;
    469 		    case SDL_GL_MULTISAMPLESAMPLES:
    470 			wgl_attrib = WGL_SAMPLES_ARB;
    471 			break;
    472 		    case SDL_GL_ACCELERATED_VISUAL:
    473 			wgl_attrib = WGL_ACCELERATION_ARB;
    474 			this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
    475 			if ( *value == WGL_NO_ACCELERATION_ARB ) {
    476 				*value = SDL_FALSE;
    477 			} else {
    478 				*value = SDL_TRUE;
    479 			}
    480 			return 0;
    481 		    default:
    482 			return(-1);
    483 		}
    484 		this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
    485 
    486 		return 0;
    487 	}
    488 
    489 	retval = 0;
    490 	switch ( attrib ) {
    491 	    case SDL_GL_RED_SIZE:
    492 		*value = GL_pfd.cRedBits;
    493 		break;
    494 	    case SDL_GL_GREEN_SIZE:
    495 		*value = GL_pfd.cGreenBits;
    496 		break;
    497 	    case SDL_GL_BLUE_SIZE:
    498 		*value = GL_pfd.cBlueBits;
    499 		break;
    500 	    case SDL_GL_ALPHA_SIZE:
    501 		*value = GL_pfd.cAlphaBits;
    502 		break;
    503 	    case SDL_GL_DOUBLEBUFFER:
    504 		if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) {
    505 			*value = 1;
    506 		} else {
    507 			*value = 0;
    508 		}
    509 		break;
    510 	    case SDL_GL_BUFFER_SIZE:
    511 		*value = GL_pfd.cColorBits;
    512 		break;
    513 	    case SDL_GL_DEPTH_SIZE:
    514 		*value = GL_pfd.cDepthBits;
    515 		break;
    516 	    case SDL_GL_STENCIL_SIZE:
    517 		*value = GL_pfd.cStencilBits;
    518 		break;
    519 	    case SDL_GL_ACCUM_RED_SIZE:
    520 		*value = GL_pfd.cAccumRedBits;
    521 		break;
    522 	    case SDL_GL_ACCUM_GREEN_SIZE:
    523 		*value = GL_pfd.cAccumGreenBits;
    524 		break;
    525 	    case SDL_GL_ACCUM_BLUE_SIZE:
    526 		*value = GL_pfd.cAccumBlueBits;
    527 		break;
    528 	    case SDL_GL_ACCUM_ALPHA_SIZE:
    529 		*value = GL_pfd.cAccumAlphaBits;
    530 		break;
    531 	    case SDL_GL_STEREO:
    532 		if ( GL_pfd.dwFlags & PFD_STEREO ) {
    533 			*value = 1;
    534 		} else {
    535 			*value = 0;
    536 		}
    537 		break;
    538 	    case SDL_GL_MULTISAMPLEBUFFERS:
    539 		*value = 0;
    540 		break;
    541 	    case SDL_GL_MULTISAMPLESAMPLES:
    542 		*value = 1;
    543 		break;
    544 	    case SDL_GL_SWAP_CONTROL:
    545 		if ( this->gl_data->wglGetSwapIntervalEXT ) {
    546 			*value = this->gl_data->wglGetSwapIntervalEXT();
    547 			return 0;
    548 		} else {
    549 			return -1;
    550 		}
    551 		break;
    552 	    default:
    553 		retval = -1;
    554 		break;
    555 	}
    556 	return retval;
    557 }
    558 
    559 void WIN_GL_SwapBuffers(_THIS)
    560 {
    561 	SwapBuffers(GL_hdc);
    562 }
    563 
    564 void WIN_GL_UnloadLibrary(_THIS)
    565 {
    566 	if ( this->gl_config.driver_loaded ) {
    567 		FreeLibrary((HMODULE)this->gl_config.dll_handle);
    568 
    569 		this->gl_data->wglGetProcAddress = NULL;
    570 		this->gl_data->wglCreateContext = NULL;
    571 		this->gl_data->wglDeleteContext = NULL;
    572 		this->gl_data->wglMakeCurrent = NULL;
    573 		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
    574 		this->gl_data->wglSwapIntervalEXT = NULL;
    575 		this->gl_data->wglGetSwapIntervalEXT = NULL;
    576 
    577 		this->gl_config.dll_handle = NULL;
    578 		this->gl_config.driver_loaded = 0;
    579 	}
    580 }
    581 
    582 /* Passing a NULL path means load pointers from the application */
    583 int WIN_GL_LoadLibrary(_THIS, const char* path)
    584 {
    585 	HMODULE handle;
    586 
    587  	if ( gl_active ) {
    588  		SDL_SetError("OpenGL context already created");
    589  		return -1;
    590  	}
    591 
    592 	if ( path == NULL ) {
    593 		path = DEFAULT_GL_DRIVER_PATH;
    594 	}
    595 	handle = LoadLibrary(path);
    596 	if ( handle == NULL ) {
    597 		SDL_SetError("Could not load OpenGL library");
    598 		return -1;
    599 	}
    600 
    601 	/* Unload the old driver and reset the pointers */
    602 	WIN_GL_UnloadLibrary(this);
    603 
    604 	/* Load new function pointers */
    605 	SDL_memset(this->gl_data, 0, sizeof(*this->gl_data));
    606 	this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *))
    607 		GetProcAddress(handle, "wglGetProcAddress");
    608 	this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC))
    609 		GetProcAddress(handle, "wglCreateContext");
    610 	this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC))
    611 		GetProcAddress(handle, "wglDeleteContext");
    612 	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
    613 		GetProcAddress(handle, "wglMakeCurrent");
    614 	this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int))
    615 		GetProcAddress(handle, "wglSwapIntervalEXT");
    616 	this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void))
    617 		GetProcAddress(handle, "wglGetSwapIntervalEXT");
    618 
    619 	if ( (this->gl_data->wglGetProcAddress == NULL) ||
    620 	     (this->gl_data->wglCreateContext == NULL) ||
    621 	     (this->gl_data->wglDeleteContext == NULL) ||
    622 	     (this->gl_data->wglMakeCurrent == NULL) ) {
    623 		SDL_SetError("Could not retrieve OpenGL functions");
    624 		FreeLibrary(handle);
    625 		return -1;
    626 	}
    627 
    628 	this->gl_config.dll_handle = handle;
    629 	SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path));
    630 	this->gl_config.driver_loaded = 1;
    631 	return 0;
    632 }
    633 
    634 void *WIN_GL_GetProcAddress(_THIS, const char* proc)
    635 {
    636 	void *func;
    637 
    638 	/* This is to pick up extensions */
    639 	func = this->gl_data->wglGetProcAddress(proc);
    640 	if ( ! func ) {
    641 		/* This is probably a normal GL function */
    642 		func = GetProcAddress(this->gl_config.dll_handle, proc);
    643 	}
    644 	return func;
    645 }
    646 
    647 #endif /* SDL_VIDEO_OPENGL */
    648