SDL_windowsopengl.c (24893B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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 30/* WGL implementation of SDL OpenGL support */ 31 32#if SDL_VIDEO_OPENGL_WGL 33#include "SDL_opengl.h" 34 35#define DEFAULT_OPENGL "OPENGL32.DLL" 36 37#ifndef WGL_ARB_create_context 38#define WGL_ARB_create_context 39#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 40#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 41#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 42#define WGL_CONTEXT_FLAGS_ARB 0x2094 43#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 44#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 45 46#ifndef WGL_ARB_create_context_profile 47#define WGL_ARB_create_context_profile 48#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 49#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 50#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 51#endif 52 53#ifndef WGL_ARB_create_context_robustness 54#define WGL_ARB_create_context_robustness 55#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 56#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 57#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 58#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 59#endif 60#endif 61 62#ifndef WGL_EXT_create_context_es2_profile 63#define WGL_EXT_create_context_es2_profile 64#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 65#endif 66 67#ifndef WGL_EXT_create_context_es_profile 68#define WGL_EXT_create_context_es_profile 69#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 70#endif 71 72#ifndef WGL_ARB_framebuffer_sRGB 73#define WGL_ARB_framebuffer_sRGB 74#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 75#endif 76 77typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, 78 HGLRC 79 hShareContext, 80 const int 81 *attribList); 82 83int 84WIN_GL_LoadLibrary(_THIS, const char *path) 85{ 86 void *handle; 87 88 if (path == NULL) { 89 path = SDL_getenv("SDL_OPENGL_LIBRARY"); 90 } 91 if (path == NULL) { 92 path = DEFAULT_OPENGL; 93 } 94 _this->gl_config.dll_handle = SDL_LoadObject(path); 95 if (!_this->gl_config.dll_handle) { 96 return -1; 97 } 98 SDL_strlcpy(_this->gl_config.driver_path, path, 99 SDL_arraysize(_this->gl_config.driver_path)); 100 101 /* Allocate OpenGL memory */ 102 _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData)); 103 if (!_this->gl_data) { 104 return SDL_OutOfMemory(); 105 } 106 107 /* Load function pointers */ 108 handle = _this->gl_config.dll_handle; 109 _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *)) 110 SDL_LoadFunction(handle, "wglGetProcAddress"); 111 _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC)) 112 SDL_LoadFunction(handle, "wglCreateContext"); 113 _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC)) 114 SDL_LoadFunction(handle, "wglDeleteContext"); 115 _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC)) 116 SDL_LoadFunction(handle, "wglMakeCurrent"); 117 _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC)) 118 SDL_LoadFunction(handle, "wglShareLists"); 119 120 if (!_this->gl_data->wglGetProcAddress || 121 !_this->gl_data->wglCreateContext || 122 !_this->gl_data->wglDeleteContext || 123 !_this->gl_data->wglMakeCurrent) { 124 return SDL_SetError("Could not retrieve OpenGL functions"); 125 } 126 127 return 0; 128} 129 130void * 131WIN_GL_GetProcAddress(_THIS, const char *proc) 132{ 133 void *func; 134 135 /* This is to pick up extensions */ 136 func = _this->gl_data->wglGetProcAddress(proc); 137 if (!func) { 138 /* This is probably a normal GL function */ 139 func = GetProcAddress(_this->gl_config.dll_handle, proc); 140 } 141 return func; 142} 143 144void 145WIN_GL_UnloadLibrary(_THIS) 146{ 147 SDL_UnloadObject(_this->gl_config.dll_handle); 148 _this->gl_config.dll_handle = NULL; 149 150 /* Free OpenGL memory */ 151 SDL_free(_this->gl_data); 152 _this->gl_data = NULL; 153} 154 155static void 156WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd) 157{ 158 SDL_zerop(pfd); 159 pfd->nSize = sizeof(*pfd); 160 pfd->nVersion = 1; 161 pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL); 162 if (_this->gl_config.double_buffer) { 163 pfd->dwFlags |= PFD_DOUBLEBUFFER; 164 } 165 if (_this->gl_config.stereo) { 166 pfd->dwFlags |= PFD_STEREO; 167 } 168 pfd->iLayerType = PFD_MAIN_PLANE; 169 pfd->iPixelType = PFD_TYPE_RGBA; 170 pfd->cRedBits = _this->gl_config.red_size; 171 pfd->cGreenBits = _this->gl_config.green_size; 172 pfd->cBlueBits = _this->gl_config.blue_size; 173 pfd->cAlphaBits = _this->gl_config.alpha_size; 174 if (_this->gl_config.buffer_size) { 175 pfd->cColorBits = 176 _this->gl_config.buffer_size - _this->gl_config.alpha_size; 177 } else { 178 pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits); 179 } 180 pfd->cAccumRedBits = _this->gl_config.accum_red_size; 181 pfd->cAccumGreenBits = _this->gl_config.accum_green_size; 182 pfd->cAccumBlueBits = _this->gl_config.accum_blue_size; 183 pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size; 184 pfd->cAccumBits = 185 (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits + 186 pfd->cAccumAlphaBits); 187 pfd->cDepthBits = _this->gl_config.depth_size; 188 pfd->cStencilBits = _this->gl_config.stencil_size; 189} 190 191/* Choose the closest pixel format that meets or exceeds the target. 192 FIXME: Should we weight any particular attribute over any other? 193*/ 194static int 195WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target) 196{ 197 PIXELFORMATDESCRIPTOR pfd; 198 int count, index, best = 0; 199 unsigned int dist, best_dist = ~0U; 200 201 count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL); 202 203 for (index = 1; index <= count; index++) { 204 205 if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) { 206 continue; 207 } 208 209 if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) { 210 continue; 211 } 212 213 if (pfd.iLayerType != target->iLayerType) { 214 continue; 215 } 216 if (pfd.iPixelType != target->iPixelType) { 217 continue; 218 } 219 220 dist = 0; 221 222 if (pfd.cColorBits < target->cColorBits) { 223 continue; 224 } else { 225 dist += (pfd.cColorBits - target->cColorBits); 226 } 227 if (pfd.cRedBits < target->cRedBits) { 228 continue; 229 } else { 230 dist += (pfd.cRedBits - target->cRedBits); 231 } 232 if (pfd.cGreenBits < target->cGreenBits) { 233 continue; 234 } else { 235 dist += (pfd.cGreenBits - target->cGreenBits); 236 } 237 if (pfd.cBlueBits < target->cBlueBits) { 238 continue; 239 } else { 240 dist += (pfd.cBlueBits - target->cBlueBits); 241 } 242 if (pfd.cAlphaBits < target->cAlphaBits) { 243 continue; 244 } else { 245 dist += (pfd.cAlphaBits - target->cAlphaBits); 246 } 247 if (pfd.cAccumBits < target->cAccumBits) { 248 continue; 249 } else { 250 dist += (pfd.cAccumBits - target->cAccumBits); 251 } 252 if (pfd.cAccumRedBits < target->cAccumRedBits) { 253 continue; 254 } else { 255 dist += (pfd.cAccumRedBits - target->cAccumRedBits); 256 } 257 if (pfd.cAccumGreenBits < target->cAccumGreenBits) { 258 continue; 259 } else { 260 dist += (pfd.cAccumGreenBits - target->cAccumGreenBits); 261 } 262 if (pfd.cAccumBlueBits < target->cAccumBlueBits) { 263 continue; 264 } else { 265 dist += (pfd.cAccumBlueBits - target->cAccumBlueBits); 266 } 267 if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) { 268 continue; 269 } else { 270 dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits); 271 } 272 if (pfd.cDepthBits < target->cDepthBits) { 273 continue; 274 } else { 275 dist += (pfd.cDepthBits - target->cDepthBits); 276 } 277 if (pfd.cStencilBits < target->cStencilBits) { 278 continue; 279 } else { 280 dist += (pfd.cStencilBits - target->cStencilBits); 281 } 282 283 if (dist < best_dist) { 284 best = index; 285 best_dist = dist; 286 } 287 } 288 289 return best; 290} 291 292static SDL_bool 293HasExtension(const char *extension, const char *extensions) 294{ 295 const char *start; 296 const char *where, *terminator; 297 298 /* Extension names should not have spaces. */ 299 where = SDL_strchr(extension, ' '); 300 if (where || *extension == '\0') 301 return SDL_FALSE; 302 303 if (!extensions) 304 return SDL_FALSE; 305 306 /* It takes a bit of care to be fool-proof about parsing the 307 * OpenGL extensions string. Don't be fooled by sub-strings, 308 * etc. */ 309 310 start = extensions; 311 312 for (;;) { 313 where = SDL_strstr(start, extension); 314 if (!where) 315 break; 316 317 terminator = where + SDL_strlen(extension); 318 if (where == start || *(where - 1) == ' ') 319 if (*terminator == ' ' || *terminator == '\0') 320 return SDL_TRUE; 321 322 start = terminator; 323 } 324 return SDL_FALSE; 325} 326 327void 328WIN_GL_InitExtensions(_THIS) 329{ 330 const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0; 331 const char *extensions; 332 HWND hwnd; 333 HDC hdc; 334 HGLRC hglrc; 335 PIXELFORMATDESCRIPTOR pfd; 336 337 if (!_this->gl_data) { 338 return; 339 } 340 341 hwnd = 342 CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0, 343 10, 10, NULL, NULL, SDL_Instance, NULL); 344 if (!hwnd) { 345 return; 346 } 347 WIN_PumpEvents(_this); 348 349 hdc = GetDC(hwnd); 350 351 WIN_GL_SetupPixelFormat(_this, &pfd); 352 353 SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); 354 355 hglrc = _this->gl_data->wglCreateContext(hdc); 356 if (!hglrc) { 357 return; 358 } 359 _this->gl_data->wglMakeCurrent(hdc, hglrc); 360 361 wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC)) 362 _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB"); 363 if (wglGetExtensionsStringARB) { 364 extensions = wglGetExtensionsStringARB(hdc); 365 } else { 366 extensions = NULL; 367 } 368 369 /* Check for WGL_ARB_pixel_format */ 370 _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE; 371 if (HasExtension("WGL_ARB_pixel_format", extensions)) { 372 _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *) 373 (HDC, const int *, 374 const FLOAT *, UINT, 375 int *, UINT *)) 376 WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB"); 377 _this->gl_data->wglGetPixelFormatAttribivARB = 378 (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *)) 379 WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB"); 380 381 if ((_this->gl_data->wglChoosePixelFormatARB != NULL) && 382 (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) { 383 _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE; 384 } 385 } 386 387 /* Check for WGL_EXT_swap_control */ 388 _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE; 389 if (HasExtension("WGL_EXT_swap_control", extensions)) { 390 _this->gl_data->wglSwapIntervalEXT = 391 WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT"); 392 _this->gl_data->wglGetSwapIntervalEXT = 393 WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT"); 394 if (HasExtension("WGL_EXT_swap_control_tear", extensions)) { 395 _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE; 396 } 397 } else { 398 _this->gl_data->wglSwapIntervalEXT = NULL; 399 _this->gl_data->wglGetSwapIntervalEXT = NULL; 400 } 401 402 /* Check for WGL_EXT_create_context_es2_profile */ 403 _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_FALSE; 404 if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) { 405 _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE; 406 } 407 408 _this->gl_data->wglMakeCurrent(hdc, NULL); 409 _this->gl_data->wglDeleteContext(hglrc); 410 ReleaseDC(hwnd, hdc); 411 DestroyWindow(hwnd); 412 WIN_PumpEvents(_this); 413} 414 415static int 416WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs) 417{ 418 HWND hwnd; 419 HDC hdc; 420 PIXELFORMATDESCRIPTOR pfd; 421 HGLRC hglrc; 422 int pixel_format = 0; 423 unsigned int matching; 424 425 hwnd = 426 CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0, 427 10, 10, NULL, NULL, SDL_Instance, NULL); 428 WIN_PumpEvents(_this); 429 430 hdc = GetDC(hwnd); 431 432 WIN_GL_SetupPixelFormat(_this, &pfd); 433 434 SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); 435 436 hglrc = _this->gl_data->wglCreateContext(hdc); 437 if (hglrc) { 438 _this->gl_data->wglMakeCurrent(hdc, hglrc); 439 440 if (_this->gl_data->HAS_WGL_ARB_pixel_format) { 441 _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs, 442 1, &pixel_format, 443 &matching); 444 } 445 446 _this->gl_data->wglMakeCurrent(hdc, NULL); 447 _this->gl_data->wglDeleteContext(hglrc); 448 } 449 ReleaseDC(hwnd, hdc); 450 DestroyWindow(hwnd); 451 WIN_PumpEvents(_this); 452 453 return pixel_format; 454} 455 456/* actual work of WIN_GL_SetupWindow() happens here. */ 457static int 458WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window) 459{ 460 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 461 PIXELFORMATDESCRIPTOR pfd; 462 int pixel_format = 0; 463 int iAttribs[64]; 464 int *iAttr; 465 int *iAccelAttr; 466 float fAttribs[1] = { 0 }; 467 468 WIN_GL_SetupPixelFormat(_this, &pfd); 469 470 /* setup WGL_ARB_pixel_format attribs */ 471 iAttr = &iAttribs[0]; 472 473 *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; 474 *iAttr++ = GL_TRUE; 475 *iAttr++ = WGL_RED_BITS_ARB; 476 *iAttr++ = _this->gl_config.red_size; 477 *iAttr++ = WGL_GREEN_BITS_ARB; 478 *iAttr++ = _this->gl_config.green_size; 479 *iAttr++ = WGL_BLUE_BITS_ARB; 480 *iAttr++ = _this->gl_config.blue_size; 481 482 if (_this->gl_config.alpha_size) { 483 *iAttr++ = WGL_ALPHA_BITS_ARB; 484 *iAttr++ = _this->gl_config.alpha_size; 485 } 486 487 *iAttr++ = WGL_DOUBLE_BUFFER_ARB; 488 *iAttr++ = _this->gl_config.double_buffer; 489 490 *iAttr++ = WGL_DEPTH_BITS_ARB; 491 *iAttr++ = _this->gl_config.depth_size; 492 493 if (_this->gl_config.stencil_size) { 494 *iAttr++ = WGL_STENCIL_BITS_ARB; 495 *iAttr++ = _this->gl_config.stencil_size; 496 } 497 498 if (_this->gl_config.accum_red_size) { 499 *iAttr++ = WGL_ACCUM_RED_BITS_ARB; 500 *iAttr++ = _this->gl_config.accum_red_size; 501 } 502 503 if (_this->gl_config.accum_green_size) { 504 *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; 505 *iAttr++ = _this->gl_config.accum_green_size; 506 } 507 508 if (_this->gl_config.accum_blue_size) { 509 *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; 510 *iAttr++ = _this->gl_config.accum_blue_size; 511 } 512 513 if (_this->gl_config.accum_alpha_size) { 514 *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; 515 *iAttr++ = _this->gl_config.accum_alpha_size; 516 } 517 518 if (_this->gl_config.stereo) { 519 *iAttr++ = WGL_STEREO_ARB; 520 *iAttr++ = GL_TRUE; 521 } 522 523 if (_this->gl_config.multisamplebuffers) { 524 *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; 525 *iAttr++ = _this->gl_config.multisamplebuffers; 526 } 527 528 if (_this->gl_config.multisamplesamples) { 529 *iAttr++ = WGL_SAMPLES_ARB; 530 *iAttr++ = _this->gl_config.multisamplesamples; 531 } 532 533 if (_this->gl_config.framebuffer_srgb_capable) { 534 *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; 535 *iAttr++ = _this->gl_config.framebuffer_srgb_capable; 536 } 537 538 /* We always choose either FULL or NO accel on Windows, because of flaky 539 drivers. If the app didn't specify, we use FULL, because that's 540 probably what they wanted (and if you didn't care and got FULL, that's 541 a perfectly valid result in any case). */ 542 *iAttr++ = WGL_ACCELERATION_ARB; 543 iAccelAttr = iAttr; 544 if (_this->gl_config.accelerated) { 545 *iAttr++ = WGL_FULL_ACCELERATION_ARB; 546 } else { 547 *iAttr++ = WGL_NO_ACCELERATION_ARB; 548 } 549 550 *iAttr = 0; 551 552 /* Choose and set the closest available pixel format */ 553 pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); 554 555 /* App said "don't care about accel" and FULL accel failed. Try NO. */ 556 if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) { 557 *iAccelAttr = WGL_NO_ACCELERATION_ARB; 558 pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs); 559 *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */ 560 } 561 if (!pixel_format) { 562 pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd); 563 } 564 if (!pixel_format) { 565 return SDL_SetError("No matching GL pixel format available"); 566 } 567 if (!SetPixelFormat(hdc, pixel_format, &pfd)) { 568 return WIN_SetError("SetPixelFormat()"); 569 } 570 return 0; 571} 572 573int 574WIN_GL_SetupWindow(_THIS, SDL_Window * window) 575{ 576 /* The current context is lost in here; save it and reset it. */ 577 SDL_Window *current_win = SDL_GL_GetCurrentWindow(); 578 SDL_GLContext current_ctx = SDL_GL_GetCurrentContext(); 579 const int retval = WIN_GL_SetupWindowInternal(_this, window); 580 WIN_GL_MakeCurrent(_this, current_win, current_ctx); 581 return retval; 582} 583 584SDL_GLContext 585WIN_GL_CreateContext(_THIS, SDL_Window * window) 586{ 587 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 588 HGLRC context, share_context; 589 590 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && 591 !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile) { 592#if SDL_VIDEO_OPENGL_EGL 593 /* Switch to EGL based functions */ 594 WIN_GL_UnloadLibrary(_this); 595 _this->GL_LoadLibrary = WIN_GLES_LoadLibrary; 596 _this->GL_GetProcAddress = WIN_GLES_GetProcAddress; 597 _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; 598 _this->GL_CreateContext = WIN_GLES_CreateContext; 599 _this->GL_MakeCurrent = WIN_GLES_MakeCurrent; 600 _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; 601 _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; 602 _this->GL_SwapWindow = WIN_GLES_SwapWindow; 603 _this->GL_DeleteContext = WIN_GLES_DeleteContext; 604 605 if (WIN_GLES_LoadLibrary(_this, NULL) != 0) { 606 return NULL; 607 } 608 609 return WIN_GLES_CreateContext(_this, window); 610#else 611 SDL_SetError("SDL not configured with EGL support"); 612 return NULL; 613#endif 614 } 615 616 if (_this->gl_config.share_with_current_context) { 617 share_context = (HGLRC)SDL_GL_GetCurrentContext(); 618 } else { 619 share_context = 0; 620 } 621 622 if (_this->gl_config.major_version < 3 && 623 _this->gl_config.profile_mask == 0 && 624 _this->gl_config.flags == 0) { 625 /* Create legacy context */ 626 context = _this->gl_data->wglCreateContext(hdc); 627 if( share_context != 0 ) { 628 _this->gl_data->wglShareLists(share_context, context); 629 } 630 } else { 631 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; 632 HGLRC temp_context = _this->gl_data->wglCreateContext(hdc); 633 if (!temp_context) { 634 SDL_SetError("Could not create GL context"); 635 return NULL; 636 } 637 638 /* Make the context current */ 639 if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) { 640 WIN_GL_DeleteContext(_this, temp_context); 641 return NULL; 642 } 643 644 wglCreateContextAttribsARB = 645 (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> 646 wglGetProcAddress("wglCreateContextAttribsARB"); 647 if (!wglCreateContextAttribsARB) { 648 SDL_SetError("GL 3.x is not supported"); 649 context = temp_context; 650 } else { 651 /* max 8 attributes plus terminator */ 652 int attribs[9] = { 653 WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, 654 WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 655 0 656 }; 657 int iattr = 4; 658 659 /* SDL profile bits match WGL profile bits */ 660 if( _this->gl_config.profile_mask != 0 ) { 661 attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB; 662 attribs[iattr++] = _this->gl_config.profile_mask; 663 } 664 665 /* SDL flags match WGL flags */ 666 if( _this->gl_config.flags != 0 ) { 667 attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB; 668 attribs[iattr++] = _this->gl_config.flags; 669 } 670 671 attribs[iattr++] = 0; 672 673 /* Create the GL 3.x context */ 674 context = wglCreateContextAttribsARB(hdc, share_context, attribs); 675 /* Delete the GL 2.x context */ 676 _this->gl_data->wglDeleteContext(temp_context); 677 } 678 } 679 680 if (!context) { 681 WIN_SetError("Could not create GL context"); 682 return NULL; 683 } 684 685 if (WIN_GL_MakeCurrent(_this, window, context) < 0) { 686 WIN_GL_DeleteContext(_this, context); 687 return NULL; 688 } 689 690 return context; 691} 692 693int 694WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) 695{ 696 HDC hdc; 697 698 if (!_this->gl_data) { 699 return SDL_SetError("OpenGL not initialized"); 700 } 701 702 /* sanity check that higher level handled this. */ 703 SDL_assert(window || (!window && !context)); 704 705 /* Some Windows drivers freak out if hdc is NULL, even when context is 706 NULL, against spec. Since hdc is _supposed_ to be ignored if context 707 is NULL, we either use the current GL window, or do nothing if we 708 already have no current context. */ 709 if (!window) { 710 window = SDL_GL_GetCurrentWindow(); 711 if (!window) { 712 SDL_assert(SDL_GL_GetCurrentContext() == NULL); 713 return 0; /* already done. */ 714 } 715 } 716 717 hdc = ((SDL_WindowData *) window->driverdata)->hdc; 718 if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) { 719 return WIN_SetError("wglMakeCurrent()"); 720 } 721 return 0; 722} 723 724int 725WIN_GL_SetSwapInterval(_THIS, int interval) 726{ 727 if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) { 728 return SDL_SetError("Negative swap interval unsupported in this GL"); 729 } else if (_this->gl_data->wglSwapIntervalEXT) { 730 if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) { 731 return WIN_SetError("wglSwapIntervalEXT()"); 732 } 733 } else { 734 return SDL_Unsupported(); 735 } 736 return 0; 737} 738 739int 740WIN_GL_GetSwapInterval(_THIS) 741{ 742 int retval = 0; 743 if (_this->gl_data->wglGetSwapIntervalEXT) { 744 retval = _this->gl_data->wglGetSwapIntervalEXT(); 745 } 746 return retval; 747} 748 749void 750WIN_GL_SwapWindow(_THIS, SDL_Window * window) 751{ 752 HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc; 753 754 SwapBuffers(hdc); 755} 756 757void 758WIN_GL_DeleteContext(_THIS, SDL_GLContext context) 759{ 760 if (!_this->gl_data) { 761 return; 762 } 763 _this->gl_data->wglDeleteContext((HGLRC) context); 764} 765 766 767SDL_bool 768WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow) 769{ 770 HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc; 771 HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc; 772 BOOL result; 773 774 /* get the pixel format of the fromWindow */ 775 int pixel_format = GetPixelFormat(hfromdc); 776 PIXELFORMATDESCRIPTOR pfd; 777 SDL_memset(&pfd, 0, sizeof(pfd)); 778 DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd); 779 780 /* set the pixel format of the toWindow */ 781 result = SetPixelFormat(htodc, pixel_format, &pfd); 782 783 return result ? SDL_TRUE : SDL_FALSE; 784} 785 786#endif /* SDL_VIDEO_OPENGL_WGL */ 787 788#endif /* SDL_VIDEO_DRIVER_WINDOWS */ 789 790/* vi: set ts=4 sw=4 expandtab: */