• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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) */
WIN_GL_ResetWindow(_THIS)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 
ExtensionSupported(const char * extension,const char * extensions)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 
ChoosePixelFormatARB(_THIS,const int * iAttribs,const FLOAT * fAttribs)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 
WIN_GL_SetupWindow(_THIS)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 
WIN_GL_ShutDown(_THIS)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 */
WIN_GL_MakeCurrent(_THIS)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. */
WIN_GL_GetAttribute(_THIS,SDL_GLattr attrib,int * value)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 
WIN_GL_SwapBuffers(_THIS)559 void WIN_GL_SwapBuffers(_THIS)
560 {
561 	SwapBuffers(GL_hdc);
562 }
563 
WIN_GL_UnloadLibrary(_THIS)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 */
WIN_GL_LoadLibrary(_THIS,const char * path)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 
WIN_GL_GetProcAddress(_THIS,const char * proc)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