00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "internal.h"
00029
00030 #include <stdlib.h>
00031 #include <malloc.h>
00032 #include <assert.h>
00033
00034
00035
00036
00037 static void initWGLExtensions(_GLFWwindow* window)
00038 {
00039
00040
00041 window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
00042 _glfw_wglGetProcAddress("wglGetExtensionsStringEXT");
00043 window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
00044 _glfw_wglGetProcAddress("wglGetExtensionsStringARB");
00045
00046
00047 window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
00048 _glfw_wglGetProcAddress("wglCreateContextAttribsARB");
00049
00050
00051 window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
00052 _glfw_wglGetProcAddress("wglSwapIntervalEXT");
00053
00054
00055 window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
00056 _glfw_wglGetProcAddress("wglGetPixelFormatAttribivARB");
00057
00058
00059
00060 window->wgl.ARB_multisample =
00061 _glfwPlatformExtensionSupported("WGL_ARB_multisample");
00062 window->wgl.ARB_framebuffer_sRGB =
00063 _glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB");
00064 window->wgl.EXT_framebuffer_sRGB =
00065 _glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB");
00066 window->wgl.ARB_create_context =
00067 _glfwPlatformExtensionSupported("WGL_ARB_create_context");
00068 window->wgl.ARB_create_context_profile =
00069 _glfwPlatformExtensionSupported("WGL_ARB_create_context_profile");
00070 window->wgl.EXT_create_context_es2_profile =
00071 _glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile");
00072 window->wgl.ARB_create_context_robustness =
00073 _glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness");
00074 window->wgl.EXT_swap_control =
00075 _glfwPlatformExtensionSupported("WGL_EXT_swap_control");
00076 window->wgl.ARB_pixel_format =
00077 _glfwPlatformExtensionSupported("WGL_ARB_pixel_format");
00078 window->wgl.ARB_context_flush_control =
00079 _glfwPlatformExtensionSupported("WGL_ARB_context_flush_control");
00080 }
00081
00082
00083
00084 static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
00085 {
00086 int value = 0;
00087
00088 assert(window->wgl.ARB_pixel_format);
00089
00090 if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc,
00091 pixelFormat,
00092 0, 1, &attrib, &value))
00093 {
00094 _glfwInputError(GLFW_PLATFORM_ERROR,
00095 "WGL: Failed to retrieve pixel format attribute %i",
00096 attrib);
00097 return 0;
00098 }
00099
00100 return value;
00101 }
00102
00103
00104
00105 static GLboolean choosePixelFormat(_GLFWwindow* window,
00106 const _GLFWfbconfig* desired,
00107 int* result)
00108 {
00109 _GLFWfbconfig* usableConfigs;
00110 const _GLFWfbconfig* closest;
00111 int i, nativeCount, usableCount;
00112
00113 if (window->wgl.ARB_pixel_format)
00114 {
00115 nativeCount = getPixelFormatAttrib(window,
00116 1,
00117 WGL_NUMBER_PIXEL_FORMATS_ARB);
00118 }
00119 else
00120 {
00121 nativeCount = DescribePixelFormat(window->wgl.dc,
00122 1,
00123 sizeof(PIXELFORMATDESCRIPTOR),
00124 NULL);
00125 }
00126
00127 usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
00128 usableCount = 0;
00129
00130 for (i = 0; i < nativeCount; i++)
00131 {
00132 const int n = i + 1;
00133 _GLFWfbconfig* u = usableConfigs + usableCount;
00134
00135 if (window->wgl.ARB_pixel_format)
00136 {
00137
00138
00139 if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
00140 !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
00141 {
00142 continue;
00143 }
00144
00145 if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
00146 WGL_TYPE_RGBA_ARB)
00147 {
00148 continue;
00149 }
00150
00151 if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
00152 WGL_NO_ACCELERATION_ARB)
00153 {
00154 continue;
00155 }
00156
00157 u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
00158 u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
00159 u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
00160 u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
00161
00162 u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
00163 u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
00164
00165 u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
00166 u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
00167 u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
00168 u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
00169
00170 u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
00171
00172 if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
00173 u->stereo = GL_TRUE;
00174 if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
00175 u->doublebuffer = GL_TRUE;
00176
00177 if (window->wgl.ARB_multisample)
00178 u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
00179
00180 if (window->wgl.ARB_framebuffer_sRGB ||
00181 window->wgl.EXT_framebuffer_sRGB)
00182 {
00183 if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
00184 u->sRGB = GL_TRUE;
00185 }
00186 }
00187 else
00188 {
00189 PIXELFORMATDESCRIPTOR pfd;
00190
00191
00192
00193 if (!DescribePixelFormat(window->wgl.dc,
00194 n,
00195 sizeof(PIXELFORMATDESCRIPTOR),
00196 &pfd))
00197 {
00198 continue;
00199 }
00200
00201 if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
00202 !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
00203 {
00204 continue;
00205 }
00206
00207 if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
00208 (pfd.dwFlags & PFD_GENERIC_FORMAT))
00209 {
00210 continue;
00211 }
00212
00213 if (pfd.iPixelType != PFD_TYPE_RGBA)
00214 continue;
00215
00216 u->redBits = pfd.cRedBits;
00217 u->greenBits = pfd.cGreenBits;
00218 u->blueBits = pfd.cBlueBits;
00219 u->alphaBits = pfd.cAlphaBits;
00220
00221 u->depthBits = pfd.cDepthBits;
00222 u->stencilBits = pfd.cStencilBits;
00223
00224 u->accumRedBits = pfd.cAccumRedBits;
00225 u->accumGreenBits = pfd.cAccumGreenBits;
00226 u->accumBlueBits = pfd.cAccumBlueBits;
00227 u->accumAlphaBits = pfd.cAccumAlphaBits;
00228
00229 u->auxBuffers = pfd.cAuxBuffers;
00230
00231 if (pfd.dwFlags & PFD_STEREO)
00232 u->stereo = GL_TRUE;
00233 if (pfd.dwFlags & PFD_DOUBLEBUFFER)
00234 u->doublebuffer = GL_TRUE;
00235 }
00236
00237 u->wgl = n;
00238 usableCount++;
00239 }
00240
00241 if (!usableCount)
00242 {
00243 _glfwInputError(GLFW_API_UNAVAILABLE,
00244 "WGL: The driver does not appear to support OpenGL");
00245
00246 free(usableConfigs);
00247 return GL_FALSE;
00248 }
00249
00250 closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
00251 if (!closest)
00252 {
00253 _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
00254 "WGL: Failed to find a suitable pixel format");
00255
00256 free(usableConfigs);
00257 return GL_FALSE;
00258 }
00259
00260 *result = closest->wgl;
00261 free(usableConfigs);
00262
00263 return GL_TRUE;
00264 }
00265
00266
00270
00271
00272
00273 int _glfwInitContextAPI(void)
00274 {
00275 if (!_glfwCreateContextTLS())
00276 return GL_FALSE;
00277
00278 _glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll");
00279 if (!_glfw.wgl.opengl32.instance)
00280 {
00281 _glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
00282 return GL_FALSE;
00283 }
00284
00285 _glfw.wgl.opengl32.CreateContext = (WGLCREATECONTEXT_T)
00286 GetProcAddress(_glfw.wgl.opengl32.instance, "wglCreateContext");
00287 _glfw.wgl.opengl32.DeleteContext = (WGLDELETECONTEXT_T)
00288 GetProcAddress(_glfw.wgl.opengl32.instance, "wglDeleteContext");
00289 _glfw.wgl.opengl32.GetProcAddress = (WGLGETPROCADDRESS_T)
00290 GetProcAddress(_glfw.wgl.opengl32.instance, "wglGetProcAddress");
00291 _glfw.wgl.opengl32.MakeCurrent = (WGLMAKECURRENT_T)
00292 GetProcAddress(_glfw.wgl.opengl32.instance, "wglMakeCurrent");
00293 _glfw.wgl.opengl32.ShareLists = (WGLSHARELISTS_T)
00294 GetProcAddress(_glfw.wgl.opengl32.instance, "wglShareLists");
00295
00296 if (!_glfw.wgl.opengl32.CreateContext ||
00297 !_glfw.wgl.opengl32.DeleteContext ||
00298 !_glfw.wgl.opengl32.GetProcAddress ||
00299 !_glfw.wgl.opengl32.MakeCurrent ||
00300 !_glfw.wgl.opengl32.ShareLists)
00301 {
00302 _glfwInputError(GLFW_PLATFORM_ERROR,
00303 "WGL: Failed to load opengl32 functions");
00304 return GL_FALSE;
00305 }
00306
00307 return GL_TRUE;
00308 }
00309
00310
00311
00312 void _glfwTerminateContextAPI(void)
00313 {
00314 if (_glfw.wgl.opengl32.instance)
00315 FreeLibrary(_glfw.wgl.opengl32.instance);
00316
00317 _glfwDestroyContextTLS();
00318 }
00319
00320 #define setWGLattrib(attribName, attribValue) \
00321 { \
00322 attribs[index++] = attribName; \
00323 attribs[index++] = attribValue; \
00324 assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
00325 }
00326
00327
00328
00329 int _glfwCreateContext(_GLFWwindow* window,
00330 const _GLFWctxconfig* ctxconfig,
00331 const _GLFWfbconfig* fbconfig)
00332 {
00333 int attribs[40];
00334 int pixelFormat = 0;
00335 PIXELFORMATDESCRIPTOR pfd;
00336 HGLRC share = NULL;
00337
00338 if (ctxconfig->share)
00339 share = ctxconfig->share->wgl.context;
00340
00341 window->wgl.dc = GetDC(window->win32.handle);
00342 if (!window->wgl.dc)
00343 {
00344 _glfwInputError(GLFW_PLATFORM_ERROR,
00345 "WGL: Failed to retrieve DC for window");
00346 return GL_FALSE;
00347 }
00348
00349 if (!choosePixelFormat(window, fbconfig, &pixelFormat))
00350 return GL_FALSE;
00351
00352 if (!DescribePixelFormat(window->wgl.dc, pixelFormat, sizeof(pfd), &pfd))
00353 {
00354 _glfwInputError(GLFW_PLATFORM_ERROR,
00355 "WGL: Failed to retrieve PFD for selected pixel format");
00356 return GL_FALSE;
00357 }
00358
00359 if (!SetPixelFormat(window->wgl.dc, pixelFormat, &pfd))
00360 {
00361 _glfwInputError(GLFW_PLATFORM_ERROR,
00362 "WGL: Failed to set selected pixel format");
00363 return GL_FALSE;
00364 }
00365
00366 if (window->wgl.ARB_create_context)
00367 {
00368 int index = 0, mask = 0, flags = 0;
00369
00370 if (ctxconfig->api == GLFW_OPENGL_API)
00371 {
00372 if (ctxconfig->forward)
00373 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
00374
00375 if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
00376 mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
00377 else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
00378 mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
00379 }
00380 else
00381 mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
00382
00383 if (ctxconfig->debug)
00384 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
00385
00386 if (ctxconfig->robustness)
00387 {
00388 if (window->wgl.ARB_create_context_robustness)
00389 {
00390 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
00391 {
00392 setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
00393 WGL_NO_RESET_NOTIFICATION_ARB);
00394 }
00395 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
00396 {
00397 setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
00398 WGL_LOSE_CONTEXT_ON_RESET_ARB);
00399 }
00400
00401 flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
00402 }
00403 }
00404
00405 if (ctxconfig->release)
00406 {
00407 if (window->wgl.ARB_context_flush_control)
00408 {
00409 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
00410 {
00411 setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
00412 WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
00413 }
00414 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
00415 {
00416 setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
00417 WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
00418 }
00419 }
00420 }
00421
00422
00423
00424
00425 if (ctxconfig->major != 1 || ctxconfig->minor != 0)
00426 {
00427 setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
00428 setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
00429 }
00430
00431 if (flags)
00432 setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
00433
00434 if (mask)
00435 setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
00436
00437 setWGLattrib(0, 0);
00438
00439 window->wgl.context = window->wgl.CreateContextAttribsARB(window->wgl.dc,
00440 share,
00441 attribs);
00442 if (!window->wgl.context)
00443 {
00444 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
00445 "WGL: Failed to create OpenGL context");
00446 return GL_FALSE;
00447 }
00448 }
00449 else
00450 {
00451 window->wgl.context = _glfw_wglCreateContext(window->wgl.dc);
00452 if (!window->wgl.context)
00453 {
00454 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
00455 "WGL: Failed to create OpenGL context");
00456 return GL_FALSE;
00457 }
00458
00459 if (share)
00460 {
00461 if (!_glfw_wglShareLists(share, window->wgl.context))
00462 {
00463 _glfwInputError(GLFW_PLATFORM_ERROR,
00464 "WGL: Failed to enable sharing with specified OpenGL context");
00465 return GL_FALSE;
00466 }
00467 }
00468 }
00469
00470 _glfwPlatformMakeContextCurrent(window);
00471 initWGLExtensions(window);
00472
00473 return GL_TRUE;
00474 }
00475
00476 #undef setWGLattrib
00477
00478
00479
00480 void _glfwDestroyContext(_GLFWwindow* window)
00481 {
00482 if (window->wgl.context)
00483 {
00484 _glfw_wglDeleteContext(window->wgl.context);
00485 window->wgl.context = NULL;
00486 }
00487
00488 if (window->wgl.dc)
00489 {
00490 ReleaseDC(window->win32.handle, window->wgl.dc);
00491 window->wgl.dc = NULL;
00492 }
00493 }
00494
00495
00496
00497 int _glfwAnalyzeContext(const _GLFWwindow* window,
00498 const _GLFWctxconfig* ctxconfig,
00499 const _GLFWfbconfig* fbconfig)
00500 {
00501 GLboolean required = GL_FALSE;
00502
00503 if (ctxconfig->api == GLFW_OPENGL_API)
00504 {
00505 if (ctxconfig->forward)
00506 {
00507 if (!window->wgl.ARB_create_context)
00508 {
00509 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
00510 "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
00511 return _GLFW_RECREATION_IMPOSSIBLE;
00512 }
00513
00514 required = GL_TRUE;
00515 }
00516
00517 if (ctxconfig->profile)
00518 {
00519 if (!window->wgl.ARB_create_context_profile)
00520 {
00521 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
00522 "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
00523 return _GLFW_RECREATION_IMPOSSIBLE;
00524 }
00525
00526 required = GL_TRUE;
00527 }
00528
00529 if (ctxconfig->release)
00530 {
00531 if (window->wgl.ARB_context_flush_control)
00532 required = GL_TRUE;
00533 }
00534 }
00535 else
00536 {
00537 if (!window->wgl.ARB_create_context ||
00538 !window->wgl.ARB_create_context_profile ||
00539 !window->wgl.EXT_create_context_es2_profile)
00540 {
00541 _glfwInputError(GLFW_API_UNAVAILABLE,
00542 "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
00543 return _GLFW_RECREATION_IMPOSSIBLE;
00544 }
00545
00546 required = GL_TRUE;
00547 }
00548
00549 if (ctxconfig->major != 1 || ctxconfig->minor != 0)
00550 {
00551 if (window->wgl.ARB_create_context)
00552 required = GL_TRUE;
00553 }
00554
00555 if (ctxconfig->debug)
00556 {
00557 if (window->wgl.ARB_create_context)
00558 required = GL_TRUE;
00559 }
00560
00561 if (fbconfig->samples > 0)
00562 {
00563
00564 if (window->wgl.ARB_multisample && window->wgl.ARB_pixel_format)
00565 required = GL_TRUE;
00566 }
00567
00568 if (fbconfig->sRGB)
00569 {
00570
00571 if ((window->wgl.ARB_framebuffer_sRGB ||
00572 window->wgl.EXT_framebuffer_sRGB) &&
00573 window->wgl.ARB_pixel_format)
00574 {
00575 required = GL_TRUE;
00576 }
00577 }
00578
00579 if (required)
00580 return _GLFW_RECREATION_REQUIRED;
00581
00582 return _GLFW_RECREATION_NOT_NEEDED;
00583 }
00584
00585
00589
00590 void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
00591 {
00592 if (window)
00593 _glfw_wglMakeCurrent(window->wgl.dc, window->wgl.context);
00594 else
00595 _glfw_wglMakeCurrent(NULL, NULL);
00596
00597 _glfwSetContextTLS(window);
00598 }
00599
00600 void _glfwPlatformSwapBuffers(_GLFWwindow* window)
00601 {
00602
00603 if (_glfwIsCompositionEnabled() && !window->monitor)
00604 {
00605 int count = abs(window->wgl.interval);
00606 while (count--)
00607 _glfw_DwmFlush();
00608 }
00609
00610 SwapBuffers(window->wgl.dc);
00611 }
00612
00613 void _glfwPlatformSwapInterval(int interval)
00614 {
00615 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
00616
00617 window->wgl.interval = interval;
00618
00619
00620
00621 if (_glfwIsCompositionEnabled() && !window->monitor)
00622 interval = 0;
00623
00624 if (window->wgl.EXT_swap_control)
00625 window->wgl.SwapIntervalEXT(interval);
00626 }
00627
00628 int _glfwPlatformExtensionSupported(const char* extension)
00629 {
00630 const char* extensions;
00631
00632 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
00633
00634 if (window->wgl.GetExtensionsStringEXT != NULL)
00635 {
00636 extensions = window->wgl.GetExtensionsStringEXT();
00637 if (extensions)
00638 {
00639 if (_glfwStringInExtensionString(extension, extensions))
00640 return GL_TRUE;
00641 }
00642 }
00643
00644 if (window->wgl.GetExtensionsStringARB != NULL)
00645 {
00646 extensions = window->wgl.GetExtensionsStringARB(window->wgl.dc);
00647 if (extensions)
00648 {
00649 if (_glfwStringInExtensionString(extension, extensions))
00650 return GL_TRUE;
00651 }
00652 }
00653
00654 return GL_FALSE;
00655 }
00656
00657 GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
00658 {
00659 const GLFWglproc proc = (GLFWglproc) _glfw_wglGetProcAddress(procname);
00660 if (proc)
00661 return proc;
00662
00663 return (GLFWglproc) GetProcAddress(_glfw.wgl.opengl32.instance, procname);
00664 }
00665
00666
00670
00671 GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
00672 {
00673 _GLFWwindow* window = (_GLFWwindow*) handle;
00674 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00675 return window->wgl.context;
00676 }
00677