SDL-1.2.14
[sdl_omap.git] / src / video / wincommon / SDL_wingl.c
CommitLineData
e14743d1 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) */
37static 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
80static 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
114static 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
172int 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
376void 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 */
398int 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. */
411int 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
559void WIN_GL_SwapBuffers(_THIS)
560{
561 SwapBuffers(GL_hdc);
562}
563
564void 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 */
583int 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
634void *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 */