1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/GLContextProviderWGL.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,682 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "GLContextProvider.h" 1.10 +#include "GLContextWGL.h" 1.11 +#include "GLLibraryLoader.h" 1.12 +#include "nsDebug.h" 1.13 +#include "nsIWidget.h" 1.14 +#include "gfxPlatform.h" 1.15 +#include "gfxWindowsSurface.h" 1.16 + 1.17 +#include "gfxCrashReporterUtils.h" 1.18 + 1.19 +#include "prenv.h" 1.20 + 1.21 +#include "mozilla/Preferences.h" 1.22 + 1.23 +using namespace mozilla::gfx; 1.24 + 1.25 +namespace mozilla { 1.26 +namespace gl { 1.27 + 1.28 +WGLLibrary sWGLLib; 1.29 + 1.30 +HWND 1.31 +WGLLibrary::CreateDummyWindow(HDC *aWindowDC) 1.32 +{ 1.33 + WNDCLASSW wc; 1.34 + if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) { 1.35 + ZeroMemory(&wc, sizeof(WNDCLASSW)); 1.36 + wc.style = CS_OWNDC; 1.37 + wc.hInstance = GetModuleHandle(nullptr); 1.38 + wc.lpfnWndProc = DefWindowProc; 1.39 + wc.lpszClassName = L"GLContextWGLClass"; 1.40 + if (!RegisterClassW(&wc)) { 1.41 + NS_WARNING("Failed to register GLContextWGLClass?!"); 1.42 + // er. failed to register our class? 1.43 + return nullptr; 1.44 + } 1.45 + } 1.46 + 1.47 + HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, 1.48 + 0, 0, 16, 16, 1.49 + nullptr, nullptr, GetModuleHandle(nullptr), 1.50 + nullptr); 1.51 + NS_ENSURE_TRUE(win, nullptr); 1.52 + 1.53 + HDC dc = GetDC(win); 1.54 + NS_ENSURE_TRUE(dc, nullptr); 1.55 + 1.56 + if (mWindowPixelFormat == 0) { 1.57 + PIXELFORMATDESCRIPTOR pfd; 1.58 + ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); 1.59 + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 1.60 + pfd.nVersion = 1; 1.61 + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 1.62 + pfd.iPixelType = PFD_TYPE_RGBA; 1.63 + pfd.cColorBits = 24; 1.64 + pfd.cRedBits = 8; 1.65 + pfd.cGreenBits = 8; 1.66 + pfd.cBlueBits = 8; 1.67 + pfd.cAlphaBits = 8; 1.68 + pfd.cDepthBits = 0; 1.69 + pfd.iLayerType = PFD_MAIN_PLANE; 1.70 + 1.71 + mWindowPixelFormat = ChoosePixelFormat(dc, &pfd); 1.72 + } 1.73 + 1.74 + if (!mWindowPixelFormat || 1.75 + !SetPixelFormat(dc, mWindowPixelFormat, nullptr)) 1.76 + { 1.77 + NS_WARNING("SetPixelFormat failed!"); 1.78 + DestroyWindow(win); 1.79 + return nullptr; 1.80 + } 1.81 + 1.82 + if (aWindowDC) { 1.83 + *aWindowDC = dc; 1.84 + } 1.85 + 1.86 + return win; 1.87 +} 1.88 + 1.89 +static inline bool 1.90 +HasExtension(const char* aExtensions, const char* aRequiredExtension) 1.91 +{ 1.92 + return GLContext::ListHasExtension( 1.93 + reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension); 1.94 +} 1.95 + 1.96 +bool 1.97 +WGLLibrary::EnsureInitialized() 1.98 +{ 1.99 + if (mInitialized) 1.100 + return true; 1.101 + 1.102 + mozilla::ScopedGfxFeatureReporter reporter("WGL"); 1.103 + 1.104 + std::string libGLFilename = "Opengl32.dll"; 1.105 + // SU_SPIES_DIRECTORY is for AMD CodeXL/gDEBugger 1.106 + if (PR_GetEnv("SU_SPIES_DIRECTORY")) { 1.107 + libGLFilename = std::string(PR_GetEnv("SU_SPIES_DIRECTORY")) + "\\opengl32.dll"; 1.108 + } 1.109 + 1.110 + if (!mOGLLibrary) { 1.111 + mOGLLibrary = PR_LoadLibrary(&libGLFilename[0]); 1.112 + if (!mOGLLibrary) { 1.113 + NS_WARNING("Couldn't load OpenGL library."); 1.114 + return false; 1.115 + } 1.116 + } 1.117 + 1.118 + GLLibraryLoader::SymLoadStruct earlySymbols[] = { 1.119 + { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", nullptr } }, 1.120 + { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", nullptr } }, 1.121 + { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", nullptr } }, 1.122 + { (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", nullptr } }, 1.123 + { (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", nullptr } }, 1.124 + { (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", nullptr } }, 1.125 + { (PRFuncPtr*) &fShareLists, { "wglShareLists", nullptr } }, 1.126 + { nullptr, { nullptr } } 1.127 + }; 1.128 + 1.129 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) { 1.130 + NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)"); 1.131 + return false; 1.132 + } 1.133 + 1.134 + // This is ridiculous -- we have to actually create a context to 1.135 + // get the OpenGL ICD to load. 1.136 + mWindow = CreateDummyWindow(&mWindowDC); 1.137 + NS_ENSURE_TRUE(mWindow, false); 1.138 + 1.139 + // create rendering context 1.140 + mWindowGLContext = fCreateContext(mWindowDC); 1.141 + NS_ENSURE_TRUE(mWindowGLContext, false); 1.142 + 1.143 + HGLRC curCtx = fGetCurrentContext(); 1.144 + HDC curDC = fGetCurrentDC(); 1.145 + 1.146 + if (!fMakeCurrent((HDC)mWindowDC, (HGLRC)mWindowGLContext)) { 1.147 + NS_WARNING("wglMakeCurrent failed"); 1.148 + return false; 1.149 + } 1.150 + 1.151 + // Now we can grab all the other symbols that we couldn't without having 1.152 + // a context current. 1.153 + 1.154 + GLLibraryLoader::SymLoadStruct pbufferSymbols[] = { 1.155 + { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } }, 1.156 + { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } }, 1.157 + { (PRFuncPtr*) &fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", nullptr } }, 1.158 + { (PRFuncPtr*) &fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } }, 1.159 + { (PRFuncPtr*) &fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } }, 1.160 + { nullptr, { nullptr } } 1.161 + }; 1.162 + 1.163 + GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = { 1.164 + { (PRFuncPtr*) &fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", nullptr } }, 1.165 + { (PRFuncPtr*) &fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } }, 1.166 + { nullptr, { nullptr } } 1.167 + }; 1.168 + 1.169 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], 1.170 + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) 1.171 + { 1.172 + // this isn't an error, just means that pbuffers aren't supported 1.173 + fCreatePbuffer = nullptr; 1.174 + } 1.175 + 1.176 + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], 1.177 + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) 1.178 + { 1.179 + // this isn't an error, just means that we don't have the pixel format extension 1.180 + fChoosePixelFormat = nullptr; 1.181 + } 1.182 + 1.183 + GLLibraryLoader::SymLoadStruct extensionsSymbols[] = { 1.184 + { (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", nullptr} }, 1.185 + { nullptr, { nullptr } } 1.186 + }; 1.187 + 1.188 + GLLibraryLoader::SymLoadStruct robustnessSymbols[] = { 1.189 + { (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", nullptr} }, 1.190 + { nullptr, { nullptr } } 1.191 + }; 1.192 + 1.193 + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], 1.194 + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { 1.195 + const char *wglExts = fGetExtensionsString(mWindowDC); 1.196 + if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) { 1.197 + GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], 1.198 + (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress); 1.199 + if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) { 1.200 + mHasRobustness = true; 1.201 + } 1.202 + } 1.203 + } 1.204 + 1.205 + // reset back to the previous context, just in case 1.206 + fMakeCurrent(curDC, curCtx); 1.207 + 1.208 + if (mHasRobustness) { 1.209 + fDeleteContext(mWindowGLContext); 1.210 + 1.211 + int attribs[] = { 1.212 + LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, 1.213 + LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 1.214 + 0 1.215 + }; 1.216 + 1.217 + mWindowGLContext = fCreateContextAttribs(mWindowDC, nullptr, attribs); 1.218 + if (!mWindowGLContext) { 1.219 + mHasRobustness = false; 1.220 + mWindowGLContext = fCreateContext(mWindowDC); 1.221 + } 1.222 + } 1.223 + 1.224 + mInitialized = true; 1.225 + 1.226 + // Call this to create the global GLContext instance, 1.227 + // and to check for errors. Note that this must happen /after/ 1.228 + // setting mInitialized to TRUE, or an infinite loop results. 1.229 + if (GLContextProviderWGL::GetGlobalContext() == nullptr) { 1.230 + mInitialized = false; 1.231 + return false; 1.232 + } 1.233 + 1.234 + reporter.SetSuccessful(); 1.235 + return true; 1.236 +} 1.237 + 1.238 +GLContextWGL::GLContextWGL( 1.239 + const SurfaceCaps& caps, 1.240 + GLContext* sharedContext, 1.241 + bool isOffscreen, 1.242 + HDC aDC, 1.243 + HGLRC aContext, 1.244 + HWND aWindow) 1.245 + : GLContext(caps, sharedContext, isOffscreen), 1.246 + mDC(aDC), 1.247 + mContext(aContext), 1.248 + mWnd(aWindow), 1.249 + mPBuffer(nullptr), 1.250 + mPixelFormat(0), 1.251 + mIsDoubleBuffered(false) 1.252 +{ 1.253 + // See 899855 1.254 + SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); 1.255 +} 1.256 + 1.257 +GLContextWGL::GLContextWGL( 1.258 + const SurfaceCaps& caps, 1.259 + GLContext* sharedContext, 1.260 + bool isOffscreen, 1.261 + HANDLE aPbuffer, 1.262 + HDC aDC, 1.263 + HGLRC aContext, 1.264 + int aPixelFormat) 1.265 + : GLContext(caps, sharedContext, isOffscreen), 1.266 + mDC(aDC), 1.267 + mContext(aContext), 1.268 + mWnd(nullptr), 1.269 + mPBuffer(aPbuffer), 1.270 + mPixelFormat(aPixelFormat), 1.271 + mIsDoubleBuffered(false) 1.272 +{ 1.273 + // See 899855 1.274 + SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); 1.275 +} 1.276 + 1.277 +GLContextWGL::~GLContextWGL() 1.278 +{ 1.279 + MarkDestroyed(); 1.280 + 1.281 + sWGLLib.fDeleteContext(mContext); 1.282 + 1.283 + if (mPBuffer) 1.284 + sWGLLib.fDestroyPbuffer(mPBuffer); 1.285 + if (mWnd) 1.286 + DestroyWindow(mWnd); 1.287 +} 1.288 + 1.289 +bool 1.290 +GLContextWGL::Init() 1.291 +{ 1.292 + if (!mDC || !mContext) 1.293 + return false; 1.294 + 1.295 + // see bug 929506 comment 29. wglGetProcAddress requires a current context. 1.296 + if (!sWGLLib.fMakeCurrent(mDC, mContext)) 1.297 + return false; 1.298 + 1.299 + SetupLookupFunction(); 1.300 + if (!InitWithPrefix("gl", true)) 1.301 + return false; 1.302 + 1.303 + return true; 1.304 +} 1.305 + 1.306 +bool 1.307 +GLContextWGL::MakeCurrentImpl(bool aForce) 1.308 +{ 1.309 + BOOL succeeded = true; 1.310 + 1.311 + // wglGetCurrentContext seems to just pull the HGLRC out 1.312 + // of its TLS slot, so no need to do our own tls slot. 1.313 + // You would think that wglMakeCurrent would avoid doing 1.314 + // work if mContext was already current, but not so much.. 1.315 + if (aForce || sWGLLib.fGetCurrentContext() != mContext) { 1.316 + succeeded = sWGLLib.fMakeCurrent(mDC, mContext); 1.317 + NS_ASSERTION(succeeded, "Failed to make GL context current!"); 1.318 + } 1.319 + 1.320 + return succeeded; 1.321 +} 1.322 + 1.323 +bool 1.324 +GLContextWGL::IsCurrent() 1.325 +{ 1.326 + return sWGLLib.fGetCurrentContext() == mContext; 1.327 +} 1.328 + 1.329 +void 1.330 +GLContextWGL::SetIsDoubleBuffered(bool aIsDB) 1.331 +{ 1.332 + mIsDoubleBuffered = aIsDB; 1.333 +} 1.334 + 1.335 +bool 1.336 +GLContextWGL::IsDoubleBuffered() const 1.337 +{ 1.338 + return mIsDoubleBuffered; 1.339 +} 1.340 + 1.341 +bool 1.342 +GLContextWGL::SupportsRobustness() const 1.343 +{ 1.344 + return sWGLLib.HasRobustness(); 1.345 +} 1.346 + 1.347 +bool 1.348 +GLContextWGL::SwapBuffers() { 1.349 + if (!mIsDoubleBuffered) 1.350 + return false; 1.351 + return ::SwapBuffers(mDC); 1.352 +} 1.353 + 1.354 +bool 1.355 +GLContextWGL::SetupLookupFunction() 1.356 +{ 1.357 + // Make sure that we have a ref to the OGL library; 1.358 + // when run under CodeXL, wglGetProcAddress won't return 1.359 + // the right thing for some core functions. 1.360 + MOZ_ASSERT(mLibrary == nullptr); 1.361 + 1.362 + mLibrary = sWGLLib.GetOGLLibrary(); 1.363 + mLookupFunc = (PlatformLookupFunction)sWGLLib.fGetProcAddress; 1.364 + return true; 1.365 +} 1.366 + 1.367 +static bool 1.368 +GetMaxSize(HDC hDC, int format, gfxIntSize& size) 1.369 +{ 1.370 + int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB}; 1.371 + int result[2]; 1.372 + 1.373 + // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues) 1.374 + if (!sWGLLib.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result)) 1.375 + return false; 1.376 + 1.377 + size.width = result[0]; 1.378 + size.height = result[1]; 1.379 + return true; 1.380 +} 1.381 + 1.382 +static bool 1.383 +IsValidSizeForFormat(HDC hDC, int format, 1.384 + const gfxIntSize& requested) 1.385 +{ 1.386 + gfxIntSize max; 1.387 + if (!GetMaxSize(hDC, format, max)) 1.388 + return true; 1.389 + 1.390 + if (requested.width > max.width) 1.391 + return false; 1.392 + if (requested.height > max.height) 1.393 + return false; 1.394 + 1.395 + return true; 1.396 +} 1.397 + 1.398 +static GLContextWGL * 1.399 +GetGlobalContextWGL() 1.400 +{ 1.401 + return static_cast<GLContextWGL*>(GLContextProviderWGL::GetGlobalContext()); 1.402 +} 1.403 + 1.404 +already_AddRefed<GLContext> 1.405 +GLContextProviderWGL::CreateWrappingExisting(void*, void*) 1.406 +{ 1.407 + return nullptr; 1.408 +} 1.409 + 1.410 +already_AddRefed<GLContext> 1.411 +GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget) 1.412 +{ 1.413 + if (!sWGLLib.EnsureInitialized()) { 1.414 + return nullptr; 1.415 + } 1.416 + 1.417 + /** 1.418 + * We need to make sure we call SetPixelFormat -after- calling 1.419 + * EnsureInitialized, otherwise it can load/unload the dll and 1.420 + * wglCreateContext will fail. 1.421 + */ 1.422 + 1.423 + HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC); 1.424 + 1.425 + SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr); 1.426 + HGLRC context; 1.427 + 1.428 + GLContextWGL *shareContext = GetGlobalContextWGL(); 1.429 + 1.430 + if (sWGLLib.HasRobustness()) { 1.431 + int attribs[] = { 1.432 + LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, 1.433 + LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 1.434 + 0 1.435 + }; 1.436 + 1.437 + context = sWGLLib.fCreateContextAttribs(dc, 1.438 + shareContext ? shareContext->Context() : nullptr, 1.439 + attribs); 1.440 + } else { 1.441 + context = sWGLLib.fCreateContext(dc); 1.442 + if (context && 1.443 + shareContext && 1.444 + !sWGLLib.fShareLists(shareContext->Context(), context)) 1.445 + { 1.446 + printf_stderr("WGL context creation failed for window: wglShareLists returned false!"); 1.447 + sWGLLib.fDeleteContext(context); 1.448 + context = nullptr; 1.449 + } 1.450 + } 1.451 + 1.452 + if (!context) { 1.453 + return nullptr; 1.454 + } 1.455 + 1.456 + SurfaceCaps caps = SurfaceCaps::ForRGBA(); 1.457 + nsRefPtr<GLContextWGL> glContext = new GLContextWGL(caps, 1.458 + shareContext, 1.459 + false, 1.460 + dc, 1.461 + context); 1.462 + if (!glContext->Init()) { 1.463 + return nullptr; 1.464 + } 1.465 + 1.466 + glContext->SetIsDoubleBuffered(true); 1.467 + 1.468 + return glContext.forget(); 1.469 +} 1.470 + 1.471 +static already_AddRefed<GLContextWGL> 1.472 +CreatePBufferOffscreenContext(const gfxIntSize& aSize, 1.473 + GLContextWGL *aShareContext) 1.474 +{ 1.475 + WGLLibrary& wgl = sWGLLib; 1.476 + 1.477 +#define A1(_a,_x) do { _a.AppendElement(_x); } while(0) 1.478 +#define A2(_a,_x,_y) do { _a.AppendElement(_x); _a.AppendElement(_y); } while(0) 1.479 + 1.480 + nsTArray<int> attrs; 1.481 + 1.482 + A2(attrs, LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE); 1.483 + A2(attrs, LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE); 1.484 + A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE); 1.485 + 1.486 + A2(attrs, LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB); 1.487 + 1.488 + A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE); 1.489 + A2(attrs, LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE); 1.490 + 1.491 + A1(attrs, 0); 1.492 + 1.493 + nsTArray<int> pbattrs; 1.494 + A1(pbattrs, 0); 1.495 + 1.496 +#undef A1 1.497 +#undef A2 1.498 + 1.499 + // We only need one! 1.500 + UINT numFormats = 1; 1.501 + int formats[1]; 1.502 + HDC windowDC = wgl.GetWindowDC(); 1.503 + if (!wgl.fChoosePixelFormat(windowDC, 1.504 + attrs.Elements(), nullptr, 1.505 + numFormats, formats, &numFormats) 1.506 + || numFormats == 0) 1.507 + { 1.508 + return nullptr; 1.509 + } 1.510 + 1.511 + // We don't care; just pick the first one. 1.512 + int chosenFormat = formats[0]; 1.513 + if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize)) 1.514 + return nullptr; 1.515 + 1.516 + HANDLE pbuffer = wgl.fCreatePbuffer(windowDC, chosenFormat, 1.517 + aSize.width, aSize.height, 1.518 + pbattrs.Elements()); 1.519 + if (!pbuffer) { 1.520 + return nullptr; 1.521 + } 1.522 + 1.523 + HDC pbdc = wgl.fGetPbufferDC(pbuffer); 1.524 + NS_ASSERTION(pbdc, "expected a dc"); 1.525 + 1.526 + HGLRC context; 1.527 + if (wgl.HasRobustness()) { 1.528 + int attribs[] = { 1.529 + LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, 1.530 + LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 1.531 + 0 1.532 + }; 1.533 + 1.534 + context = wgl.fCreateContextAttribs(pbdc, aShareContext->Context(), attribs); 1.535 + } else { 1.536 + context = wgl.fCreateContext(pbdc); 1.537 + if (context && aShareContext) { 1.538 + if (!wgl.fShareLists(aShareContext->Context(), context)) { 1.539 + wgl.fDeleteContext(context); 1.540 + context = nullptr; 1.541 + printf_stderr("ERROR - creating pbuffer context failed because wglShareLists returned FALSE"); 1.542 + } 1.543 + } 1.544 + } 1.545 + 1.546 + if (!context) { 1.547 + wgl.fDestroyPbuffer(pbuffer); 1.548 + return nullptr; 1.549 + } 1.550 + 1.551 + SurfaceCaps dummyCaps = SurfaceCaps::Any(); 1.552 + nsRefPtr<GLContextWGL> glContext = new GLContextWGL(dummyCaps, 1.553 + aShareContext, 1.554 + true, 1.555 + pbuffer, 1.556 + pbdc, 1.557 + context, 1.558 + chosenFormat); 1.559 + 1.560 + return glContext.forget(); 1.561 +} 1.562 + 1.563 +static already_AddRefed<GLContextWGL> 1.564 +CreateWindowOffscreenContext() 1.565 +{ 1.566 + // CreateWindowOffscreenContext must return a global-shared context 1.567 + GLContextWGL *shareContext = GetGlobalContextWGL(); 1.568 + if (!shareContext) { 1.569 + return nullptr; 1.570 + } 1.571 + 1.572 + HDC dc; 1.573 + HWND win = sWGLLib.CreateDummyWindow(&dc); 1.574 + if (!win) { 1.575 + return nullptr; 1.576 + } 1.577 + 1.578 + HGLRC context = sWGLLib.fCreateContext(dc); 1.579 + if (sWGLLib.HasRobustness()) { 1.580 + int attribs[] = { 1.581 + LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, 1.582 + LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 1.583 + 0 1.584 + }; 1.585 + 1.586 + context = sWGLLib.fCreateContextAttribs(dc, shareContext->Context(), attribs); 1.587 + } else { 1.588 + context = sWGLLib.fCreateContext(dc); 1.589 + if (context && shareContext && 1.590 + !sWGLLib.fShareLists(shareContext->Context(), context)) 1.591 + { 1.592 + NS_WARNING("wglShareLists failed!"); 1.593 + 1.594 + sWGLLib.fDeleteContext(context); 1.595 + DestroyWindow(win); 1.596 + return nullptr; 1.597 + } 1.598 + } 1.599 + 1.600 + if (!context) { 1.601 + return nullptr; 1.602 + } 1.603 + 1.604 + SurfaceCaps caps = SurfaceCaps::ForRGBA(); 1.605 + nsRefPtr<GLContextWGL> glContext = new GLContextWGL(caps, 1.606 + shareContext, true, 1.607 + dc, context, win); 1.608 + 1.609 + return glContext.forget(); 1.610 +} 1.611 + 1.612 +already_AddRefed<GLContext> 1.613 +GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size, 1.614 + const SurfaceCaps& caps) 1.615 +{ 1.616 + if (!sWGLLib.EnsureInitialized()) { 1.617 + return nullptr; 1.618 + } 1.619 + 1.620 + nsRefPtr<GLContextWGL> glContext; 1.621 + 1.622 + // Always try to create a pbuffer context first, because we 1.623 + // want the context isolation. 1.624 + if (sWGLLib.fCreatePbuffer && 1.625 + sWGLLib.fChoosePixelFormat) 1.626 + { 1.627 + gfxIntSize dummySize = gfxIntSize(16, 16); 1.628 + glContext = CreatePBufferOffscreenContext(dummySize, GetGlobalContextWGL()); 1.629 + } 1.630 + 1.631 + // If it failed, then create a window context and use a FBO. 1.632 + if (!glContext) { 1.633 + glContext = CreateWindowOffscreenContext(); 1.634 + } 1.635 + 1.636 + if (!glContext || 1.637 + !glContext->Init()) 1.638 + { 1.639 + return nullptr; 1.640 + } 1.641 + 1.642 + if (!glContext->InitOffscreen(ToIntSize(size), caps)) 1.643 + return nullptr; 1.644 + 1.645 + return glContext.forget(); 1.646 +} 1.647 + 1.648 +static nsRefPtr<GLContextWGL> gGlobalContext; 1.649 + 1.650 +GLContext * 1.651 +GLContextProviderWGL::GetGlobalContext() 1.652 +{ 1.653 + if (!sWGLLib.EnsureInitialized()) { 1.654 + return nullptr; 1.655 + } 1.656 + 1.657 + static bool triedToCreateContext = false; 1.658 + 1.659 + if (!triedToCreateContext && !gGlobalContext) { 1.660 + triedToCreateContext = true; 1.661 + 1.662 + // conveniently, we already have what we need... 1.663 + SurfaceCaps dummyCaps = SurfaceCaps::Any(); 1.664 + gGlobalContext = new GLContextWGL(dummyCaps, 1.665 + nullptr, true, 1.666 + sWGLLib.GetWindowDC(), 1.667 + sWGLLib.GetWindowGLContext()); 1.668 + if (!gGlobalContext->Init()) { 1.669 + NS_WARNING("Global context GLContext initialization failed?"); 1.670 + gGlobalContext = nullptr; 1.671 + return nullptr; 1.672 + } 1.673 + } 1.674 + 1.675 + return static_cast<GLContext*>(gGlobalContext); 1.676 +} 1.677 + 1.678 +void 1.679 +GLContextProviderWGL::Shutdown() 1.680 +{ 1.681 + gGlobalContext = nullptr; 1.682 +} 1.683 + 1.684 +} /* namespace gl */ 1.685 +} /* namespace mozilla */