--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -582,17 +582,17 @@ BaseCaps(const WebGLContextOptions& opti
static already_AddRefed<gl::GLContext>
CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
WebGLContext* webgl, nsACString* const out_failReason,
nsACString* const out_failureId)
{
const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
- flags);
+ flags, *out_failureId);
if (gl && gl->IsANGLE()) {
gl = nullptr;
}
if (!gl) {
if (out_failReason->Length()) {
out_failReason->AppendLiteral("\n");
}
@@ -606,17 +606,17 @@ CreateGLWithEGL(const gl::SurfaceCaps& c
static already_AddRefed<GLContext>
CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
WebGLContext* webgl, nsACString* const out_failReason,
nsACString* const out_failureId)
{
const gfx::IntSize dummySize(16, 16);
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
- flags);
+ flags, *out_failureId);
if (gl && !gl->IsANGLE()) {
gl = nullptr;
}
if (!gl) {
if (out_failReason->Length()) {
out_failReason->AppendLiteral("\n");
}
@@ -642,17 +642,18 @@ CreateGLWithDefault(const gl::SurfaceCap
out_failReason->AppendASCII("\n");
}
out_failReason->AppendASCII("Refused to create native OpenGL context because of"
" blacklisting.");
return nullptr;
}
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;
}
if (!gl) {
if (out_failReason->Length()) {
out_failReason->AppendASCII("\n");
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -87,17 +87,18 @@ private:
bool mCanceled;
};
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;
}
static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
#endif
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -18,17 +18,18 @@ class GLContextEGL : public GLContext
friend class TextureImageEGL;
static already_AddRefed<GLContextEGL>
CreateGLContext(CreateContextFlags flags,
const SurfaceCaps& caps,
GLContextEGL *shareContext,
bool isOffscreen,
EGLConfig config,
- EGLSurface surface);
+ EGLSurface surface,
+ nsACString& aFailureId);
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override)
GLContextEGL(const SurfaceCaps& caps,
GLContext* shareContext,
bool isOffscreen,
EGLConfig config,
EGLSurface surface,
@@ -101,17 +102,18 @@ public:
bool BindTex2DOffscreen(GLContext *aOffscreen);
void UnbindTex2DOffscreen(GLContext *aOffscreen);
void BindOffscreenFramebuffer();
static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
const gfx::IntSize& size,
- const SurfaceCaps& minCaps);
+ const SurfaceCaps& minCaps,
+ nsACString& aFailureId);
protected:
friend class GLContextProviderEGL;
public:
const EGLConfig mConfig;
protected:
EGLSurface mSurface;
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -316,57 +316,66 @@ CreateOffscreenFBOContext(CreateContextF
if (gfxPrefs::GLMultithreaded()) {
CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine);
}
return glContext.forget();
}
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;
}
return gl.forget();
}
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();
}
static RefPtr<GLContext> gGlobalContext;
GLContext*
GLContextProviderCGL::GetGlobalContext()
{
static bool triedToCreateContext = false;
if (!triedToCreateContext) {
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) {
NS_WARNING("Couldn't init gGlobalContext.");
}
}
return gGlobalContext;
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -450,17 +450,18 @@ GLContextEGL::SwapBuffers()
void
GLContextEGL::HoldSurface(gfxASurface *aSurf) {
mThebesSurface = 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;
}
EGLConfig config;
if (!CreateConfig(&config, aWidget)) {
MOZ_CRASH("GFX: Failed to create EGLConfig!\n");
return nullptr;
@@ -483,19 +484,21 @@ GLContextEGL::DestroySurface(EGLSurface
}
already_AddRefed<GLContextEGL>
GLContextEGL::CreateGLContext(CreateContextFlags flags,
const SurfaceCaps& caps,
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;
}
EGLContext eglShareContext = shareContext ? shareContext->mContext
: EGL_NO_CONTEXT;
nsTArray<EGLint> contextAttribs;
@@ -522,29 +525,32 @@ GLContextEGL::CreateGLContext(CreateCont
if (!context && shareContext) {
shareContext = nullptr;
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_CONTEXT,
contextAttribs.Elements());
}
if (!context) {
+ aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_CREATE");
NS_WARNING("Failed to create EGLContext!");
return nullptr;
}
RefPtr<GLContextEGL> glContext = new GLContextEGL(caps,
shareContext,
isOffscreen,
config,
surface,
context);
- if (!glContext->Init())
+ if (!glContext->Init()) {
+ aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_INIT");
return nullptr;
+ }
return glContext.forget();
}
EGLSurface
GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
EGLenum bindToTextureFormat,
mozilla::gfx::IntSize& pbsize)
@@ -733,17 +739,18 @@ CreateConfig(EGLConfig* aConfig, nsIWidg
} else {
return true;
}
}
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;
}
if (aContext && aSurface) {
SurfaceCaps caps = SurfaceCaps::Any();
EGLConfig config = EGL_NO_CONFIG;
RefPtr<GLContextEGL> glContext =
@@ -758,17 +765,18 @@ GLContextProviderEGL::CreateWrappingExis
}
return nullptr;
}
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;
}
bool doubleBuffered = true;
EGLConfig config;
if (!CreateConfig(&config, aWidget)) {
@@ -781,17 +789,17 @@ GLContextProviderEGL::CreateForWindow(ns
MOZ_CRASH("GFX: Failed to create EGLSurface!\n");
return nullptr;
}
SurfaceCaps caps = SurfaceCaps::Any();
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");
mozilla::gl::DestroySurface(surface);
return nullptr;
}
glContext->MakeCurrent();
@@ -799,17 +807,18 @@ GLContextProviderEGL::CreateForWindow(ns
return glContext.forget();
}
#if defined(ANDROID)
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");
}
EGLConfig config;
if (!CreateConfig(&config, static_cast<nsIWidget*>(aWindow))) {
MOZ_CRASH("GFX: Failed to create EGLConfig 2!\n");
}
@@ -822,17 +831,18 @@ GLContextProviderEGL::CreateEGLSurface(v
}
return surface;
}
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");
}
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
}
#endif // defined(ANDROID)
static void
@@ -933,111 +943,124 @@ ChooseConfig(GLLibraryEGL* egl, CreateCo
out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8);
return config;
}
/*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;
}
if (GLContext::ShouldSpew()) {
sEGLLibrary.DumpEGLConfig(config);
}
mozilla::gfx::IntSize pbSize(size);
EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
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);
return nullptr;
}
return gl.forget();
}
/*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()) {
// ANGLE needs to use PBuffers.
canOffscreenUseHeadless = false;
}
RefPtr<GLContext> gl;
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) {
minBackbufferCaps.antialias = false;
minBackbufferCaps.depth = false;
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.
minOffscreenCaps.alpha = gl->Caps().alpha;
if (!minOffscreenCaps.antialias) {
// Only update these if we don't have AA. If we do have AA, we ignore
// backbuffer depth/stencil.
minOffscreenCaps.depth = gl->Caps().depth;
minOffscreenCaps.stencil = gl->Caps().stencil;
}
}
// 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();
}
// Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
// and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
// and 3) each EGL context eats 750k on B2G (bug 813783)
/*static*/ GLContext*
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -1218,17 +1218,18 @@ GLContextGLX::FindFBConfigForWindow(Disp
}
}
NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual");
return false;
}
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())
return nullptr;
Display* display = DefaultXDisplay();
int screen = DefaultScreen(display);
@@ -1280,64 +1281,68 @@ DONE_CREATING_PIXMAP:
return nullptr;
GLContextGLX* shareContext = GetGlobalContextGLX();
return GLContextGLX::CreateGLContext(minCaps, shareContext, true, display, pixmap,
config, true, surface, profile);
}
/*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) {
minBackbufferCaps.antialias = false;
minBackbufferCaps.depth = false;
minBackbufferCaps.stencil = false;
}
ContextProfile profile = ContextProfile::OpenGLCore;
if (flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE) {
profile = ContextProfile::OpenGLCompatibility;
}
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();
}
/*static*/ GLContext*
GLContextProviderGLX::GetGlobalContext()
{
// TODO: get GLX context sharing to work well with multiple threads
if (gfxEnv::DisableContextSharingGlx())
return nullptr;
static bool triedToCreateContext = false;
if (!triedToCreateContext) {
triedToCreateContext = true;
MOZ_RELEASE_ASSERT(!gGlobalContext);
- RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
+ nsCString discardFailureId;
+ RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, discardFailureId);
gGlobalContext = temp;
}
return gGlobalContext;
}
/*static*/ void
GLContextProviderGLX::Shutdown()
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -62,21 +62,22 @@ public:
* @param flags The set of CreateContextFlags to be used for this
* offscreen context.
*
* @return Context to use for offscreen rendering
*/
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.
*
* @param aContext External context which will be wrapped by Gecko GLContext.
* @param aSurface External surface which is used for external context.
*
* @return Wrapping Context to use for rendering
--- a/gfx/gl/GLContextProviderNull.cpp
+++ b/gfx/gl/GLContextProviderNull.cpp
@@ -18,18 +18,20 @@ already_AddRefed<GLContext>
GLContextProviderNull::CreateWrappingExisting(void*, void*)
{
return nullptr;
}
already_AddRefed<GLContext>
GLContextProviderNull::CreateOffscreen(const gfx::IntSize&,
const SurfaceCaps&,
- CreateContextFlags)
+ CreateContextFlags,
+ nsACString& aFailureId)
{
+ aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NULL");
return nullptr;
}
already_AddRefed<GLContext>
GLContextProviderNull::CreateHeadless(CreateContextFlags)
{
return nullptr;
}
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -636,17 +636,17 @@ CreateWindowOffscreenContext()
RefPtr<GLContextWGL> glContext = new GLContextWGL(caps,
shareContext, true,
dc, context, win);
return glContext.forget();
}
/*static*/ already_AddRefed<GLContext>
-GLContextProviderWGL::CreateHeadless(CreateContextFlags)
+GLContextProviderWGL::CreateHeadless(CreateContextFlags, nsACString& aFailureId)
{
if (!sWGLLib.EnsureInitialized()) {
return nullptr;
}
RefPtr<GLContextWGL> glContext;
// Always try to create a pbuffer context first, because we
@@ -671,39 +671,43 @@ GLContextProviderWGL::CreateHeadless(Cre
RefPtr<GLContext> retGL = glContext.get();
return retGL.forget();
}
/*static*/ already_AddRefed<GLContext>
GLContextProviderWGL::CreateOffscreen(const IntSize& size,
const SurfaceCaps& minCaps,
- CreateContextFlags flags)
+ CreateContextFlags flags,
+ nsACString& aFailureId)
{
- RefPtr<GLContext> gl = CreateHeadless(flags);
+ 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_WGL_INIT");
return nullptr;
+ }
return gl.forget();
}
static StaticRefPtr<GLContext> gGlobalContext;
/*static*/ GLContext*
GLContextProviderWGL::GetGlobalContext()
{
static bool triedToCreateContext = false;
if (!triedToCreateContext) {
triedToCreateContext = true;
MOZ_RELEASE_ASSERT(!gGlobalContext);
- RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
+ nsCString discardFailureId;
+ RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, discardFailureId);
gGlobalContext = temp;
}
return static_cast<GLContext*>(gGlobalContext);
}
/*static*/ void
GLContextProviderWGL::Shutdown()
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -137,26 +137,29 @@ GetAndInitWARPDisplay(GLLibraryEGL& egl,
if (!egl.fInitialize(display, nullptr, nullptr))
return EGL_NO_DISPLAY;
return display;
}
static bool
-IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
+IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo, nsACString& aFailureId)
{
int32_t angleSupport;
nsCString failureId;
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
nsIGfxInfo::FEATURE_WEBGL_ANGLE,
failureId,
&angleSupport);
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
failureId);
+ if (failureId.IsEmpty()) {
+ aFailureId = failureId;
+ }
return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
}
static EGLDisplay
GetAndInitDisplay(GLLibraryEGL& egl, void* displayType)
{
EGLDisplay display = egl.fGetDisplay(displayType);
if (display == EGL_NO_DISPLAY)
@@ -196,17 +199,19 @@ GetAndInitDisplayForAccelANGLE(GLLibrary
return ret;
}
bool
GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface)
{
StaticMutexAutoUnlock lock(sMutex);
if (!mReadbackGL) {
- mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE);
+ nsCString discardFailureId;
+ mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE,
+ discardFailureId);
}
ScopedTexture destTex(mReadbackGL);
const GLuint target = LOCAL_GL_TEXTURE_EXTERNAL;
ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
@@ -218,17 +223,17 @@ GLLibraryEGL::ReadbackEGLImage(EGLImage
int shaderConfig = config.mFeatures;
mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target,
out_surface->GetSize(), shaderConfig);
return true;
}
bool
-GLLibraryEGL::EnsureInitialized(bool forceAccel)
+GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString& aFailureId)
{
if (mInitialized) {
return true;
}
mozilla::ScopedGfxFeatureReporter reporter("EGL");
#ifdef MOZ_B2G
@@ -384,17 +389,17 @@ GLLibraryEGL::EnsureInitialized(bool for
// Check the ANGLE support the system has
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
mIsANGLE = IsExtensionSupported(ANGLE_platform_angle);
EGLDisplay chosenDisplay = nullptr;
if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
- bool accelAngleSupport = IsAccelAngleSupported(gfxInfo);
+ bool accelAngleSupport = IsAccelAngleSupported(gfxInfo, aFailureId);
bool shouldTryAccel = forceAccel || accelAngleSupport;
bool shouldTryWARP = !shouldTryAccel;
if (gfxPrefs::WebGLANGLEForceWARP()) {
shouldTryWARP = true;
shouldTryAccel = false;
}
@@ -405,28 +410,34 @@ GLLibraryEGL::EnsureInitialized(bool for
mIsWARP = true;
}
}
if (!chosenDisplay) {
// If falling back to WARP did not work and we don't want to try
// using HW accelerated ANGLE, then fail.
if (!shouldTryAccel) {
+ if (aFailureId.IsEmpty()) {
+ aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WARP_FALLBACK");
+ }
NS_ERROR("Fallback WARP ANGLE context failed to initialize.");
return false;
}
// Hardware accelerated ANGLE path
chosenDisplay = GetAndInitDisplayForAccelANGLE(*this);
}
} else {
chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);
}
if (!chosenDisplay) {
+ if (aFailureId.IsEmpty()) {
+ aFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_DISPLAY");
+ }
NS_WARNING("Failed to initialize a display.");
return false;
}
mEGLDisplay = chosenDisplay;
InitDisplayExtensions();
////////////////////////////////////
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -530,17 +530,17 @@ public:
}
bool HasRobustness() const {
return IsExtensionSupported(EXT_create_context_robustness);
}
bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
- bool EnsureInitialized(bool forceAccel = false);
+ bool EnsureInitialized(bool forceAccel, nsACString& aFailureId);
void DumpEGLConfig(EGLConfig cfg);
void DumpEGLConfigs();
struct {
typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
pfnGetDisplay fGetDisplay;
typedef EGLDisplay(GLAPIENTRY * pfnGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -46,17 +46,19 @@ EGLImageImage::~EGLImageImage()
}
already_AddRefed<gfx::SourceSurface>
GLImage::GetAsSourceSurface()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");
if (!sSnapshotContext) {
- sSnapshotContext = GLContextProvider::CreateHeadless(CreateContextFlags::NONE);
+ nsCString discardFailureId;
+ sSnapshotContext = GLContextProvider::CreateHeadless(CreateContextFlags::NONE,
+ discardFailureId);
if (!sSnapshotContext) {
NS_WARNING("Failed to create snapshot GLContext");
return nullptr;
}
}
sSnapshotContext->MakeCurrent();
ScopedTexture scopedTex(sSnapshotContext);
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -126,18 +126,20 @@ CompositorOGL::CreateContext()
#endif
// Allow to create offscreen GL context for main Layer Manager
if (!context && gfxEnv::LayersPreferOffscreen()) {
SurfaceCaps caps = SurfaceCaps::ForRGB();
caps.preserve = false;
caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == SurfaceFormat::R5G6B5_UINT16;
+ nsCString discardFailureId;
context = GLContextProvider::CreateOffscreen(mSurfaceSize,
- caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE);
+ caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE,
+ discardFailureId);
}
if (!context) {
context = gl::GLContextProvider::CreateForWindow(mWidget->RealWidget(),
gfxPlatform::GetPlatform()->RequiresAcceleratedGLContextForCompositorOGL());
}
if (!context) {
--- a/gfx/tests/gtest/TestCompositor.cpp
+++ b/gfx/tests/gtest/TestCompositor.cpp
@@ -43,19 +43,21 @@ public:
return GetClientBounds(aRect);
}
void* GetNativeData(uint32_t aDataType) override {
if (aDataType == NS_NATIVE_OPENGL_CONTEXT) {
mozilla::gl::SurfaceCaps caps = mozilla::gl::SurfaceCaps::ForRGB();
caps.preserve = false;
caps.bpp16 = false;
+ nsCString discardFailureId;
RefPtr<GLContext> context = GLContextProvider::CreateOffscreen(
IntSize(gCompWidth, gCompHeight), caps,
- CreateContextFlags::REQUIRE_COMPAT_PROFILE);
+ CreateContextFlags::REQUIRE_COMPAT_PROFILE,
+ discardFailureId);
return context.forget().take();
}
return nullptr;
}
NS_IMETHOD Create(nsIWidget* aParent,
nsNativeWidget aNativeParent,
const LayoutDeviceIntRect& aRect,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1316,18 +1316,20 @@ gfxPlatform::GetSkiaGLGlue()
if (!mSkiaGlue) {
/* Dummy context. We always draw into a FBO.
*
* FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
* stands, this only works on the main thread.
*/
RefPtr<GLContext> glContext;
+ nsCString discardFailureId;
glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE |
- CreateContextFlags::ALLOW_OFFLINE_RENDERER);
+ CreateContextFlags::ALLOW_OFFLINE_RENDERER,
+ discardFailureId);
if (!glContext) {
printf_stderr("Failed to create GLContext for SkiaGL!\n");
return nullptr;
}
mSkiaGlue = new SkiaGLGlue(glContext);
MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext");
InitializeSkiaCacheLimits();
}
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -70,17 +70,19 @@ public:
}
void EnsureInitialized() {
if (mReady) {
return;
}
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) {
// Setting mReady to true here means that we won't retry. Everything will
// remain blacklisted forever. Ideally, we would like to update that once
// any GLContext is successfully created, like the compositor's GLContext.
mReady = true;
return;
}