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 (at) 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 */ 660