Bug 1276732 - Report the GLContext error to WebGL for telemetry. r=jrmuizel

MozReview-Commit-ID: 24eb4FXMOiI
This commit is contained in:
Benoit Girard
2016-06-06 16:52:42 -04:00
parent 70ed486797
commit fa721f31b7
16 changed files with 127 additions and 58 deletions

View File

@@ -587,7 +587,7 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
{ {
const gfx::IntSize dummySize(16, 16); const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps, RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
flags); flags, *out_failureId);
if (gl && gl->IsANGLE()) { if (gl && gl->IsANGLE()) {
gl = nullptr; gl = nullptr;
} }
@@ -611,7 +611,7 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
{ {
const gfx::IntSize dummySize(16, 16); const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps, RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
flags); flags, *out_failureId);
if (gl && !gl->IsANGLE()) { if (gl && !gl->IsANGLE()) {
gl = nullptr; gl = nullptr;
} }
@@ -647,7 +647,8 @@ CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
} }
const gfx::IntSize dummySize(16, 16); const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps, flags); RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps,
flags, *out_failureId);
if (gl && gl->IsANGLE()) { if (gl && gl->IsANGLE()) {
gl = nullptr; gl = nullptr;

View File

@@ -92,7 +92,8 @@ static RefPtr<GLContext> sPluginContext = nullptr;
static bool EnsureGLContext() static bool EnsureGLContext()
{ {
if (!sPluginContext) { if (!sPluginContext) {
sPluginContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE); nsCString failureId;
sPluginContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE, failureId);
} }
return sPluginContext != nullptr; return sPluginContext != nullptr;

View File

@@ -23,7 +23,8 @@ class GLContextEGL : public GLContext
GLContextEGL *shareContext, GLContextEGL *shareContext,
bool isOffscreen, bool isOffscreen,
EGLConfig config, EGLConfig config,
EGLSurface surface); EGLSurface surface,
nsACString& aFailureId);
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override)
@@ -106,7 +107,8 @@ public:
static already_AddRefed<GLContextEGL> static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(CreateContextFlags flags, CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
const gfx::IntSize& size, const gfx::IntSize& size,
const SurfaceCaps& minCaps); const SurfaceCaps& minCaps,
nsACString& aFailureId);
protected: protected:
friend class GLContextProviderEGL; friend class GLContextProviderEGL;

View File

@@ -321,14 +321,17 @@ CreateOffscreenFBOContext(CreateContextFlags flags)
} }
already_AddRefed<GLContext> already_AddRefed<GLContext>
GLContextProviderCGL::CreateHeadless(CreateContextFlags flags) GLContextProviderCGL::CreateHeadless(CreateContextFlags flags, nsACString& aFailureId)
{ {
RefPtr<GLContextCGL> gl; RefPtr<GLContextCGL> gl;
gl = CreateOffscreenFBOContext(flags); gl = CreateOffscreenFBOContext(flags);
if (!gl) if (!gl) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_FBO");
return nullptr; return nullptr;
}
if (!gl->Init()) { if (!gl->Init()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
NS_WARNING("Failed during Init."); NS_WARNING("Failed during Init.");
return nullptr; return nullptr;
} }
@@ -339,14 +342,18 @@ GLContextProviderCGL::CreateHeadless(CreateContextFlags flags)
already_AddRefed<GLContext> already_AddRefed<GLContext>
GLContextProviderCGL::CreateOffscreen(const IntSize& size, GLContextProviderCGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps, const SurfaceCaps& minCaps,
CreateContextFlags flags) CreateContextFlags flags,
nsACString& aFailureId)
{ {
RefPtr<GLContext> gl = CreateHeadless(flags); RefPtr<GLContext> gl = CreateHeadless(flags, aFailureId);
if (!gl) if (!gl) {
return nullptr; return nullptr;
}
if (!gl->InitOffscreen(size, minCaps)) if (!gl->InitOffscreen(size, minCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
return nullptr; return nullptr;
}
return gl.forget(); return gl.forget();
} }
@@ -361,7 +368,9 @@ GLContextProviderCGL::GetGlobalContext()
triedToCreateContext = true; triedToCreateContext = true;
MOZ_RELEASE_ASSERT(!gGlobalContext); MOZ_RELEASE_ASSERT(!gGlobalContext);
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE); nsCString discardFailureId;
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE,
discardFailureId);
gGlobalContext = temp; gGlobalContext = temp;
if (!gGlobalContext) { if (!gGlobalContext) {

View File

@@ -455,7 +455,8 @@ GLContextEGL::HoldSurface(gfxASurface *aSurf) {
/* static */ EGLSurface /* static */ EGLSurface
GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget) GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
{ {
if (!sEGLLibrary.EnsureInitialized()) { nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library!\n"); MOZ_CRASH("GFX: Failed to load EGL library!\n");
return nullptr; return nullptr;
} }
@@ -488,9 +489,11 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
GLContextEGL *shareContext, GLContextEGL *shareContext,
bool isOffscreen, bool isOffscreen,
EGLConfig config, EGLConfig config,
EGLSurface surface) EGLSurface surface,
nsACString& aFailureId)
{ {
if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) { if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_ES");
NS_WARNING("Failed to bind API to GLES!"); NS_WARNING("Failed to bind API to GLES!");
return nullptr; return nullptr;
} }
@@ -527,6 +530,7 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
contextAttribs.Elements()); contextAttribs.Elements());
} }
if (!context) { if (!context) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_CREATE");
NS_WARNING("Failed to create EGLContext!"); NS_WARNING("Failed to create EGLContext!");
return nullptr; return nullptr;
} }
@@ -538,8 +542,10 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
surface, surface,
context); context);
if (!glContext->Init()) if (!glContext->Init()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_INIT");
return nullptr; return nullptr;
}
return glContext.forget(); return glContext.forget();
} }
@@ -738,7 +744,8 @@ CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget)
already_AddRefed<GLContext> already_AddRefed<GLContext>
GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface) GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface)
{ {
if (!sEGLLibrary.EnsureInitialized()) { nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 2!\n"); MOZ_CRASH("GFX: Failed to load EGL library 2!\n");
return nullptr; return nullptr;
} }
@@ -763,7 +770,8 @@ GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface)
already_AddRefed<GLContext> already_AddRefed<GLContext>
GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated) GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated)
{ {
if (!sEGLLibrary.EnsureInitialized()) { nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 3!\n"); MOZ_CRASH("GFX: Failed to load EGL library 3!\n");
return nullptr; return nullptr;
} }
@@ -786,7 +794,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated
RefPtr<GLContextEGL> glContext = RefPtr<GLContextEGL> glContext =
GLContextEGL::CreateGLContext(CreateContextFlags::NONE, caps, GLContextEGL::CreateGLContext(CreateContextFlags::NONE, caps,
nullptr, false, nullptr, false,
config, surface); config, surface, discardFailureId);
if (!glContext) { if (!glContext) {
MOZ_CRASH("GFX: Failed to create EGLContext!\n"); MOZ_CRASH("GFX: Failed to create EGLContext!\n");
@@ -804,7 +812,8 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated
EGLSurface EGLSurface
GLContextProviderEGL::CreateEGLSurface(void* aWindow) GLContextProviderEGL::CreateEGLSurface(void* aWindow)
{ {
if (!sEGLLibrary.EnsureInitialized()) { nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 4!\n"); MOZ_CRASH("GFX: Failed to load EGL library 4!\n");
} }
@@ -827,7 +836,8 @@ GLContextProviderEGL::CreateEGLSurface(void* aWindow)
void void
GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface) GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
{ {
if (!sEGLLibrary.EnsureInitialized()) { nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 5!\n"); MOZ_CRASH("GFX: Failed to load EGL library 5!\n");
} }
@@ -938,15 +948,18 @@ ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& min
/*static*/ already_AddRefed<GLContextEGL> /*static*/ already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags, GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
const mozilla::gfx::IntSize& size, const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps) const SurfaceCaps& minCaps,
nsACString& aFailureId)
{ {
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE); bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware)) if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, aFailureId)) {
return nullptr; return nullptr;
}
SurfaceCaps configCaps; SurfaceCaps configCaps;
EGLConfig config = ChooseConfig(&sEGLLibrary, flags, minCaps, &configCaps); EGLConfig config = ChooseConfig(&sEGLLibrary, flags, minCaps, &configCaps);
if (config == EGL_NO_CONFIG) { if (config == EGL_NO_CONFIG) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_NO_CONFIG");
NS_WARNING("Failed to find a compatible config."); NS_WARNING("Failed to find a compatible config.");
return nullptr; return nullptr;
} }
@@ -960,12 +973,13 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
LOCAL_EGL_NONE, LOCAL_EGL_NONE,
pbSize); pbSize);
if (!surface) { if (!surface) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT");
NS_WARNING("Failed to create PBuffer for context!"); NS_WARNING("Failed to create PBuffer for context!");
return nullptr; return nullptr;
} }
RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, configCaps, nullptr, true, RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, configCaps, nullptr, true,
config, surface); config, surface, aFailureId);
if (!gl) { if (!gl) {
NS_WARNING("Failed to create GLContext from PBuffer"); NS_WARNING("Failed to create GLContext from PBuffer");
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface); sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
@@ -976,11 +990,12 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
} }
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateHeadless(CreateContextFlags flags) GLContextProviderEGL::CreateHeadless(CreateContextFlags flags, nsACString& aFailureId)
{ {
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16); mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
SurfaceCaps dummyCaps = SurfaceCaps::Any(); SurfaceCaps dummyCaps = SurfaceCaps::Any();
return GLContextEGL::CreateEGLPBufferOffscreenContext(flags, dummySize, dummyCaps); return GLContextEGL::CreateEGLPBufferOffscreenContext(flags, dummySize, dummyCaps,
aFailureId);
} }
// Under EGL, on Android, pbuffers are supported fine, though // Under EGL, on Android, pbuffers are supported fine, though
@@ -988,11 +1003,14 @@ GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size, GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps, const SurfaceCaps& minCaps,
CreateContextFlags flags) CreateContextFlags flags,
nsACString& aFailureId)
{ {
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE); bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware)) // Needed for IsANGLE(). if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, aFailureId)) { // Needed for IsANGLE().
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_LIB_INIT");
return nullptr; return nullptr;
}
bool canOffscreenUseHeadless = true; bool canOffscreenUseHeadless = true;
if (sEGLLibrary.IsANGLE()) { if (sEGLLibrary.IsANGLE()) {
@@ -1004,9 +1022,10 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
SurfaceCaps minOffscreenCaps = minCaps; SurfaceCaps minOffscreenCaps = minCaps;
if (canOffscreenUseHeadless) { if (canOffscreenUseHeadless) {
gl = CreateHeadless(flags); gl = CreateHeadless(flags, aFailureId);
if (!gl) if (!gl) {
return nullptr; return nullptr;
}
} else { } else {
SurfaceCaps minBackbufferCaps = minOffscreenCaps; SurfaceCaps minBackbufferCaps = minOffscreenCaps;
if (minOffscreenCaps.antialias) { if (minOffscreenCaps.antialias) {
@@ -1015,9 +1034,11 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
minBackbufferCaps.stencil = false; minBackbufferCaps.stencil = false;
} }
gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size, minBackbufferCaps); gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size, minBackbufferCaps,
if (!gl) aFailureId);
if (!gl) {
return nullptr; return nullptr;
}
// Pull the actual resulting caps to ensure that our offscreen matches our // Pull the actual resulting caps to ensure that our offscreen matches our
// backbuffer. // backbuffer.
@@ -1031,8 +1052,10 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
} }
// Init the offscreen with the updated offscreen caps. // Init the offscreen with the updated offscreen caps.
if (!gl->InitOffscreen(size, minOffscreenCaps)) if (!gl->InitOffscreen(size, minOffscreenCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_OFFSCREEN");
return nullptr; return nullptr;
}
return gl.forget(); return gl.forget();
} }

View File

@@ -1223,7 +1223,8 @@ GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window,
} }
static already_AddRefed<GLContextGLX> static already_AddRefed<GLContextGLX>
CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps, ContextProfile profile = ContextProfile::OpenGLCompatibility) CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps, nsACString& aFailureId,
ContextProfile profile = ContextProfile::OpenGLCompatibility)
{ {
GLXLibrary* glx = &sGLXLibrary; GLXLibrary* glx = &sGLXLibrary;
if (!glx->EnsureInitialized()) if (!glx->EnsureInitialized())
@@ -1285,17 +1286,18 @@ DONE_CREATING_PIXMAP:
} }
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateHeadless(CreateContextFlags) GLContextProviderGLX::CreateHeadless(CreateContextFlags, nsACString& aFailureId)
{ {
IntSize dummySize = IntSize(16, 16); IntSize dummySize = IntSize(16, 16);
SurfaceCaps dummyCaps = SurfaceCaps::Any(); SurfaceCaps dummyCaps = SurfaceCaps::Any();
return CreateOffscreenPixmapContext(dummySize, dummyCaps); return CreateOffscreenPixmapContext(dummySize, dummyCaps, aFailureId);
} }
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateOffscreen(const IntSize& size, GLContextProviderGLX::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps, const SurfaceCaps& minCaps,
CreateContextFlags flags) CreateContextFlags flags,
nsACString& aFailureId)
{ {
SurfaceCaps minBackbufferCaps = minCaps; SurfaceCaps minBackbufferCaps = minCaps;
if (minCaps.antialias) { if (minCaps.antialias) {
@@ -1310,12 +1312,14 @@ GLContextProviderGLX::CreateOffscreen(const IntSize& size,
} }
RefPtr<GLContext> gl; RefPtr<GLContext> gl;
gl = CreateOffscreenPixmapContext(size, minBackbufferCaps, profile); gl = CreateOffscreenPixmapContext(size, minBackbufferCaps, aFailureId, profile);
if (!gl) if (!gl)
return nullptr; return nullptr;
if (!gl->InitOffscreen(size, minCaps)) if (!gl->InitOffscreen(size, minCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT");
return nullptr; return nullptr;
}
return gl.forget(); return gl.forget();
} }
@@ -1332,7 +1336,8 @@ GLContextProviderGLX::GetGlobalContext()
triedToCreateContext = true; triedToCreateContext = true;
MOZ_RELEASE_ASSERT(!gGlobalContext); MOZ_RELEASE_ASSERT(!gGlobalContext);
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE); nsCString discardFailureId;
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, discardFailureId);
gGlobalContext = temp; gGlobalContext = temp;
} }

View File

@@ -67,11 +67,12 @@ public:
static already_AddRefed<GLContext> static already_AddRefed<GLContext>
CreateOffscreen(const mozilla::gfx::IntSize& size, CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps, const SurfaceCaps& minCaps,
CreateContextFlags flags); CreateContextFlags flags,
nsACString& failureId);
// Just create a context. We'll add offscreen stuff ourselves. // Just create a context. We'll add offscreen stuff ourselves.
static already_AddRefed<GLContext> static already_AddRefed<GLContext>
CreateHeadless(CreateContextFlags flags); CreateHeadless(CreateContextFlags flags, nsACString& aFailureId);
/** /**
* Create wrapping Gecko GLContext for external gl context. * Create wrapping Gecko GLContext for external gl context.

View File

@@ -23,8 +23,10 @@ GLContextProviderNull::CreateWrappingExisting(void*, void*)
already_AddRefed<GLContext> already_AddRefed<GLContext>
GLContextProviderNull::CreateOffscreen(const gfx::IntSize&, GLContextProviderNull::CreateOffscreen(const gfx::IntSize&,
const SurfaceCaps&, const SurfaceCaps&,
CreateContextFlags) CreateContextFlags,
nsACString& aFailureId)
{ {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NULL");
return nullptr; return nullptr;
} }

View File

@@ -641,7 +641,7 @@ CreateWindowOffscreenContext()
} }
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderWGL::CreateHeadless(CreateContextFlags) GLContextProviderWGL::CreateHeadless(CreateContextFlags, nsACString& aFailureId)
{ {
if (!sWGLLib.EnsureInitialized()) { if (!sWGLLib.EnsureInitialized()) {
return nullptr; return nullptr;
@@ -676,14 +676,17 @@ GLContextProviderWGL::CreateHeadless(CreateContextFlags)
/*static*/ already_AddRefed<GLContext> /*static*/ already_AddRefed<GLContext>
GLContextProviderWGL::CreateOffscreen(const IntSize& size, GLContextProviderWGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps, const SurfaceCaps& minCaps,
CreateContextFlags flags) CreateContextFlags flags,
nsACString& aFailureId)
{ {
RefPtr<GLContext> gl = CreateHeadless(flags); RefPtr<GLContext> gl = CreateHeadless(flags, aFailureId);
if (!gl) if (!gl)
return nullptr; return nullptr;
if (!gl->InitOffscreen(size, minCaps)) if (!gl->InitOffscreen(size, minCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT");
return nullptr; return nullptr;
}
return gl.forget(); return gl.forget();
} }
@@ -698,7 +701,8 @@ GLContextProviderWGL::GetGlobalContext()
triedToCreateContext = true; triedToCreateContext = true;
MOZ_RELEASE_ASSERT(!gGlobalContext); MOZ_RELEASE_ASSERT(!gGlobalContext);
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE); nsCString discardFailureId;
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, discardFailureId);
gGlobalContext = temp; gGlobalContext = temp;
} }

View File

@@ -142,7 +142,7 @@ GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType)
} }
static bool static bool
IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo) IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo, nsACString& aFailureId)
{ {
int32_t angleSupport; int32_t angleSupport;
nsCString failureId; nsCString failureId;
@@ -152,6 +152,9 @@ IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
&angleSupport); &angleSupport);
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID, Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
failureId); failureId);
if (failureId.IsEmpty()) {
aFailureId = failureId;
}
return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK); return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
} }
@@ -201,7 +204,9 @@ GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surfa
{ {
StaticMutexAutoUnlock lock(sMutex); StaticMutexAutoUnlock lock(sMutex);
if (!mReadbackGL) { if (!mReadbackGL) {
mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE); nsCString discardFailureId;
mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE,
discardFailureId);
} }
ScopedTexture destTex(mReadbackGL); ScopedTexture destTex(mReadbackGL);
@@ -223,7 +228,7 @@ GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surfa
} }
bool bool
GLLibraryEGL::EnsureInitialized(bool forceAccel) GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString& aFailureId)
{ {
if (mInitialized) { if (mInitialized) {
return true; return true;
@@ -389,7 +394,7 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel)
EGLDisplay chosenDisplay = nullptr; EGLDisplay chosenDisplay = nullptr;
if (IsExtensionSupported(ANGLE_platform_angle_d3d)) { if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
bool accelAngleSupport = IsAccelAngleSupported(gfxInfo); bool accelAngleSupport = IsAccelAngleSupported(gfxInfo, aFailureId);
bool shouldTryAccel = forceAccel || accelAngleSupport; bool shouldTryAccel = forceAccel || accelAngleSupport;
bool shouldTryWARP = !shouldTryAccel; bool shouldTryWARP = !shouldTryAccel;
@@ -410,6 +415,9 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel)
// If falling back to WARP did not work and we don't want to try // If falling back to WARP did not work and we don't want to try
// using HW accelerated ANGLE, then fail. // using HW accelerated ANGLE, then fail.
if (!shouldTryAccel) { if (!shouldTryAccel) {
if (aFailureId.IsEmpty()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WARP_FALLBACK");
}
NS_ERROR("Fallback WARP ANGLE context failed to initialize."); NS_ERROR("Fallback WARP ANGLE context failed to initialize.");
return false; return false;
} }
@@ -422,6 +430,9 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel)
} }
if (!chosenDisplay) { if (!chosenDisplay) {
if (aFailureId.IsEmpty()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_DISPLAY");
}
NS_WARNING("Failed to initialize a display."); NS_WARNING("Failed to initialize a display.");
return false; return false;
} }

View File

@@ -535,7 +535,7 @@ public:
bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface); bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
bool EnsureInitialized(bool forceAccel = false); bool EnsureInitialized(bool forceAccel, nsACString& aFailureId);
void DumpEGLConfig(EGLConfig cfg); void DumpEGLConfig(EGLConfig cfg);
void DumpEGLConfigs(); void DumpEGLConfigs();

View File

@@ -51,7 +51,9 @@ GLImage::GetAsSourceSurface()
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread"); MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");
if (!sSnapshotContext) { if (!sSnapshotContext) {
sSnapshotContext = GLContextProvider::CreateHeadless(CreateContextFlags::NONE); nsCString discardFailureId;
sSnapshotContext = GLContextProvider::CreateHeadless(CreateContextFlags::NONE,
discardFailureId);
if (!sSnapshotContext) { if (!sSnapshotContext) {
NS_WARNING("Failed to create snapshot GLContext"); NS_WARNING("Failed to create snapshot GLContext");
return nullptr; return nullptr;

View File

@@ -131,8 +131,10 @@ CompositorOGL::CreateContext()
caps.preserve = false; caps.preserve = false;
caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == SurfaceFormat::R5G6B5_UINT16; caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == SurfaceFormat::R5G6B5_UINT16;
nsCString discardFailureId;
context = GLContextProvider::CreateOffscreen(mSurfaceSize, context = GLContextProvider::CreateOffscreen(mSurfaceSize,
caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE); caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE,
discardFailureId);
} }
if (!context) { if (!context) {

View File

@@ -48,9 +48,11 @@ public:
mozilla::gl::SurfaceCaps caps = mozilla::gl::SurfaceCaps::ForRGB(); mozilla::gl::SurfaceCaps caps = mozilla::gl::SurfaceCaps::ForRGB();
caps.preserve = false; caps.preserve = false;
caps.bpp16 = false; caps.bpp16 = false;
nsCString discardFailureId;
RefPtr<GLContext> context = GLContextProvider::CreateOffscreen( RefPtr<GLContext> context = GLContextProvider::CreateOffscreen(
IntSize(gCompWidth, gCompHeight), caps, IntSize(gCompWidth, gCompHeight), caps,
CreateContextFlags::REQUIRE_COMPAT_PROFILE); CreateContextFlags::REQUIRE_COMPAT_PROFILE,
discardFailureId);
return context.forget().take(); return context.forget().take();
} }
return nullptr; return nullptr;

View File

@@ -1321,8 +1321,10 @@ gfxPlatform::GetSkiaGLGlue()
* stands, this only works on the main thread. * stands, this only works on the main thread.
*/ */
RefPtr<GLContext> glContext; RefPtr<GLContext> glContext;
nsCString discardFailureId;
glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE | glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE |
CreateContextFlags::ALLOW_OFFLINE_RENDERER); CreateContextFlags::ALLOW_OFFLINE_RENDERER,
discardFailureId);
if (!glContext) { if (!glContext) {
printf_stderr("Failed to create GLContext for SkiaGL!\n"); printf_stderr("Failed to create GLContext for SkiaGL!\n");
return nullptr; return nullptr;

View File

@@ -75,7 +75,9 @@ public:
} }
RefPtr<gl::GLContext> gl; RefPtr<gl::GLContext> gl;
gl = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE); nsCString discardFailureId;
gl = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE,
discardFailureId);
if (!gl) { if (!gl) {
// Setting mReady to true here means that we won't retry. Everything will // Setting mReady to true here means that we won't retry. Everything will