Webgl Opengl fix

This commit is contained in:
Fedor 2024-05-04 16:30:54 +03:00
parent 32172d9123
commit 3e5993cc08
4 changed files with 356 additions and 366 deletions

View File

@ -32,21 +32,10 @@ using namespace mozilla::widget;
WGLLibrary sWGLLib;
/*
ScopedWindow::~ScopedWindow()
{
if (mDC) {
MOZ_ALWAYS_TRUE( ReleaseDC(mDC) );
}
if (mWindow) {
MOZ_ALWAYS_TRUE( DestroyWindow(mWindow) );
}
}
*/
static HWND CreateDummyWindow() {
WNDCLASSW wc{};
HWND WGLLibrary::CreateDummyWindow(HDC* aWindowDC) {
WNDCLASSW wc;
if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) {
wc = {};
ZeroMemory(&wc, sizeof(WNDCLASSW));
wc.style = CS_OWNDC;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpfnWndProc = DefWindowProc;
@ -58,8 +47,43 @@ static HWND CreateDummyWindow() {
}
}
return CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, 0, 0, 1, 1,
nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
HWND win =
CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, 0, 0, 16, 16,
nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
NS_ENSURE_TRUE(win, nullptr);
HDC dc = GetDC(win);
NS_ENSURE_TRUE(dc, nullptr);
if (mWindowPixelFormat == 0) {
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = gfxVars::UseWebRender() ? 24 : 0;
pfd.iLayerType = PFD_MAIN_PLANE;
mWindowPixelFormat = ChoosePixelFormat(dc, &pfd);
}
if (!mWindowPixelFormat || !SetPixelFormat(dc, mWindowPixelFormat, nullptr)) {
NS_WARNING("SetPixelFormat failed!");
DestroyWindow(win);
return nullptr;
}
if (aWindowDC) {
*aWindowDC = dc;
}
return win;
}
static inline bool HasExtension(const char* aExtensions,
@ -119,129 +143,124 @@ bool WGLLibrary::EnsureInitialized() {
}
}
mDummyWindow = CreateDummyWindow();
MOZ_ASSERT(mDummyWindow);
if (!mDummyWindow) return false;
auto cleanup = MakeScopeExit([&]() { Reset(); });
mRootDc = GetDC(mDummyWindow);
MOZ_ASSERT(mRootDc);
if (!mRootDc) return false;
// --
{
PIXELFORMATDESCRIPTOR pfd{};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
// pfd.iPixelType = PFD_TYPE_RGBA;
// pfd.cColorBits = 24;
// pfd.cRedBits = 8;
// pfd.cGreenBits = 8;
// pfd.cBlueBits = 8;
// pfd.cAlphaBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
const auto pixelFormat = ChoosePixelFormat(mRootDc, &pfd);
MOZ_ASSERT(pixelFormat);
if (!pixelFormat) return false;
const bool setPixelFormatOk = SetPixelFormat(mRootDc, pixelFormat, nullptr);
MOZ_ASSERT(setPixelFormatOk);
if (!setPixelFormatOk) return false;
}
// --
// This is ridiculous -- we have to actually create a context to
// get the OpenGL ICD to load.
mWindow = CreateDummyWindow(&mWindowDC);
NS_ENSURE_TRUE(mWindow, false);
// create rendering context
mDummyGlrc = mSymbols.fCreateContext(mRootDc);
if (!mDummyGlrc) return false;
mWindowGLContext = mSymbols.fCreateContext(mWindowDC);
NS_ENSURE_TRUE(mWindowGLContext, false);
const auto curCtx = mSymbols.fGetCurrentContext();
const auto curDC = mSymbols.fGetCurrentDC();
if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) {
if (!mSymbols.fMakeCurrent(mWindowDC, mWindowGLContext)) {
NS_WARNING("wglMakeCurrent failed");
return false;
}
const auto resetContext =
MakeScopeExit([&]() { mSymbols.fMakeCurrent(curDC, curCtx); });
const auto loader = GetSymbolLoader();
const auto& curCtx = mSymbols.fGetCurrentContext();
const auto& curDC = mSymbols.fGetCurrentDC();
const auto& loader = GetSymbolLoader();
// Now we can grab all the other symbols that we couldn't without having
// a context current.
// clang-format off
const SymLoadStruct reqExtSymbols[] = {
const SymLoadStruct pbufferSymbols[] = {
{ (PRFuncPtr*)&mSymbols.fCreatePbuffer, {{ "wglCreatePbufferARB", "wglCreatePbufferEXT" }} },
{ (PRFuncPtr*)&mSymbols.fDestroyPbuffer, {{ "wglDestroyPbufferARB", "wglDestroyPbufferEXT" }} },
{ (PRFuncPtr*)&mSymbols.fGetPbufferDC, {{ "wglGetPbufferDCARB", "wglGetPbufferDCEXT" }} },
{ (PRFuncPtr*)&mSymbols.fReleasePbufferDC, {{ "wglReleasePbufferDCARB", "wglReleasePbufferDCEXT" }} },
// { (PRFuncPtr*)&mSymbols.fBindTexImage, {{ "wglBindTexImageARB", "wglBindTexImageEXT" }} },
// { (PRFuncPtr*)&mSymbols.fReleaseTexImage, {{ "wglReleaseTexImageARB", "wglReleaseTexImageEXT" }} },
{ (PRFuncPtr*)&mSymbols.fBindTexImage, {{ "wglBindTexImageARB", "wglBindTexImageEXT" }} },
{ (PRFuncPtr*)&mSymbols.fReleaseTexImage, {{ "wglReleaseTexImageARB", "wglReleaseTexImageEXT" }} },
END_OF_SYMBOLS
};
const SymLoadStruct pixFmtSymbols[] = {
{ (PRFuncPtr*)&mSymbols.fChoosePixelFormat, {{ "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT" }} },
// { (PRFuncPtr*)&mSymbols.fGetPixelFormatAttribiv, {{ "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT" }} },
SYMBOL(GetExtensionsStringARB),
{ (PRFuncPtr*)&mSymbols.fGetPixelFormatAttribiv, {{ "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT" }} },
END_OF_SYMBOLS
};
// clang-format on
if (!loader.LoadSymbols(reqExtSymbols)) {
NS_WARNING("reqExtSymbols missing");
return false;
if (!loader.LoadSymbols(pbufferSymbols)) {
// this isn't an error, just means that pbuffers aren't supported
ClearSymbols(pbufferSymbols);
}
// --
if (!loader.LoadSymbols(pixFmtSymbols)) {
// this isn't an error, just means that we don't have the pixel format
// extension
ClearSymbols(pixFmtSymbols);
}
const auto extString = mSymbols.fGetExtensionsStringARB(mRootDc);
MOZ_ASSERT(extString);
MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string"));
const SymLoadStruct extensionsSymbols[] = {SYMBOL(GetExtensionsStringARB),
END_OF_SYMBOLS};
// --
const SymLoadStruct robustnessSymbols[] = {SYMBOL(CreateContextAttribsARB),
END_OF_SYMBOLS};
if (HasExtension(extString, "WGL_ARB_create_context")) {
const SymLoadStruct createContextSymbols[] = {
SYMBOL(CreateContextAttribsARB), END_OF_SYMBOLS};
if (loader.LoadSymbols(createContextSymbols)) {
if (HasExtension(extString, "WGL_ARB_create_context_robustness")) {
mHasRobustness = true;
const SymLoadStruct dxInteropSymbols[] = {SYMBOL(DXSetResourceShareHandleNV),
SYMBOL(DXOpenDeviceNV),
SYMBOL(DXCloseDeviceNV),
SYMBOL(DXRegisterObjectNV),
SYMBOL(DXUnregisterObjectNV),
SYMBOL(DXObjectAccessNV),
SYMBOL(DXLockObjectsNV),
SYMBOL(DXUnlockObjectsNV),
END_OF_SYMBOLS};
if (loader.LoadSymbols(extensionsSymbols)) {
const char* extString = mSymbols.fGetExtensionsStringARB(mWindowDC);
MOZ_ASSERT(extString);
MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string"));
if (HasExtension(extString, "WGL_ARB_create_context")) {
if (loader.LoadSymbols(robustnessSymbols)) {
if (HasExtension(extString, "WGL_ARB_create_context_robustness")) {
mHasRobustness = true;
}
} else {
NS_ERROR(
"WGL supports ARB_create_context without supplying its functions.");
ClearSymbols(robustnessSymbols);
}
}
////
bool hasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2");
if (gfxVars::DXInterop2Blocked() &&
!StaticPrefs::gl_ignore_dx_interop2_blacklist()) {
hasDXInterop2 = false;
}
if (hasDXInterop2) {
if (!loader.LoadSymbols(dxInteropSymbols)) {
NS_ERROR(
"WGL supports NV_DX_interop(2) without supplying its functions.");
ClearSymbols(dxInteropSymbols);
}
} else {
NS_ERROR(
"WGL_ARB_create_context announced without supplying its functions.");
ClearSymbols(createContextSymbols);
}
}
// --
// reset back to the previous context, just in case
mSymbols.fMakeCurrent(curDC, curCtx);
bool hasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2");
if (gfxVars::DXInterop2Blocked() &&
!StaticPrefs::gl_ignore_dx_interop2_blacklist()) {
hasDXInterop2 = false;
}
if (mHasRobustness) {
mSymbols.fDeleteContext(mWindowGLContext);
if (hasDXInterop2) {
const SymLoadStruct dxInteropSymbols[] = {
SYMBOL(DXSetResourceShareHandleNV),
SYMBOL(DXOpenDeviceNV),
SYMBOL(DXCloseDeviceNV),
SYMBOL(DXRegisterObjectNV),
SYMBOL(DXUnregisterObjectNV),
SYMBOL(DXObjectAccessNV),
SYMBOL(DXLockObjectsNV),
SYMBOL(DXUnlockObjectsNV),
END_OF_SYMBOLS};
if (!loader.LoadSymbols(dxInteropSymbols)) {
NS_ERROR(
"WGL_NV_DX_interop2 announceed without supplying its functions.");
ClearSymbols(dxInteropSymbols);
const int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
mWindowGLContext =
mSymbols.fCreateContextAttribsARB(mWindowDC, nullptr, attribs);
if (!mWindowGLContext) {
mHasRobustness = false;
mWindowGLContext = mSymbols.fCreateContext(mWindowDC);
}
}
// --
cleanup.release();
mInitialized = true;
reporter.SetSuccessful();
@ -251,21 +270,6 @@ bool WGLLibrary::EnsureInitialized() {
#undef SYMBOL
#undef END_OF_SYMBOLS
void WGLLibrary::Reset() {
if (mDummyGlrc) {
(void)mSymbols.fDeleteContext(mDummyGlrc);
mDummyGlrc = nullptr;
}
if (mRootDc) {
(void)ReleaseDC(mDummyWindow, mRootDc);
mRootDc = nullptr;
}
if (mDummyWindow) {
(void)DestroyWindow(mDummyWindow);
mDummyWindow = nullptr;
}
}
GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps,
bool isOffscreen, HDC aDC, HGLRC aContext,
HWND aWindow)
@ -289,16 +293,10 @@ GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps,
GLContextWGL::~GLContextWGL() {
MarkDestroyed();
(void)sWGLLib.mSymbols.fDeleteContext(mContext);
sWGLLib.mSymbols.fDeleteContext(mContext);
if (mPBuffer) {
(void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC);
(void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
}
if (mWnd) {
(void)ReleaseDC(mWnd, mDC);
DestroyWindow(mWnd);
}
if (mPBuffer) sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
if (mWnd) DestroyWindow(mWnd);
}
bool GLContextWGL::MakeCurrentImpl() const {
@ -311,6 +309,12 @@ bool GLContextWGL::IsCurrentImpl() const {
return sWGLLib.mSymbols.fGetCurrentContext() == mContext;
}
void GLContextWGL::SetIsDoubleBuffered(bool aIsDB) {
mIsDoubleBuffered = aIsDB;
}
bool GLContextWGL::IsDoubleBuffered() const { return mIsDoubleBuffered; }
bool GLContextWGL::SwapBuffers() {
if (!mIsDoubleBuffered) return false;
return ::SwapBuffers(mDC);
@ -321,145 +325,80 @@ void GLContextWGL::GetWSIInfo(nsCString* const out) const {
out->Append(sWGLLib.mSymbols.fGetExtensionsStringARB(mDC));
}
static bool GetMaxSize(HDC hDC, int format, IntSize& size) {
int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB,
LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB};
int result[2];
// (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int*
// piAttributes, int* piValues)
if (!sWGLLib.mSymbols.fGetPixelFormatAttribiv(hDC, format, 0, 2, query,
result))
return false;
size.width = result[0];
size.height = result[1];
return true;
}
static bool IsValidSizeForFormat(HDC hDC, int format,
const IntSize& requested) {
IntSize max;
if (!GetMaxSize(hDC, format, max)) return true;
if (requested.width > max.width) return false;
if (requested.height > max.height) return false;
return true;
} // namespace gl
already_AddRefed<GLContext> GLContextProviderWGL::CreateWrappingExisting(
void*, void*) {
return nullptr;
}
HGLRC
WGLLibrary::CreateContextWithFallback(const HDC dc,
const bool tryRobustBuffers) const {
if (mHasRobustness) {
if (tryRobustBuffers) {
const int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
const auto context =
mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
if (context) return context;
}
const int attribs[] = {LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
const auto context =
mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
if (context) return context;
already_AddRefed<GLContext> CreateForWidget(HWND aHwnd,
#ifdef MOZ_BUILD_WEBRENDER
bool aWebRender,
#endif
bool aForceAccelerated) {
if (!sWGLLib.EnsureInitialized()) {
return nullptr;
}
if (mSymbols.fCreateContextAttribsARB) {
const auto context =
mSymbols.fCreateContextAttribsARB(dc, nullptr, nullptr);
if (context) return context;
/**
* We need to make sure we call SetPixelFormat -after- calling
* EnsureInitialized, otherwise it can load/unload the dll and
* wglCreateContext will fail.
*/
HDC dc = ::GetDC(aHwnd);
SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr);
HGLRC context;
if (sWGLLib.HasRobustness()) {
int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
context = sWGLLib.mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
} else {
context = sWGLLib.mSymbols.fCreateContext(dc);
}
return mSymbols.fCreateContext(dc);
}
static RefPtr<GLContext> CreateForWidget(const HWND window,
#ifdef MOZ_BUILD_WEBRENDER
const bool isWebRender,
#endif
const bool requireAccelerated) {
auto& wgl = sWGLLib;
if (!wgl.EnsureInitialized()) return nullptr;
const auto dc = GetDC(window);
if (!dc) return nullptr;
auto cleanupDc = MakeScopeExit([&]() { (void)ReleaseDC(window, dc); });
int chosenFormat;
UINT foundFormats = 0;
if (!foundFormats) {
const int kAttribs[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
true,
LOCAL_WGL_SUPPORT_OPENGL_ARB,
true,
LOCAL_WGL_DOUBLE_BUFFER_ARB,
true,
LOCAL_WGL_ACCELERATION_ARB,
LOCAL_WGL_FULL_ACCELERATION_ARB,
0};
const int* attribs;
#ifdef MOZ_BUILD_WEBRENDER
const int kAttribsForWebRender[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
true,
LOCAL_WGL_SUPPORT_OPENGL_ARB,
true,
LOCAL_WGL_DOUBLE_BUFFER_ARB,
true,
LOCAL_WGL_DEPTH_BITS_ARB,
24,
LOCAL_WGL_ACCELERATION_ARB,
LOCAL_WGL_FULL_ACCELERATION_ARB,
0};
if (wr::RenderThread::IsInRenderThread()) {
attribs = kAttribsForWebRender;
} else {
#endif
attribs = kAttribs;
#ifdef MOZ_BUILD_WEBRENDER
}
#endif
if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), attribs, nullptr, 1,
&chosenFormat, &foundFormats)) {
foundFormats = 0;
}
}
if (!foundFormats) {
if (requireAccelerated) return nullptr;
const int kAttribs[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
true,
LOCAL_WGL_SUPPORT_OPENGL_ARB,
true,
LOCAL_WGL_DOUBLE_BUFFER_ARB,
true,
0};
const int* attribs;
#ifdef MOZ_BUILD_WEBRENDER
const int kAttribsForWebRender[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
true,
LOCAL_WGL_SUPPORT_OPENGL_ARB,
true,
LOCAL_WGL_DOUBLE_BUFFER_ARB,
true,
LOCAL_WGL_DEPTH_BITS_ARB,
24,
0};
if (wr::RenderThread::IsInRenderThread()) {
attribs = kAttribsForWebRender;
} else {
#endif
attribs = kAttribs;
#ifdef MOZ_BUILD_WEBRENDER
}
#endif
if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), attribs, nullptr, 1,
&chosenFormat, &foundFormats)) {
foundFormats = 0;
}
}
if (!foundFormats) return nullptr;
// We need to make sure we call SetPixelFormat -after- calling
// EnsureInitialized, otherwise it can load/unload the dll and
// wglCreateContext will fail.
SetPixelFormat(dc, chosenFormat, nullptr);
const auto context = sWGLLib.CreateContextWithFallback(dc, false);
if (!context) return nullptr;
SurfaceCaps caps = SurfaceCaps::ForRGBA();
const RefPtr<GLContextWGL> gl = new GLContextWGL(
CreateContextFlags::NONE, SurfaceCaps::ForRGBA(), false, dc, context);
cleanupDc.release();
gl->mIsDoubleBuffered = true;
if (!gl->Init()) return nullptr;
RefPtr<GLContextWGL> glContext =
new GLContextWGL(CreateContextFlags::NONE, caps, false, dc, context);
if (!glContext->Init()) {
return nullptr;
}
return gl;
glContext->SetIsDoubleBuffered(true);
return glContext.forget();
}
already_AddRefed<GLContext> GLContextProviderWGL::CreateForCompositorWidget(
@ -476,8 +415,7 @@ already_AddRefed<GLContext> GLContextProviderWGL::CreateForCompositorWidget(
#ifdef MOZ_BUILD_WEBRENDER
aWebRender,
#endif
aForceAccelerated)
.forget();
aForceAccelerated);
}
already_AddRefed<GLContext> GLContextProviderWGL::CreateForWindow(
@ -490,77 +428,141 @@ already_AddRefed<GLContext> GLContextProviderWGL::CreateForWindow(
#ifdef MOZ_BUILD_WEBRENDER
aWebRender,
#endif
aForceAccelerated)
.forget();
aForceAccelerated);
}
/*static*/
already_AddRefed<GLContext> GLContextProviderWGL::CreateHeadless(
const CreateContextFlags flags, nsACString* const out_failureId) {
auto& wgl = sWGLLib;
if (!wgl.EnsureInitialized()) return nullptr;
static already_AddRefed<GLContextWGL> CreatePBufferOffscreenContext(
CreateContextFlags flags, const IntSize& aSize) {
WGLLibrary& wgl = sWGLLib;
int chosenFormat;
UINT foundFormats = 0;
const int pfAttribs[] = {LOCAL_WGL_SUPPORT_OPENGL_ARB,
LOCAL_GL_TRUE,
LOCAL_WGL_ACCELERATION_ARB,
LOCAL_WGL_FULL_ACCELERATION_ARB,
if (!foundFormats) {
const int kAttribs[] = {LOCAL_WGL_DRAW_TO_PBUFFER_ARB,
true,
LOCAL_WGL_SUPPORT_OPENGL_ARB,
true,
LOCAL_WGL_ACCELERATION_ARB,
LOCAL_WGL_FULL_ACCELERATION_ARB,
0};
if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
&chosenFormat, &foundFormats)) {
foundFormats = 0;
}
LOCAL_WGL_DRAW_TO_PBUFFER_ARB,
LOCAL_GL_TRUE,
LOCAL_WGL_DOUBLE_BUFFER_ARB,
LOCAL_GL_FALSE,
LOCAL_WGL_STEREO_ARB,
LOCAL_GL_FALSE,
0};
// We only need one!
static const uint32_t kMaxFormats = 1024;
int formats[kMaxFormats];
uint32_t foundFormats;
HDC windowDC = wgl.GetWindowDC();
if (!wgl.mSymbols.fChoosePixelFormat(windowDC, pfAttribs, nullptr,
kMaxFormats, formats, &foundFormats) ||
foundFormats == 0) {
return nullptr;
}
if (!foundFormats) {
const int kAttribs[] = {LOCAL_WGL_DRAW_TO_PBUFFER_ARB, true,
LOCAL_WGL_SUPPORT_OPENGL_ARB, true, 0};
if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
&chosenFormat, &foundFormats)) {
foundFormats = 0;
}
// We don't care; just pick the first one.
int chosenFormat = formats[0];
if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize)) return nullptr;
const int pbAttribs[] = {0};
HANDLE pbuffer = wgl.mSymbols.fCreatePbuffer(
windowDC, chosenFormat, aSize.width, aSize.height, pbAttribs);
if (!pbuffer) {
return nullptr;
}
if (!foundFormats) return nullptr;
const int kPbufferAttribs[] = {0};
const auto pbuffer = wgl.mSymbols.fCreatePbuffer(wgl.RootDc(), chosenFormat,
1, 1, kPbufferAttribs);
if (!pbuffer) return nullptr;
auto cleanupPbuffer =
MakeScopeExit([&]() { (void)wgl.mSymbols.fDestroyPbuffer(pbuffer); });
const auto dc = wgl.mSymbols.fGetPbufferDC(pbuffer);
if (!dc) return nullptr;
auto cleanupDc = MakeScopeExit(
[&]() { (void)wgl.mSymbols.fReleasePbufferDC(pbuffer, dc); });
HDC pbdc = wgl.mSymbols.fGetPbufferDC(pbuffer);
NS_ASSERTION(pbdc, "expected a dc");
const auto context = wgl.CreateContextWithFallback(dc, true);
if (!context) return nullptr;
HGLRC context;
if (wgl.HasRobustness()) {
const int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
context = wgl.mSymbols.fCreateContextAttribsARB(pbdc, nullptr, attribs);
} else {
context = wgl.mSymbols.fCreateContext(pbdc);
}
const bool isOffscreen = true;
const RefPtr<GLContextWGL> gl =
new GLContextWGL(flags, SurfaceCaps::Any(), isOffscreen, pbuffer, dc,
context, chosenFormat);
cleanupPbuffer.release();
cleanupDc.release();
if (!gl->Init()) return nullptr;
if (!context) {
wgl.mSymbols.fDestroyPbuffer(pbuffer);
return nullptr;
}
return RefPtr<GLContext>(gl.get()).forget();
SurfaceCaps dummyCaps = SurfaceCaps::Any();
RefPtr<GLContextWGL> glContext = new GLContextWGL(
flags, dummyCaps, true, pbuffer, pbdc, context, chosenFormat);
return glContext.forget();
}
static already_AddRefed<GLContextWGL> CreateWindowOffscreenContext() {
HDC dc;
HWND win = sWGLLib.CreateDummyWindow(&dc);
if (!win) {
return nullptr;
}
HGLRC context = sWGLLib.mSymbols.fCreateContext(dc);
if (sWGLLib.HasRobustness()) {
int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
context = sWGLLib.mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
} else {
context = sWGLLib.mSymbols.fCreateContext(dc);
}
if (!context) {
}
SurfaceCaps caps = SurfaceCaps::ForRGBA();
RefPtr<GLContextWGL> glContext =
new GLContextWGL(CreateContextFlags::NONE, caps, true, dc, context, win);
return glContext.forget();
}
/*static*/ already_AddRefed<GLContext> GLContextProviderWGL::CreateHeadless(
CreateContextFlags flags, nsACString* const out_failureId) {
if (!sWGLLib.EnsureInitialized()) {
return nullptr;
}
RefPtr<GLContextWGL> glContext;
// Always try to create a pbuffer context first, because we
// want the context isolation.
if (sWGLLib.mSymbols.fCreatePbuffer && sWGLLib.mSymbols.fChoosePixelFormat) {
IntSize dummySize = IntSize(16, 16);
glContext = CreatePBufferOffscreenContext(flags, dummySize);
}
// If it failed, then create a window context and use a FBO.
if (!glContext) {
glContext = CreateWindowOffscreenContext();
}
if (!glContext || !glContext->Init()) {
return nullptr;
}
RefPtr<GLContext> retGL = glContext.get();
return retGL.forget();
}
/*static*/
already_AddRefed<GLContext> GLContextProviderWGL::CreateOffscreen(
const IntSize& size, const SurfaceCaps& minCaps, CreateContextFlags flags,
nsACString* const out_failureId) {
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT");
RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId);
if (!gl) return nullptr;
if (!gl->InitOffscreen(size, minCaps)) return nullptr;
if (!gl->InitOffscreen(size, minCaps)) {
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT");
return nullptr;
}
return gl.forget();
}
@ -571,5 +573,5 @@ GLContext* GLContextProviderWGL::GetGlobalContext() { return nullptr; }
/*static*/
void GLContextProviderWGL::Shutdown() {}
} /* namespace gl */
} // namespace gl
} /* namespace mozilla */

View File

@ -11,7 +11,7 @@
namespace mozilla {
namespace gl {
class GLContextWGL final : public GLContext {
class GLContextWGL : public GLContext {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextWGL, override)
// From Window: (possibly for offscreen!)
@ -30,10 +30,21 @@ class GLContextWGL final : public GLContext {
return GLContextType::WGL;
}
static GLContextWGL* Cast(GLContext* gl) {
MOZ_ASSERT(gl->GetContextType() == GLContextType::WGL);
return static_cast<GLContextWGL*>(gl);
}
virtual bool MakeCurrentImpl() const override;
virtual bool IsCurrentImpl() const override;
virtual bool IsDoubleBuffered() const override { return mIsDoubleBuffered; }
void SetIsDoubleBuffered(bool aIsDB);
virtual bool IsDoubleBuffered() const override;
virtual bool SwapBuffers() override;
virtual void GetWSIInfo(nsCString* const out) const override;
Maybe<SymbolLoader> GetSymbolLoader() const override {
@ -51,7 +62,6 @@ class GLContextWGL final : public GLContext {
HANDLE mPBuffer;
int mPixelFormat;
public:
bool mIsDoubleBuffered = false;
};

View File

@ -4,46 +4,23 @@
#include "GLContextTypes.h"
#include "GLLibraryLoader.h"
#include "mozilla/UniquePtr.h"
#include <windows.h>
struct PRLibrary;
namespace mozilla {
namespace gl {
/*
struct ScopedDC
{
const HDC mDC;
ScopedDC() = delete;
virtual ~ScopedDC() = 0;
};
struct WindowDC final : public ScopedDC
{
const HWND mWindow;
WindowDC() = delete;
~WindowDC();
};
struct PBufferDC final : public ScopedDC
{
const HWND mWindow;
PBufferDC() = delete;
~PBufferDC();
};
*/
class WGLLibrary {
public:
~WGLLibrary() { Reset(); }
WGLLibrary()
: mInitialized(false),
mHasRobustness(false),
mWindow(0),
mWindowDC(0),
mWindowGLContext(0),
mWindowPixelFormat(0) {}
private:
void Reset();
public:
struct {
HGLRC(GLAPIENTRY* fCreateContext)(HDC);
BOOL(GLAPIENTRY* fDeleteContext)(HGLRC);
@ -51,24 +28,20 @@ class WGLLibrary {
PROC(GLAPIENTRY* fGetProcAddress)(LPCSTR);
HGLRC(GLAPIENTRY* fGetCurrentContext)(void);
HDC(GLAPIENTRY* fGetCurrentDC)(void);
// BOOL (GLAPIENTRY * fShareLists) (HGLRC oldContext, HGLRC newContext);
BOOL(GLAPIENTRY* fShareLists)(HGLRC oldContext, HGLRC newContext);
HANDLE(GLAPIENTRY* fCreatePbuffer)
(HDC hDC, int iPixelFormat, int iWidth, int iHeight,
const int* piAttribList);
BOOL(GLAPIENTRY* fDestroyPbuffer)(HANDLE hPbuffer);
HDC(GLAPIENTRY* fGetPbufferDC)(HANDLE hPbuffer);
int(GLAPIENTRY* fReleasePbufferDC)(HANDLE hPbuffer, HDC dc);
// BOOL (GLAPIENTRY * fBindTexImage) (HANDLE hPbuffer, int iBuffer);
// BOOL (GLAPIENTRY * fReleaseTexImage) (HANDLE hPbuffer, int iBuffer);
BOOL(GLAPIENTRY* fBindTexImage)(HANDLE hPbuffer, int iBuffer);
BOOL(GLAPIENTRY* fReleaseTexImage)(HANDLE hPbuffer, int iBuffer);
BOOL(GLAPIENTRY* fChoosePixelFormat)
(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList,
UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
// BOOL (GLAPIENTRY * fGetPixelFormatAttribiv) (HDC hdc,
// int iPixelFormat,
// int iLayerPlane,
// UINT nAttributes,
// int* piAttributes,
// int* piValues);
BOOL(GLAPIENTRY* fGetPixelFormatAttribiv)
(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes,
int* piAttributes, int* piValues);
const char*(GLAPIENTRY* fGetExtensionsStringARB)(HDC hdc);
HGLRC(GLAPIENTRY* fCreateContextAttribsARB)
(HDC hdc, HGLRC hShareContext, const int* attribList);
@ -88,22 +61,27 @@ class WGLLibrary {
} mSymbols = {};
bool EnsureInitialized();
// UniquePtr<WindowDC> CreateDummyWindow();
HGLRC CreateContextWithFallback(HDC dc, bool tryRobustBuffers) const;
HWND CreateDummyWindow(HDC* aWindowDC = nullptr);
bool HasRobustness() const { return mHasRobustness; }
bool HasDXInterop2() const { return bool(mSymbols.fDXOpenDeviceNV); }
bool IsInitialized() const { return mInitialized; }
auto GetOGLLibrary() const { return mOGLLibrary; }
auto RootDc() const { return mRootDc; }
SymbolLoader GetSymbolLoader() const;
HWND GetWindow() const { return mWindow; }
HDC GetWindowDC() const { return mWindowDC; }
HGLRC GetWindowGLContext() const { return mWindowGLContext; }
int GetWindowPixelFormat() const { return mWindowPixelFormat; }
PRLibrary* GetOGLLibrary() { return mOGLLibrary; }
private:
bool mInitialized = false;
bool mInitialized;
PRLibrary* mOGLLibrary;
bool mHasRobustness;
HWND mDummyWindow;
HDC mRootDc;
HGLRC mDummyGlrc;
HWND mWindow;
HDC mWindowDC;
HGLRC mWindowGLContext;
int mWindowPixelFormat;
};
// a global WGLLibrary instance

View File

@ -7376,7 +7376,7 @@
- name: webgl.disable-angle
type: RelaxedAtomicBool
value: false
value: true
mirror: always
- name: webgl.disable-wgl
@ -7441,7 +7441,7 @@
- name: webgl.force-enabled
type: RelaxedAtomicBool
value: false
value: true
mirror: always
- name: webgl.force-layers-readback