1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 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 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
WIN_GL_ShutDown(_THIS)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 */
WIN_GL_MakeCurrent(_THIS)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. */
WIN_GL_GetAttribute(_THIS,SDL_GLattr attrib,int * value)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
WIN_GL_SwapBuffers(_THIS)571 void WIN_GL_SwapBuffers(_THIS)
572 {
573 SwapBuffers(GL_hdc);
574 }
575
WIN_GL_UnloadLibrary(_THIS)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 */
WIN_GL_LoadLibrary(_THIS,const char * path)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
WIN_GL_GetProcAddress(_THIS,const char * proc)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 */
660