michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "GLContextProvider.h" michael@0: #include "GLContextWGL.h" michael@0: #include "GLLibraryLoader.h" michael@0: #include "nsDebug.h" michael@0: #include "nsIWidget.h" michael@0: #include "gfxPlatform.h" michael@0: #include "gfxWindowsSurface.h" michael@0: michael@0: #include "gfxCrashReporterUtils.h" michael@0: michael@0: #include "prenv.h" michael@0: michael@0: #include "mozilla/Preferences.h" michael@0: michael@0: using namespace mozilla::gfx; michael@0: michael@0: namespace mozilla { michael@0: namespace gl { michael@0: michael@0: WGLLibrary sWGLLib; michael@0: michael@0: HWND michael@0: WGLLibrary::CreateDummyWindow(HDC *aWindowDC) michael@0: { michael@0: WNDCLASSW wc; michael@0: if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) { michael@0: ZeroMemory(&wc, sizeof(WNDCLASSW)); michael@0: wc.style = CS_OWNDC; michael@0: wc.hInstance = GetModuleHandle(nullptr); michael@0: wc.lpfnWndProc = DefWindowProc; michael@0: wc.lpszClassName = L"GLContextWGLClass"; michael@0: if (!RegisterClassW(&wc)) { michael@0: NS_WARNING("Failed to register GLContextWGLClass?!"); michael@0: // er. failed to register our class? michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, michael@0: 0, 0, 16, 16, michael@0: nullptr, nullptr, GetModuleHandle(nullptr), michael@0: nullptr); michael@0: NS_ENSURE_TRUE(win, nullptr); michael@0: michael@0: HDC dc = GetDC(win); michael@0: NS_ENSURE_TRUE(dc, nullptr); michael@0: michael@0: if (mWindowPixelFormat == 0) { michael@0: PIXELFORMATDESCRIPTOR pfd; michael@0: ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); michael@0: pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); michael@0: pfd.nVersion = 1; michael@0: pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; michael@0: pfd.iPixelType = PFD_TYPE_RGBA; michael@0: pfd.cColorBits = 24; michael@0: pfd.cRedBits = 8; michael@0: pfd.cGreenBits = 8; michael@0: pfd.cBlueBits = 8; michael@0: pfd.cAlphaBits = 8; michael@0: pfd.cDepthBits = 0; michael@0: pfd.iLayerType = PFD_MAIN_PLANE; michael@0: michael@0: mWindowPixelFormat = ChoosePixelFormat(dc, &pfd); michael@0: } michael@0: michael@0: if (!mWindowPixelFormat || michael@0: !SetPixelFormat(dc, mWindowPixelFormat, nullptr)) michael@0: { michael@0: NS_WARNING("SetPixelFormat failed!"); michael@0: DestroyWindow(win); michael@0: return nullptr; michael@0: } michael@0: michael@0: if (aWindowDC) { michael@0: *aWindowDC = dc; michael@0: } michael@0: michael@0: return win; michael@0: } michael@0: michael@0: static inline bool michael@0: HasExtension(const char* aExtensions, const char* aRequiredExtension) michael@0: { michael@0: return GLContext::ListHasExtension( michael@0: reinterpret_cast(aExtensions), aRequiredExtension); michael@0: } michael@0: michael@0: bool michael@0: WGLLibrary::EnsureInitialized() michael@0: { michael@0: if (mInitialized) michael@0: return true; michael@0: michael@0: mozilla::ScopedGfxFeatureReporter reporter("WGL"); michael@0: michael@0: std::string libGLFilename = "Opengl32.dll"; michael@0: // SU_SPIES_DIRECTORY is for AMD CodeXL/gDEBugger michael@0: if (PR_GetEnv("SU_SPIES_DIRECTORY")) { michael@0: libGLFilename = std::string(PR_GetEnv("SU_SPIES_DIRECTORY")) + "\\opengl32.dll"; michael@0: } michael@0: michael@0: if (!mOGLLibrary) { michael@0: mOGLLibrary = PR_LoadLibrary(&libGLFilename[0]); michael@0: if (!mOGLLibrary) { michael@0: NS_WARNING("Couldn't load OpenGL library."); michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: GLLibraryLoader::SymLoadStruct earlySymbols[] = { michael@0: { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", nullptr } }, michael@0: { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", nullptr } }, michael@0: { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", nullptr } }, michael@0: { (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", nullptr } }, michael@0: { (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", nullptr } }, michael@0: { (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", nullptr } }, michael@0: { (PRFuncPtr*) &fShareLists, { "wglShareLists", nullptr } }, michael@0: { nullptr, { nullptr } } michael@0: }; michael@0: michael@0: if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) { michael@0: NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)"); michael@0: return false; michael@0: } michael@0: michael@0: // This is ridiculous -- we have to actually create a context to michael@0: // get the OpenGL ICD to load. michael@0: mWindow = CreateDummyWindow(&mWindowDC); michael@0: NS_ENSURE_TRUE(mWindow, false); michael@0: michael@0: // create rendering context michael@0: mWindowGLContext = fCreateContext(mWindowDC); michael@0: NS_ENSURE_TRUE(mWindowGLContext, false); michael@0: michael@0: HGLRC curCtx = fGetCurrentContext(); michael@0: HDC curDC = fGetCurrentDC(); michael@0: michael@0: if (!fMakeCurrent((HDC)mWindowDC, (HGLRC)mWindowGLContext)) { michael@0: NS_WARNING("wglMakeCurrent failed"); michael@0: return false; michael@0: } michael@0: michael@0: // Now we can grab all the other symbols that we couldn't without having michael@0: // a context current. michael@0: michael@0: GLLibraryLoader::SymLoadStruct pbufferSymbols[] = { michael@0: { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } }, michael@0: { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } }, michael@0: { (PRFuncPtr*) &fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", nullptr } }, michael@0: { (PRFuncPtr*) &fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } }, michael@0: { (PRFuncPtr*) &fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } }, michael@0: { nullptr, { nullptr } } michael@0: }; michael@0: michael@0: GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = { michael@0: { (PRFuncPtr*) &fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", nullptr } }, michael@0: { (PRFuncPtr*) &fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } }, michael@0: { nullptr, { nullptr } } michael@0: }; michael@0: michael@0: if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], michael@0: (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) michael@0: { michael@0: // this isn't an error, just means that pbuffers aren't supported michael@0: fCreatePbuffer = nullptr; michael@0: } michael@0: michael@0: if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], michael@0: (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) michael@0: { michael@0: // this isn't an error, just means that we don't have the pixel format extension michael@0: fChoosePixelFormat = nullptr; michael@0: } michael@0: michael@0: GLLibraryLoader::SymLoadStruct extensionsSymbols[] = { michael@0: { (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", nullptr} }, michael@0: { nullptr, { nullptr } } michael@0: }; michael@0: michael@0: GLLibraryLoader::SymLoadStruct robustnessSymbols[] = { michael@0: { (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", nullptr} }, michael@0: { nullptr, { nullptr } } michael@0: }; michael@0: michael@0: if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], michael@0: (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { michael@0: const char *wglExts = fGetExtensionsString(mWindowDC); michael@0: if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) { michael@0: GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], michael@0: (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress); michael@0: if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) { michael@0: mHasRobustness = true; michael@0: } michael@0: } michael@0: } michael@0: michael@0: // reset back to the previous context, just in case michael@0: fMakeCurrent(curDC, curCtx); michael@0: michael@0: if (mHasRobustness) { michael@0: fDeleteContext(mWindowGLContext); michael@0: michael@0: int attribs[] = { michael@0: LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, michael@0: LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, michael@0: 0 michael@0: }; michael@0: michael@0: mWindowGLContext = fCreateContextAttribs(mWindowDC, nullptr, attribs); michael@0: if (!mWindowGLContext) { michael@0: mHasRobustness = false; michael@0: mWindowGLContext = fCreateContext(mWindowDC); michael@0: } michael@0: } michael@0: michael@0: mInitialized = true; michael@0: michael@0: // Call this to create the global GLContext instance, michael@0: // and to check for errors. Note that this must happen /after/ michael@0: // setting mInitialized to TRUE, or an infinite loop results. michael@0: if (GLContextProviderWGL::GetGlobalContext() == nullptr) { michael@0: mInitialized = false; michael@0: return false; michael@0: } michael@0: michael@0: reporter.SetSuccessful(); michael@0: return true; michael@0: } michael@0: michael@0: GLContextWGL::GLContextWGL( michael@0: const SurfaceCaps& caps, michael@0: GLContext* sharedContext, michael@0: bool isOffscreen, michael@0: HDC aDC, michael@0: HGLRC aContext, michael@0: HWND aWindow) michael@0: : GLContext(caps, sharedContext, isOffscreen), michael@0: mDC(aDC), michael@0: mContext(aContext), michael@0: mWnd(aWindow), michael@0: mPBuffer(nullptr), michael@0: mPixelFormat(0), michael@0: mIsDoubleBuffered(false) michael@0: { michael@0: // See 899855 michael@0: SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); michael@0: } michael@0: michael@0: GLContextWGL::GLContextWGL( michael@0: const SurfaceCaps& caps, michael@0: GLContext* sharedContext, michael@0: bool isOffscreen, michael@0: HANDLE aPbuffer, michael@0: HDC aDC, michael@0: HGLRC aContext, michael@0: int aPixelFormat) michael@0: : GLContext(caps, sharedContext, isOffscreen), michael@0: mDC(aDC), michael@0: mContext(aContext), michael@0: mWnd(nullptr), michael@0: mPBuffer(aPbuffer), michael@0: mPixelFormat(aPixelFormat), michael@0: mIsDoubleBuffered(false) michael@0: { michael@0: // See 899855 michael@0: SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); michael@0: } michael@0: michael@0: GLContextWGL::~GLContextWGL() michael@0: { michael@0: MarkDestroyed(); michael@0: michael@0: sWGLLib.fDeleteContext(mContext); michael@0: michael@0: if (mPBuffer) michael@0: sWGLLib.fDestroyPbuffer(mPBuffer); michael@0: if (mWnd) michael@0: DestroyWindow(mWnd); michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::Init() michael@0: { michael@0: if (!mDC || !mContext) michael@0: return false; michael@0: michael@0: // see bug 929506 comment 29. wglGetProcAddress requires a current context. michael@0: if (!sWGLLib.fMakeCurrent(mDC, mContext)) michael@0: return false; michael@0: michael@0: SetupLookupFunction(); michael@0: if (!InitWithPrefix("gl", true)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::MakeCurrentImpl(bool aForce) michael@0: { michael@0: BOOL succeeded = true; michael@0: michael@0: // wglGetCurrentContext seems to just pull the HGLRC out michael@0: // of its TLS slot, so no need to do our own tls slot. michael@0: // You would think that wglMakeCurrent would avoid doing michael@0: // work if mContext was already current, but not so much.. michael@0: if (aForce || sWGLLib.fGetCurrentContext() != mContext) { michael@0: succeeded = sWGLLib.fMakeCurrent(mDC, mContext); michael@0: NS_ASSERTION(succeeded, "Failed to make GL context current!"); michael@0: } michael@0: michael@0: return succeeded; michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::IsCurrent() michael@0: { michael@0: return sWGLLib.fGetCurrentContext() == mContext; michael@0: } michael@0: michael@0: void michael@0: GLContextWGL::SetIsDoubleBuffered(bool aIsDB) michael@0: { michael@0: mIsDoubleBuffered = aIsDB; michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::IsDoubleBuffered() const michael@0: { michael@0: return mIsDoubleBuffered; michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::SupportsRobustness() const michael@0: { michael@0: return sWGLLib.HasRobustness(); michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::SwapBuffers() { michael@0: if (!mIsDoubleBuffered) michael@0: return false; michael@0: return ::SwapBuffers(mDC); michael@0: } michael@0: michael@0: bool michael@0: GLContextWGL::SetupLookupFunction() michael@0: { michael@0: // Make sure that we have a ref to the OGL library; michael@0: // when run under CodeXL, wglGetProcAddress won't return michael@0: // the right thing for some core functions. michael@0: MOZ_ASSERT(mLibrary == nullptr); michael@0: michael@0: mLibrary = sWGLLib.GetOGLLibrary(); michael@0: mLookupFunc = (PlatformLookupFunction)sWGLLib.fGetProcAddress; michael@0: return true; michael@0: } michael@0: michael@0: static bool michael@0: GetMaxSize(HDC hDC, int format, gfxIntSize& size) michael@0: { michael@0: int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB}; michael@0: int result[2]; michael@0: michael@0: // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues) michael@0: if (!sWGLLib.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result)) michael@0: return false; michael@0: michael@0: size.width = result[0]; michael@0: size.height = result[1]; michael@0: return true; michael@0: } michael@0: michael@0: static bool michael@0: IsValidSizeForFormat(HDC hDC, int format, michael@0: const gfxIntSize& requested) michael@0: { michael@0: gfxIntSize max; michael@0: if (!GetMaxSize(hDC, format, max)) michael@0: return true; michael@0: michael@0: if (requested.width > max.width) michael@0: return false; michael@0: if (requested.height > max.height) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static GLContextWGL * michael@0: GetGlobalContextWGL() michael@0: { michael@0: return static_cast(GLContextProviderWGL::GetGlobalContext()); michael@0: } michael@0: michael@0: already_AddRefed michael@0: GLContextProviderWGL::CreateWrappingExisting(void*, void*) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: already_AddRefed michael@0: GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget) michael@0: { michael@0: if (!sWGLLib.EnsureInitialized()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: /** michael@0: * We need to make sure we call SetPixelFormat -after- calling michael@0: * EnsureInitialized, otherwise it can load/unload the dll and michael@0: * wglCreateContext will fail. michael@0: */ michael@0: michael@0: HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC); michael@0: michael@0: SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr); michael@0: HGLRC context; michael@0: michael@0: GLContextWGL *shareContext = GetGlobalContextWGL(); michael@0: michael@0: if (sWGLLib.HasRobustness()) { michael@0: int attribs[] = { michael@0: LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, michael@0: LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, michael@0: 0 michael@0: }; michael@0: michael@0: context = sWGLLib.fCreateContextAttribs(dc, michael@0: shareContext ? shareContext->Context() : nullptr, michael@0: attribs); michael@0: } else { michael@0: context = sWGLLib.fCreateContext(dc); michael@0: if (context && michael@0: shareContext && michael@0: !sWGLLib.fShareLists(shareContext->Context(), context)) michael@0: { michael@0: printf_stderr("WGL context creation failed for window: wglShareLists returned false!"); michael@0: sWGLLib.fDeleteContext(context); michael@0: context = nullptr; michael@0: } michael@0: } michael@0: michael@0: if (!context) { michael@0: return nullptr; michael@0: } michael@0: michael@0: SurfaceCaps caps = SurfaceCaps::ForRGBA(); michael@0: nsRefPtr glContext = new GLContextWGL(caps, michael@0: shareContext, michael@0: false, michael@0: dc, michael@0: context); michael@0: if (!glContext->Init()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: glContext->SetIsDoubleBuffered(true); michael@0: michael@0: return glContext.forget(); michael@0: } michael@0: michael@0: static already_AddRefed michael@0: CreatePBufferOffscreenContext(const gfxIntSize& aSize, michael@0: GLContextWGL *aShareContext) michael@0: { michael@0: WGLLibrary& wgl = sWGLLib; michael@0: michael@0: #define A1(_a,_x) do { _a.AppendElement(_x); } while(0) michael@0: #define A2(_a,_x,_y) do { _a.AppendElement(_x); _a.AppendElement(_y); } while(0) michael@0: michael@0: nsTArray attrs; michael@0: michael@0: A2(attrs, LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE); michael@0: A2(attrs, LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE); michael@0: A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE); michael@0: michael@0: A2(attrs, LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB); michael@0: michael@0: A2(attrs, LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE); michael@0: A2(attrs, LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE); michael@0: michael@0: A1(attrs, 0); michael@0: michael@0: nsTArray pbattrs; michael@0: A1(pbattrs, 0); michael@0: michael@0: #undef A1 michael@0: #undef A2 michael@0: michael@0: // We only need one! michael@0: UINT numFormats = 1; michael@0: int formats[1]; michael@0: HDC windowDC = wgl.GetWindowDC(); michael@0: if (!wgl.fChoosePixelFormat(windowDC, michael@0: attrs.Elements(), nullptr, michael@0: numFormats, formats, &numFormats) michael@0: || numFormats == 0) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: // We don't care; just pick the first one. michael@0: int chosenFormat = formats[0]; michael@0: if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize)) michael@0: return nullptr; michael@0: michael@0: HANDLE pbuffer = wgl.fCreatePbuffer(windowDC, chosenFormat, michael@0: aSize.width, aSize.height, michael@0: pbattrs.Elements()); michael@0: if (!pbuffer) { michael@0: return nullptr; michael@0: } michael@0: michael@0: HDC pbdc = wgl.fGetPbufferDC(pbuffer); michael@0: NS_ASSERTION(pbdc, "expected a dc"); michael@0: michael@0: HGLRC context; michael@0: if (wgl.HasRobustness()) { michael@0: int attribs[] = { michael@0: LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, michael@0: LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, michael@0: 0 michael@0: }; michael@0: michael@0: context = wgl.fCreateContextAttribs(pbdc, aShareContext->Context(), attribs); michael@0: } else { michael@0: context = wgl.fCreateContext(pbdc); michael@0: if (context && aShareContext) { michael@0: if (!wgl.fShareLists(aShareContext->Context(), context)) { michael@0: wgl.fDeleteContext(context); michael@0: context = nullptr; michael@0: printf_stderr("ERROR - creating pbuffer context failed because wglShareLists returned FALSE"); michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (!context) { michael@0: wgl.fDestroyPbuffer(pbuffer); michael@0: return nullptr; michael@0: } michael@0: michael@0: SurfaceCaps dummyCaps = SurfaceCaps::Any(); michael@0: nsRefPtr glContext = new GLContextWGL(dummyCaps, michael@0: aShareContext, michael@0: true, michael@0: pbuffer, michael@0: pbdc, michael@0: context, michael@0: chosenFormat); michael@0: michael@0: return glContext.forget(); michael@0: } michael@0: michael@0: static already_AddRefed michael@0: CreateWindowOffscreenContext() michael@0: { michael@0: // CreateWindowOffscreenContext must return a global-shared context michael@0: GLContextWGL *shareContext = GetGlobalContextWGL(); michael@0: if (!shareContext) { michael@0: return nullptr; michael@0: } michael@0: michael@0: HDC dc; michael@0: HWND win = sWGLLib.CreateDummyWindow(&dc); michael@0: if (!win) { michael@0: return nullptr; michael@0: } michael@0: michael@0: HGLRC context = sWGLLib.fCreateContext(dc); michael@0: if (sWGLLib.HasRobustness()) { michael@0: int attribs[] = { michael@0: LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB, michael@0: LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, michael@0: 0 michael@0: }; michael@0: michael@0: context = sWGLLib.fCreateContextAttribs(dc, shareContext->Context(), attribs); michael@0: } else { michael@0: context = sWGLLib.fCreateContext(dc); michael@0: if (context && shareContext && michael@0: !sWGLLib.fShareLists(shareContext->Context(), context)) michael@0: { michael@0: NS_WARNING("wglShareLists failed!"); michael@0: michael@0: sWGLLib.fDeleteContext(context); michael@0: DestroyWindow(win); michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: if (!context) { michael@0: return nullptr; michael@0: } michael@0: michael@0: SurfaceCaps caps = SurfaceCaps::ForRGBA(); michael@0: nsRefPtr glContext = new GLContextWGL(caps, michael@0: shareContext, true, michael@0: dc, context, win); michael@0: michael@0: return glContext.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size, michael@0: const SurfaceCaps& caps) michael@0: { michael@0: if (!sWGLLib.EnsureInitialized()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr glContext; michael@0: michael@0: // Always try to create a pbuffer context first, because we michael@0: // want the context isolation. michael@0: if (sWGLLib.fCreatePbuffer && michael@0: sWGLLib.fChoosePixelFormat) michael@0: { michael@0: gfxIntSize dummySize = gfxIntSize(16, 16); michael@0: glContext = CreatePBufferOffscreenContext(dummySize, GetGlobalContextWGL()); michael@0: } michael@0: michael@0: // If it failed, then create a window context and use a FBO. michael@0: if (!glContext) { michael@0: glContext = CreateWindowOffscreenContext(); michael@0: } michael@0: michael@0: if (!glContext || michael@0: !glContext->Init()) michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!glContext->InitOffscreen(ToIntSize(size), caps)) michael@0: return nullptr; michael@0: michael@0: return glContext.forget(); michael@0: } michael@0: michael@0: static nsRefPtr gGlobalContext; michael@0: michael@0: GLContext * michael@0: GLContextProviderWGL::GetGlobalContext() michael@0: { michael@0: if (!sWGLLib.EnsureInitialized()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: static bool triedToCreateContext = false; michael@0: michael@0: if (!triedToCreateContext && !gGlobalContext) { michael@0: triedToCreateContext = true; michael@0: michael@0: // conveniently, we already have what we need... michael@0: SurfaceCaps dummyCaps = SurfaceCaps::Any(); michael@0: gGlobalContext = new GLContextWGL(dummyCaps, michael@0: nullptr, true, michael@0: sWGLLib.GetWindowDC(), michael@0: sWGLLib.GetWindowGLContext()); michael@0: if (!gGlobalContext->Init()) { michael@0: NS_WARNING("Global context GLContext initialization failed?"); michael@0: gGlobalContext = nullptr; michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: return static_cast(gGlobalContext); michael@0: } michael@0: michael@0: void michael@0: GLContextProviderWGL::Shutdown() michael@0: { michael@0: gGlobalContext = nullptr; michael@0: } michael@0: michael@0: } /* namespace gl */ michael@0: } /* namespace mozilla */