]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libsdl/contrib/src/video/wincommon/SDL_wingl.c
update
[l4.git] / l4 / pkg / libsdl / contrib / src / video / wincommon / SDL_wingl.c
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) */
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 */