Atlas - SDL_windowsopengl.c
Home / ext / SDL2 / src / video / windows Lines: 1 | Size: 29870 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_DRIVER_WINDOWS 24 25#include "SDL_assert.h" 26#include "SDL_loadso.h" 27#include "SDL_windowsvideo.h" 28#include "SDL_windowsopengles.h" 29#include "SDL_hints.h" 30 31/* WGL implementation of SDL OpenGL support */ 32 33#if SDL_VIDEO_OPENGL_WGL 34#include "SDL_opengl.h" 35 36#define DEFAULT_OPENGL "OPENGL32.DLL" 37 38#ifndef WGL_ARB_create_context 39#define WGL_ARB_create_context 40#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 41#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 42#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 43#define WGL_CONTEXT_FLAGS_ARB 0x2094 44#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 45#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 46 47#ifndef WGL_ARB_create_context_profile 48#define WGL_ARB_create_context_profile 49#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 50#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 51#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 52#endif 53 54#ifndef WGL_ARB_create_context_robustness 55#define WGL_ARB_create_context_robustness 56#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 57#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 58#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 59#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 60#endif 61#endif 62 63#ifndef WGL_EXT_create_context_es2_profile 64#define WGL_EXT_create_context_es2_profile 65#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 66#endif 67 68#ifndef WGL_EXT_create_context_es_profile 69#define WGL_EXT_create_context_es_profile 70#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 71#endif 72 73#ifndef WGL_ARB_framebuffer_sRGB 74#define WGL_ARB_framebuffer_sRGB 75#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 76#endif 77 78#ifndef WGL_ARB_context_flush_control 79#define WGL_ARB_context_flush_control 80#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 81#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000 82#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 83#endif 84 85#ifndef WGL_ARB_create_context_no_error 86#define WGL_ARB_create_context_no_error 87#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 88#endif 89 90typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, 91 HGLRC 92 hShareContext, 93 const int 94 *attribList); 95 96int 97WIN_GL_LoadLibrary(_THIS, const char *path) 98{ 99 void *handle; 100 101 if (path == NULL) { 102 path = SDL_getenv("SDL_OPENGL_LIBRARY"); 103 } 104 if (path == NULL) { 105 path = DEFAULT_OPENGL; 106 } 107 _this->gl_config.dll_handle = SDL_LoadObject(path); 108 if (!_this->gl_config.dll_handle) { 109 return -1; 110 } 111 SDL_strlcpy(_this->gl_config.driver_path, path, 112 SDL_arraysize(_this->gl_config.driver_path)); 113 114 /* Allocate OpenGL memory */ 115 _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData)); 116 if (!_this->gl_data) { 117 return SDL_OutOfMemory(); 118 } 119 120 /* Load function pointers */ 121 handle = _this->gl_config.dll_handle; 122 _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *)) 123 SDL_LoadFunction(handle, "wglGetProcAddress"); 124 _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC)) 125 SDL_LoadFunction(handle, "wglCreateContext"); 126 _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC)) 127 SDL_LoadFunction(handle, "wglDeleteContext"); 128 _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC)) 129 SDL_LoadFunction(handle, "wglMakeCurrent"); 130 _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC)) 131 SDL_LoadFunction(handle, "wglShareLists"); 132 133 if (!_this->gl_data->wglGetProcAddress || 134 !_this->gl_data->wglCreateContext || 135 !_this->gl_data->wglDeleteContext || 136 !_this->gl_data->wglMakeCurrent) { 137 return SDL_SetError("Could not retrieve OpenGL functions"); 138 } 139 140 /* XXX Too sleazy? WIN_GL_InitExtensions looks for certain OpenGL 141 extensions via SDL_GL_DeduceMaxSupportedESProfile. This uses 142 SDL_GL_ExtensionSupported which in turn calls SDL_GL_GetProcAddress. 143 However SDL_GL_GetProcAddress will fail if the library is not 144 loaded; it checks for gl_config.driver_loaded > 0. To avoid this 145 test failing, increment driver_loaded around the call to 146 WIN_GLInitExtensions. 147 148 Successful loading of the library is normally indicated by 149 SDL_GL_LoadLibrary incrementing driver_loaded immediately after 150 this function returns 0 to it. 151 152 Alternatives to this are: 153 - moving SDL_GL_DeduceMaxSupportedESProfile to both the WIN and 154 X11 platforms while adding a function equivalent to 155 SDL_GL_ExtensionSupported but which directly calls 156 glGetProcAddress(). Having 3 copies of the 157 SDL_GL_ExtensionSupported makes this alternative unattractive. 158 - moving SDL_GL_DeduceMaxSupportedESProfile to a new file shared 159 by the WIN and X11 platforms while adding a function equivalent 160 to SDL_GL_ExtensionSupported. This is unattractive due to the 161 number of project files that will need updating, plus there 162 will be 2 copies of the SDL_GL_ExtensionSupported code. 163 - Add a private equivalent of SDL_GL_ExtensionSupported to 164 SDL_video.c. 165 - Move the call to WIN_GL_InitExtensions back to WIN_CreateWindow 166 and add a flag to gl_data to avoid multiple calls to this 167 expensive function. This is probably the least objectionable 168 alternative if this increment/decrement trick is unacceptable. 169 170 Note that the driver_loaded > 0 check needs to remain in 171 SDL_GL_ExtensionSupported and SDL_GL_GetProcAddress as they are 172 public API functions. 173 */ 174 ++_this->gl_config.driver_loaded; 175 WIN_GL_InitExtensions(_this); 176 --_this->gl_config.driver_loaded; 177 178 return 0; 179} 180 181void * 182WIN_GL_GetProcAddress(_THIS, const char *proc) 183{ 184 void *func; 185 186 /* This is to pick up extensions */ 187 func = _this->gl_data->wglGetProcAddress(proc); 188 if (!func) { 189 /* This is probably a normal GL function */ 190 func = GetProcAddress(_this->gl_config.dll_handle, proc); 191 } 192 return func; 193} 194 195void 196WIN_GL_UnloadLibrary(_THIS) 197{ 198 SDL_UnloadObject(_this->gl_config.dll_handle); 199 _this->gl_config.dll_handle = NULL; 200 201 /* Free OpenGL memory */ 202 SDL_free(_this->gl_data); 203 _this->gl_data = NULL; 204} 205 206static void 207WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd) 208{ 209 SDL_zerop(pfd); 210 pfd->nSize = sizeof(*pfd); 211 pfd->nVersion = 1; 212 pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL); 213 if (_this->gl_config.double_buffer) { 214 pfd->dwFlags |= PFD_DOUBLEBUFFER; 215 } 216 if (_this->gl_config.stereo) { 217 pfd->dwFlags |= PFD_STEREO; 218 } 219 pfd->iLayerType = PFD_MAIN_PLANE; 220 pfd->iPixelType = PFD_TYPE_RGBA; 221 pfd->cRedBits = _this->gl_config.red_size; 222 pfd->cGreenBits = _this->gl_config.green_size; 223 pfd->cBlueBits = _this->gl_config.blue_size; 224 pfd->cAlphaBits = _this->gl_config.alpha_size; 225 if (_this->gl_config.buffer_size) { 226 pfd->cColorBits = 227 _this->gl_config.buffer_size - _this->gl_config.alpha_size; 228 } else { 229 pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits); 230 } 231 pfd->cAccumRedBits = _this->gl_config.accum_red_size; 232 pfd->cAccumGreenBits = _this->gl_config.accum_green_size; 233 pfd->cAccumBlueBits = _this->gl_config.accum_blue_size; 234 pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size; 235 pfd->cAccumBits = 236 (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits + 237 pfd->cAccumAlphaBits); 238 pfd->cDepthBits = _this->gl_config.depth_size; 239 pfd->cStencilBits = _this->gl_config.stencil_size; 240} 241 242/* Choose the closest pixel format that meets or exceeds the target. 243 FIXME: Should we weight any particular attribute over any other? 244*/ 245static int 246WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target) 247{ 248 PIXELFORMATDESCRIPTOR pfd; 249 int count, index, best = 0; 250 unsigned int dist, best_dist = ~0U; 251 252 count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL); 253 254 for (index = 1; index <= count; index++) { 255 256 if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) { 257 continue; 258 } 259 260 if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) { 261 continue; 262 } 263 264 if (pfd.iLayerType != target->iLayerType) { 265 continue; 266 } 267 if (pfd.iPixelType != target->iPixelType) { 268 continue; 269 } 270 271 dist = 0; 272 273 if (pfd.cColorBits < target->cColorBits) { 274 continue; 275 } else { 276 dist += (pfd.cColorBits - target->cColorBits); 277 } 278 if (pfd.cRedBits < target->cRedBits) { 279 continue; 280 } else { 281 dist += (pfd.cRedBits - target->cRedBits); 282 } 283 if (pfd.cGreenBits < target->cGreenBits) { 284 continue; 285 } else { 286 dist += (pfd.cGreenBits - target->cGreenBits); 287 } 288 if (pfd.cBlueBits < target->cBlueBits) { 289 continue; 290 } else { 291 dist += (pfd.cBlueBits - target->cBlueBits); 292 } 293 if (pfd.cAlphaBits < target->cAlphaBits) { 294 continue; 295 } else { 296 dist += (pfd.cAlphaBits - target->cAlphaBits); 297 } 298 if (pfd.cAccumBits < target->cAccumBits) { 299 continue; 300 } else { 301 dist += (pfd.cAccumBits - target->cAccumBits); 302 } 303 if (pfd.cAccumRedBits < target->cAccumRedBits) { 304 continue; 305 } else { 306 dist += (pfd.cAccumRedBits - target->cAccumRedBits); 307 } 308 if (pfd.cAccumGreenBits < target->cAccumGreenBits) { 309 continue; 310 } else { 311 dist += (pfd.cAccumGreenBits - target->cAccumGreenBits); 312 } 313 if (pfd.cAccumBlueBits < target->cAccumBlueBits) { 314 continue; 315 } else { 316 dist += (pfd.cAccumBlueBits - target->cAccumBlueBits); 317 } 318 if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) { 319 continue; 320 } else { 321 dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits); 322 } 323 if (pfd.cDepthBits < target->cDepthBits) { 324 continue; 325 } else { 326 dist += (pfd.cDepthBits - target->cDepthBits); 327 } 328 if (pfd.cStencilBits < target->cStencilBits) { 329 continue; 330 } else { 331 dist += (pfd.cStencilBits - target->cStencilBits); 332 } 333 334 if (dist < best_dist) { 335 best = index; 336 best_dist = dist; 337 } 338 } 339 340 return best; 341} 342 343static SDL_bool 344HasExtension(const char *extension, const char *extensions) 345{ 346 const char *start; 347 const char *where, *terminator; 348 349 /* Extension names should not have spaces. */ 350 where = SDL_strchr(extension, ' '); 351 if (where || *extension == '\0') 352 return SDL_FALSE; 353 354 if (!extensions) 355 return SDL_FALSE; 356 357 /* It takes a bit of care to be fool-proof about parsing the 358 * OpenGL extensions string. Don't be fooled by sub-strings, 359 * etc. */ 360 361 start = extensions; 362 363 for (;;) { 364 where = SDL_strstr(start, extension); 365 if (!where) 366 break; 367 368 terminator = where + SDL_strlen(extension); 369 if (where == start || *(where - 1) == ' ') 370 if (*terminator == ' ' || *terminator == '\0') 371 return SDL_TRUE; 372 373 start = terminator; 374 } 375 return SDL_FALSE; 376} 377 378void 379WIN_GL_InitExtensions(_THIS) 380{ 381 const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0; 382 const char *extensions; 383 HWND hwnd; 384 HDC hdc; 385 HGLRC hglrc; 386 PIXELFORMATDESCRIPTOR pfd; 387 388 if (!_this->gl_data) { 389 return; 390 } 391 392 hwnd = 393 CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0, 394 10, 10, NULL, NULL, SDL_Instance, NULL); 395 if (!hwnd) { 396 return; 397 } 398 WIN_PumpEvents(_this); 399 400 hdc = GetDC(hwnd); 401 402 WIN_GL_SetupPixelFormat(_this, &pfd); 403 404 SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); 405 406 hglrc = _this->gl_data->wglCreateContext(hdc); 407 if (!hglrc) { 408 return; 409 } 410 _this->gl_data->wglMakeCurrent(hdc, hglrc); 411 412 wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC)) 413 _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB"); 414 if (wglGetExtensionsStringARB) { 415 extensions = wglGetExtensionsStringARB(hdc); 416 } else { 417 extensions = NULL; 418 } 419 420 /* Check for WGL_ARB_pixel_format */ 421 _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE; 422 if (HasExtension("WGL_ARB_pixel_format", extensions)) { 423 _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *) 424 (HDC, const int *, 425 const FLOAT *, UINT, 426 int *, UINT *)) 427 WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB"); 428 _this->gl_data->wglGetPixelFormatAttribivARB = 429 (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *)) 430 WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB"); 431 432 if ((_this->gl_data->wglChoosePixelFormatARB != NULL) && 433 (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) { 434 _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE; 435 } 436 } 437 438 /* Check for WGL_EXT_swap_control */ 439 _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE; 440 if (HasExtension("WGL_EXT_swap_control", extensions)) { 441 _this->gl_data->wglSwapIntervalEXT = 442 WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT"); 443 _this->gl_data->wglGetSwapIntervalEXT = 444 WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT"); 445 if (HasExtension("WGL_EXT_swap_control_tear", extensions)) { 446 _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE; 447 } 448 } else { 449 _this->gl_data->wglSwapIntervalEXT = NULL; 450 _this->gl_data->wglGetSwapIntervalEXT = NULL; 451 } 452 453 /* Check for WGL_EXT_create_context_es2_profile */ 454 if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) { 455 SDL_GL_DeduceMaxSupportedESProfile( 456 &_this->gl_data->es_profile_max_supported_version.major, 457 &_this->gl_data->es_profile_max_supported_version.minor 458 ); 459 } 460 461 /* Check for WGL_ARB_context_flush_control */ 462 if (HasExtension("WGL_ARB_context_flush_control", extensions)) { 463 _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE; 464 } 465 466 /* Check for WGL_ARB_create_context_robustness */ 467 if (HasExtension("WGL_ARB_create_context_robustness", extensions)) { 468 _this->gl_data->HAS_WGL_ARB_create_context_robustness = SDL_TRUE; 469 } 470 471 /* Check for WGL_ARB_create_context_no_error */ 472 if (HasExtension("WGL_ARB_create_context_no_error", extensions)) { 473 _this->gl_data->HAS_WGL_ARB_create_context_no_error = SDL_TRUE; 474 } 475 476 _this->gl_data->wglMakeCurrent(hdc, NULL); 477 _this->gl_data->wglDeleteContext(hglrc); 478 ReleaseDC(hwnd, hdc); 479 DestroyWindow(hwnd); 480 WIN_PumpEvents(_this); 481} 482 483static int 484WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs) 485{ 486 HWND hwnd; 487 HDC hdc; 488 PIXELFORMATDESCRIPTOR pfd; 489 HGLRC hglrc; 490 int pixel_format = 0; 491 unsigned int matching; 492 493 hwnd = 494 CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0, 495 10, 10, NULL, NULL, SDL_Instance, NULL); 496 WIN_PumpEvents(_this); 497 498 hdc = GetDC(hwnd); 499 500 WIN_GL_SetupPixelFormat(_this, &pfd); 501 502 SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); 503 504 hglrc = _this->gl_data->wglCreateContext(hdc); 505 if (hglrc) { 506 _this->gl_data->wglMakeCurrent(hdc, hglrc); 507 508 if (_this->gl_data->HAS_WGL_ARB_pixel_format) { 509 _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs, 510 1, &pixel_format, 511 &matching); 512 } 513 514 _this->gl_data->wglMakeCurrent(hdc, NULL); 515 _this->gl_data->wglDeleteContext(hglrc); 516 } 517 ReleaseDC(hwnd, hdc); 518 DestroyWindow(hwnd); 519 WIN_PumpEvents(_this); 520 521 return pixel_format; 522} 523 524/* actual work of WIN_GL_SetupWindow() happens here. */ 525static int 526WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window) 527{ 528 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 529 PIXELFORMATDESCRIPTOR pfd; 530 int pixel_format = 0; 531 int iAttribs[64]; 532 int *iAttr; 533 int *iAccelAttr; 534 float fAttribs[1] = { 0 }; 535 536 WIN_GL_SetupPixelFormat(_this, &pfd); 537 538 /* setup WGL_ARB_pixel_format attribs */ 539 iAttr = &iAttribs[0]; 540 541 *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; 542 *iAttr++ = GL_TRUE; 543 *iAttr++ = WGL_RED_BITS_ARB; 544 *iAttr++ = _this->gl_config.red_size; 545 *iAttr++ = WGL_GREEN_BITS_ARB; 546 *iAttr++ = _this->gl_config.green_size; 547 *iAttr++ = WGL_BLUE_BITS_ARB; 548 *iAttr++ = _this->gl_config.blue_size; 549 550 if (_this->gl_config.alpha_size) { 551 *iAttr++ = WGL_ALPHA_BITS_ARB; 552 *iAttr++ = _this->gl_config.alpha_size; 553 } 554 555 *iAttr++ = WGL_DOUBLE_BUFFER_ARB; 556 *iAttr++ = _this->gl_config.double_buffer; 557 558 *iAttr++ = WGL_DEPTH_BITS_ARB; 559 *iAttr++ = _this->gl_config.depth_size; 560 561 if (_this->gl_config.stencil_size) { 562 *iAttr++ = WGL_STENCIL_BITS_ARB; 563 *iAttr++ = _this->gl_config.stencil_size; 564 } 565 566 if (_this->gl_config.accum_red_size) { 567 *iAttr++ = WGL_ACCUM_RED_BITS_ARB; 568 *iAttr++ = _this->gl_config.accum_red_size; 569 } 570 571 if (_this->gl_config.accum_green_size) { 572 *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; 573 *iAttr++ = _this->gl_config.accum_green_size; 574 } 575 576 if (_this->gl_config.accum_blue_size) { 577 *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; 578 *iAttr++ = _this->gl_config.accum_blue_size; 579 } 580 581 if (_this->gl_config.accum_alpha_size) { 582 *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; 583 *iAttr++ = _this->gl_config.accum_alpha_size; 584 } 585 586 if (_this->gl_config.stereo) { 587 *iAttr++ = WGL_STEREO_ARB; 588 *iAttr++ = GL_TRUE; 589 } 590 591 if (_this->gl_config.multisamplebuffers) { 592 *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; 593 *iAttr++ = _this->gl_config.multisamplebuffers; 594 } 595 596 if (_this->gl_config.multisamplesamples) { 597 *iAttr++ = WGL_SAMPLES_ARB; 598 *iAttr++ = _this->gl_config.multisamplesamples; 599 } 600 601 if (_this->gl_config.framebuffer_srgb_capable) { 602 *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; 603 *iAttr++ = _this->gl_config.framebuffer_srgb_capable; 604 } 605 606 /* We always choose either FULL or NO accel on Windows, because of flaky 607 drivers. If the app didn't specify, we use FULL, because that's 608 probably what they wanted (and if you didn't care and got FULL, that's 609 a perfectly valid result in any case). */ 610 *iAttr++ = WGL_ACCELERATION_ARB; 611 iAccelAttr = iAttr; 612 if (_this->gl_config.accelerated) { 613 *iAttr++ = WGL_FULL_ACCELERATION_ARB; 614 } else { 615 *iAttr++ = WGL_NO_ACCELERATION_ARB; 616 } 617 618 *iAttr = 0; 619 620 /* Choose and set the closest available pixel format */ 621 pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); 622 623 /* App said "don't care about accel" and FULL accel failed. Try NO. */ 624 if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) { 625 *iAccelAttr = WGL_NO_ACCELERATION_ARB; 626 pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); 627 *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */ 628 } 629 if (!pixel_format) { 630 pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd); 631 } 632 if (!pixel_format) { 633 return SDL_SetError("No matching GL pixel format available"); 634 } 635 if (!SetPixelFormat(hdc, pixel_format, &pfd)) { 636 return WIN_SetError("SetPixelFormat()"); 637 } 638 return 0; 639} 640 641int 642WIN_GL_SetupWindow(_THIS, SDL_Window * window) 643{ 644 /* The current context is lost in here; save it and reset it. */ 645 SDL_Window *current_win = SDL_GL_GetCurrentWindow(); 646 SDL_GLContext current_ctx = SDL_GL_GetCurrentContext(); 647 const int retval = WIN_GL_SetupWindowInternal(_this, window); 648 WIN_GL_MakeCurrent(_this, current_win, current_ctx); 649 return retval; 650} 651 652SDL_bool 653WIN_GL_UseEGL(_THIS) 654{ 655 SDL_assert(_this->gl_data != NULL); 656 SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES); 657 658 return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE) 659 || _this->gl_config.major_version == 1 /* No WGL extension for OpenGL ES 1.x profiles. */ 660 || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major 661 || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major 662 && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor)); 663} 664 665SDL_GLContext 666WIN_GL_CreateContext(_THIS, SDL_Window * window) 667{ 668 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 669 HGLRC context, share_context; 670 671 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && WIN_GL_UseEGL(_this)) { 672#if SDL_VIDEO_OPENGL_EGL 673 /* Switch to EGL based functions */ 674 WIN_GL_UnloadLibrary(_this); 675 _this->GL_LoadLibrary = WIN_GLES_LoadLibrary; 676 _this->GL_GetProcAddress = WIN_GLES_GetProcAddress; 677 _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; 678 _this->GL_CreateContext = WIN_GLES_CreateContext; 679 _this->GL_MakeCurrent = WIN_GLES_MakeCurrent; 680 _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; 681 _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; 682 _this->GL_SwapWindow = WIN_GLES_SwapWindow; 683 _this->GL_DeleteContext = WIN_GLES_DeleteContext; 684 685 if (WIN_GLES_LoadLibrary(_this, NULL) != 0) { 686 return NULL; 687 } 688 689 return WIN_GLES_CreateContext(_this, window); 690#else 691 SDL_SetError("SDL not configured with EGL support"); 692 return NULL; 693#endif 694 } 695 696 if (_this->gl_config.share_with_current_context) { 697 share_context = (HGLRC)SDL_GL_GetCurrentContext(); 698 } else { 699 share_context = 0; 700 } 701 702 if (_this->gl_config.major_version < 3 && 703 _this->gl_config.profile_mask == 0 && 704 _this->gl_config.flags == 0) { 705 /* Create legacy context */ 706 context = _this->gl_data->wglCreateContext(hdc); 707 if( share_context != 0 ) { 708 _this->gl_data->wglShareLists(share_context, context); 709 } 710 } else { 711 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; 712 HGLRC temp_context = _this->gl_data->wglCreateContext(hdc); 713 if (!temp_context) { 714 SDL_SetError("Could not create GL context"); 715 return NULL; 716 } 717 718 /* Make the context current */ 719 if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) { 720 WIN_GL_DeleteContext(_this, temp_context); 721 return NULL; 722 } 723 724 wglCreateContextAttribsARB = 725 (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> 726 wglGetProcAddress("wglCreateContextAttribsARB"); 727 if (!wglCreateContextAttribsARB) { 728 SDL_SetError("GL 3.x is not supported"); 729 context = temp_context; 730 } else { 731 int attribs[15]; /* max 14 attributes plus terminator */ 732 int iattr = 0; 733 734 attribs[iattr++] = WGL_CONTEXT_MAJOR_VERSION_ARB; 735 attribs[iattr++] = _this->gl_config.major_version; 736 attribs[iattr++] = WGL_CONTEXT_MINOR_VERSION_ARB; 737 attribs[iattr++] = _this->gl_config.minor_version; 738 739 /* SDL profile bits match WGL profile bits */ 740 if (_this->gl_config.profile_mask != 0) { 741 attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB; 742 attribs[iattr++] = _this->gl_config.profile_mask; 743 } 744 745 /* SDL flags match WGL flags */ 746 if (_this->gl_config.flags != 0) { 747 attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB; 748 attribs[iattr++] = _this->gl_config.flags; 749 } 750 751 /* only set if wgl extension is available */ 752 if (_this->gl_data->HAS_WGL_ARB_context_flush_control) { 753 attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB; 754 attribs[iattr++] = _this->gl_config.release_behavior ? 755 WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : 756 WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; 757 } 758 759 /* only set if wgl extension is available */ 760 if (_this->gl_data->HAS_WGL_ARB_create_context_robustness) { 761 attribs[iattr++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB; 762 attribs[iattr++] = _this->gl_config.reset_notification ? 763 WGL_LOSE_CONTEXT_ON_RESET_ARB : 764 WGL_NO_RESET_NOTIFICATION_ARB; 765 } 766 767 /* only set if wgl extension is available */ 768 if (_this->gl_data->HAS_WGL_ARB_create_context_no_error) { 769 attribs[iattr++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; 770 attribs[iattr++] = _this->gl_config.no_error; 771 } 772 773 attribs[iattr++] = 0; 774 775 /* Create the GL 3.x context */ 776 context = wglCreateContextAttribsARB(hdc, share_context, attribs); 777 /* Delete the GL 2.x context */ 778 _this->gl_data->wglDeleteContext(temp_context); 779 } 780 } 781 782 if (!context) { 783 WIN_SetError("Could not create GL context"); 784 return NULL; 785 } 786 787 if (WIN_GL_MakeCurrent(_this, window, context) < 0) { 788 WIN_GL_DeleteContext(_this, context); 789 return NULL; 790 } 791 792 return context; 793} 794 795int 796WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) 797{ 798 HDC hdc; 799 800 if (!_this->gl_data) { 801 return SDL_SetError("OpenGL not initialized"); 802 } 803 804 /* sanity check that higher level handled this. */ 805 SDL_assert(window || (!window && !context)); 806 807 /* Some Windows drivers freak out if hdc is NULL, even when context is 808 NULL, against spec. Since hdc is _supposed_ to be ignored if context 809 is NULL, we either use the current GL window, or do nothing if we 810 already have no current context. */ 811 if (!window) { 812 window = SDL_GL_GetCurrentWindow(); 813 if (!window) { 814 SDL_assert(SDL_GL_GetCurrentContext() == NULL); 815 return 0; /* already done. */ 816 } 817 } 818 819 hdc = ((SDL_WindowData *) window->driverdata)->hdc; 820 if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) { 821 return WIN_SetError("wglMakeCurrent()"); 822 } 823 return 0; 824} 825 826int 827WIN_GL_SetSwapInterval(_THIS, int interval) 828{ 829 if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) { 830 return SDL_SetError("Negative swap interval unsupported in this GL"); 831 } else if (_this->gl_data->wglSwapIntervalEXT) { 832 if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) { 833 return WIN_SetError("wglSwapIntervalEXT()"); 834 } 835 } else { 836 return SDL_Unsupported(); 837 } 838 return 0; 839} 840 841int 842WIN_GL_GetSwapInterval(_THIS) 843{ 844 int retval = 0; 845 if (_this->gl_data->wglGetSwapIntervalEXT) { 846 retval = _this->gl_data->wglGetSwapIntervalEXT(); 847 } 848 return retval; 849} 850 851int 852WIN_GL_SwapWindow(_THIS, SDL_Window * window) 853{ 854 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 855 856 if (!SwapBuffers(hdc)) { 857 return WIN_SetError("SwapBuffers()"); 858 } 859 return 0; 860} 861 862void 863WIN_GL_DeleteContext(_THIS, SDL_GLContext context) 864{ 865 if (!_this->gl_data) { 866 return; 867 } 868 _this->gl_data->wglDeleteContext((HGLRC) context); 869} 870 871 872SDL_bool 873WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow) 874{ 875 HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc; 876 HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc; 877 BOOL result; 878 879 /* get the pixel format of the fromWindow */ 880 int pixel_format = GetPixelFormat(hfromdc); 881 PIXELFORMATDESCRIPTOR pfd; 882 SDL_memset(&pfd, 0, sizeof(pfd)); 883 DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd); 884 885 /* set the pixel format of the toWindow */ 886 result = SetPixelFormat(htodc, pixel_format, &pfd); 887 888 return result ? SDL_TRUE : SDL_FALSE; 889} 890 891#endif /* SDL_VIDEO_OPENGL_WGL */ 892 893#endif /* SDL_VIDEO_DRIVER_WINDOWS */ 894 895/* vi: set ts=4 sw=4 expandtab: */ 896[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.