Skip to content

Commit

Permalink
Bug 1276732 - Report the GLContext error to WebGL for telemetry. r=jr…
Browse files Browse the repository at this point in the history
…muizel

MozReview-Commit-ID: 24eb4FXMOiI
  • Loading branch information
bgirard committed Jun 6, 2016
1 parent 11e6f19 commit 6ca0b0a
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 58 deletions.
7 changes: 4 additions & 3 deletions dom/canvas/WebGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
{
const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
flags);
flags, *out_failureId);
if (gl && gl->IsANGLE()) {
gl = nullptr;
}
Expand All @@ -611,7 +611,7 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
{
const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
flags);
flags, *out_failureId);
if (gl && !gl->IsANGLE()) {
gl = nullptr;
}
Expand Down Expand Up @@ -647,7 +647,8 @@ CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
}

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()) {
gl = nullptr;
Expand Down
3 changes: 2 additions & 1 deletion dom/plugins/base/nsNPAPIPluginInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ static RefPtr<GLContext> sPluginContext = nullptr;
static bool EnsureGLContext()
{
if (!sPluginContext) {
sPluginContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE);
nsCString failureId;
sPluginContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE, failureId);
}

return sPluginContext != nullptr;
Expand Down
6 changes: 4 additions & 2 deletions gfx/gl/GLContextEGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class GLContextEGL : public GLContext
GLContextEGL *shareContext,
bool isOffscreen,
EGLConfig config,
EGLSurface surface);
EGLSurface surface,
nsACString& aFailureId);

public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override)
Expand Down Expand Up @@ -106,7 +107,8 @@ class GLContextEGL : public GLContext
static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
const gfx::IntSize& size,
const SurfaceCaps& minCaps);
const SurfaceCaps& minCaps,
nsACString& aFailureId);

protected:
friend class GLContextProviderEGL;
Expand Down
23 changes: 16 additions & 7 deletions gfx/gl/GLContextProviderCGL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,17 @@ bool UseDoubleBufferedWindows() const {
}

already_AddRefed<GLContext>
GLContextProviderCGL::CreateHeadless(CreateContextFlags flags)
GLContextProviderCGL::CreateHeadless(CreateContextFlags flags, nsACString& aFailureId)
{
RefPtr<GLContextCGL> gl;
gl = CreateOffscreenFBOContext(flags);
if (!gl)
if (!gl) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_FBO");
return nullptr;
}

if (!gl->Init()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
NS_WARNING("Failed during Init.");
return nullptr;
}
Expand All @@ -339,14 +342,18 @@ bool UseDoubleBufferedWindows() const {
already_AddRefed<GLContext>
GLContextProviderCGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
CreateContextFlags flags,
nsACString& aFailureId)
{
RefPtr<GLContext> gl = CreateHeadless(flags);
if (!gl)
RefPtr<GLContext> gl = CreateHeadless(flags, aFailureId);
if (!gl) {
return nullptr;
}

if (!gl->InitOffscreen(size, minCaps))
if (!gl->InitOffscreen(size, minCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT");
return nullptr;
}

return gl.forget();
}
Expand All @@ -361,7 +368,9 @@ bool UseDoubleBufferedWindows() const {
triedToCreateContext = true;

MOZ_RELEASE_ASSERT(!gGlobalContext);
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
nsCString discardFailureId;
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE,
discardFailureId);
gGlobalContext = temp;

if (!gGlobalContext) {
Expand Down
63 changes: 43 additions & 20 deletions gfx/gl/GLContextProviderEGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ GLContextEGL::HoldSurface(gfxASurface *aSurf) {
/* static */ EGLSurface
GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
{
if (!sEGLLibrary.EnsureInitialized()) {
nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library!\n");
return nullptr;
}
Expand Down Expand Up @@ -488,9 +489,11 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
GLContextEGL *shareContext,
bool isOffscreen,
EGLConfig config,
EGLSurface surface)
EGLSurface surface,
nsACString& aFailureId)
{
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!");
return nullptr;
}
Expand Down Expand Up @@ -527,6 +530,7 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
contextAttribs.Elements());
}
if (!context) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_CREATE");
NS_WARNING("Failed to create EGLContext!");
return nullptr;
}
Expand All @@ -538,8 +542,10 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
surface,
context);

if (!glContext->Init())
if (!glContext->Init()) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_INIT");
return nullptr;
}

return glContext.forget();
}
Expand Down Expand Up @@ -738,7 +744,8 @@ CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget)
already_AddRefed<GLContext>
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");
return nullptr;
}
Expand All @@ -763,7 +770,8 @@ GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface)
already_AddRefed<GLContext>
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");
return nullptr;
}
Expand All @@ -786,7 +794,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated
RefPtr<GLContextEGL> glContext =
GLContextEGL::CreateGLContext(CreateContextFlags::NONE, caps,
nullptr, false,
config, surface);
config, surface, discardFailureId);

if (!glContext) {
MOZ_CRASH("GFX: Failed to create EGLContext!\n");
Expand All @@ -804,7 +812,8 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget, bool aForceAccelerated
EGLSurface
GLContextProviderEGL::CreateEGLSurface(void* aWindow)
{
if (!sEGLLibrary.EnsureInitialized()) {
nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 4!\n");
}

Expand All @@ -827,7 +836,8 @@ GLContextProviderEGL::CreateEGLSurface(void* aWindow)
void
GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
{
if (!sEGLLibrary.EnsureInitialized()) {
nsCString discardFailureId;
if (!sEGLLibrary.EnsureInitialized(false, discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 5!\n");
}

Expand Down Expand Up @@ -938,15 +948,18 @@ ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& min
/*static*/ already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps)
const SurfaceCaps& minCaps,
nsACString& aFailureId)
{
bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware))
if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, aFailureId)) {
return nullptr;
}

SurfaceCaps configCaps;
EGLConfig config = ChooseConfig(&sEGLLibrary, flags, minCaps, &configCaps);
if (config == EGL_NO_CONFIG) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_NO_CONFIG");
NS_WARNING("Failed to find a compatible config.");
return nullptr;
}
Expand All @@ -960,12 +973,13 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
LOCAL_EGL_NONE,
pbSize);
if (!surface) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT");
NS_WARNING("Failed to create PBuffer for context!");
return nullptr;
}

RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, configCaps, nullptr, true,
config, surface);
config, surface, aFailureId);
if (!gl) {
NS_WARNING("Failed to create GLContext from PBuffer");
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
Expand All @@ -976,23 +990,27 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
}

/*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateHeadless(CreateContextFlags flags)
GLContextProviderEGL::CreateHeadless(CreateContextFlags flags, nsACString& aFailureId)
{
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
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
// often without the ability to texture from them directly.
/*static*/ already_AddRefed<GLContext>
GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
CreateContextFlags flags,
nsACString& aFailureId)
{
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;
}

bool canOffscreenUseHeadless = true;
if (sEGLLibrary.IsANGLE()) {
Expand All @@ -1004,9 +1022,10 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
SurfaceCaps minOffscreenCaps = minCaps;

if (canOffscreenUseHeadless) {
gl = CreateHeadless(flags);
if (!gl)
gl = CreateHeadless(flags, aFailureId);
if (!gl) {
return nullptr;
}
} else {
SurfaceCaps minBackbufferCaps = minOffscreenCaps;
if (minOffscreenCaps.antialias) {
Expand All @@ -1015,9 +1034,11 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
minBackbufferCaps.stencil = false;
}

gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size, minBackbufferCaps);
if (!gl)
gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size, minBackbufferCaps,
aFailureId);
if (!gl) {
return nullptr;
}

// Pull the actual resulting caps to ensure that our offscreen matches our
// backbuffer.
Expand All @@ -1031,8 +1052,10 @@ GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
}

// 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 gl.forget();
}
Expand Down
19 changes: 12 additions & 7 deletions gfx/gl/GLContextProviderGLX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,8 @@ GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window,
}

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;
if (!glx->EnsureInitialized())
Expand Down Expand Up @@ -1285,17 +1286,18 @@ CreateOffscreenPixmapContext(const IntSize& size, const SurfaceCaps& minCaps, Co
}

/*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateHeadless(CreateContextFlags)
GLContextProviderGLX::CreateHeadless(CreateContextFlags, nsACString& aFailureId)
{
IntSize dummySize = IntSize(16, 16);
SurfaceCaps dummyCaps = SurfaceCaps::Any();
return CreateOffscreenPixmapContext(dummySize, dummyCaps);
return CreateOffscreenPixmapContext(dummySize, dummyCaps, aFailureId);
}

/*static*/ already_AddRefed<GLContext>
GLContextProviderGLX::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps,
CreateContextFlags flags)
CreateContextFlags flags,
nsACString& aFailureId)
{
SurfaceCaps minBackbufferCaps = minCaps;
if (minCaps.antialias) {
Expand All @@ -1310,12 +1312,14 @@ GLContextProviderGLX::CreateOffscreen(const IntSize& size,
}

RefPtr<GLContext> gl;
gl = CreateOffscreenPixmapContext(size, minBackbufferCaps, profile);
gl = CreateOffscreenPixmapContext(size, minBackbufferCaps, aFailureId, profile);
if (!gl)
return nullptr;

if (!gl->InitOffscreen(size, minCaps))
if (!gl->InitOffscreen(size, minCaps)) {
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT");
return nullptr;
}

return gl.forget();
}
Expand All @@ -1332,7 +1336,8 @@ GLContextProviderGLX::GetGlobalContext()
triedToCreateContext = true;

MOZ_RELEASE_ASSERT(!gGlobalContext);
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
nsCString discardFailureId;
RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, discardFailureId);
gGlobalContext = temp;
}

Expand Down
5 changes: 3 additions & 2 deletions gfx/gl/GLContextProviderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ class GL_CONTEXT_PROVIDER_NAME
static already_AddRefed<GLContext>
CreateOffscreen(const mozilla::gfx::IntSize& size,
const SurfaceCaps& minCaps,
CreateContextFlags flags);
CreateContextFlags flags,
nsACString& failureId);

// Just create a context. We'll add offscreen stuff ourselves.
static already_AddRefed<GLContext>
CreateHeadless(CreateContextFlags flags);
CreateHeadless(CreateContextFlags flags, nsACString& aFailureId);

/**
* Create wrapping Gecko GLContext for external gl context.
Expand Down
4 changes: 3 additions & 1 deletion gfx/gl/GLContextProviderNull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ GLContextProviderNull::CreateWrappingExisting(void*, void*)
already_AddRefed<GLContext>
GLContextProviderNull::CreateOffscreen(const gfx::IntSize&,
const SurfaceCaps&,
CreateContextFlags)
CreateContextFlags,
nsACString& aFailureId)
{
aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NULL");
return nullptr;
}

Expand Down
Loading

0 comments on commit 6ca0b0a

Please sign in to comment.