SDL-1.2.14
[sdl_omap.git] / src / video / wincommon / SDL_wingl.c
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         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 */