Bug 1214802 - gfxEnv - consolidate environment variables used by the graphics code in one place. r=botond
authorMilan Sreckovic <milan@mozilla.com>
Wed, 28 Oct 2015 14:31:00 +0100
changeset 270435 e9b1d8eb222f8b8a820f88a3cabd5f25c4b48645
parent 270434 c801709386851bf1f2fa4672a26d211035ac004e
child 270436 73e240ab0d9075d8ad60e03143f0590edd5b4451
push id16025
push userkwierso@gmail.com
push dateSat, 31 Oct 2015 00:00:26 +0000
treeherderfx-team@23a54dcff6ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1214802
milestone45.0a1
Bug 1214802 - gfxEnv - consolidate environment variables used by the graphics code in one place. r=botond
gfx/gl/GLContext.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/layers/LayerSorter.cpp
gfx/layers/Layers.cpp
gfx/layers/client/ContentClient.cpp
gfx/layers/composite/CanvasLayerComposite.cpp
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/layers/composite/ImageLayerComposite.cpp
gfx/layers/composite/PaintedLayerComposite.cpp
gfx/layers/ipc/ShadowLayerUtilsX11.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/OGLShaderProgram.cpp
gfx/src/DriverCrashGuard.cpp
gfx/thebes/gfxEnv.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
gfx/thebes/moz.build
layout/base/FrameLayerBuilder.cpp
layout/base/nsLayoutUtils.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -12,16 +12,17 @@
 #include <ctype.h>
 #include <vector>
 
 #include "GLBlitHelper.h"
 #include "GLReadTexImageHelper.h"
 #include "GLScreenBuffer.h"
 
 #include "gfxCrashReporterUtils.h"
+#include "gfxEnv.h"
 #include "gfxUtils.h"
 #include "GLContextProvider.h"
 #include "GLTextureImage.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "prlink.h"
 #include "ScopedGLHelpers.h"
@@ -632,26 +633,26 @@ GLContext::InitWithPrefix(const char *pr
                 mRenderer = GLRenderer(i);
                 break;
             }
         }
     }
 
 
 #ifdef MOZ_GL_DEBUG
-    if (PR_GetEnv("MOZ_GL_DEBUG"))
+    if (gfxEnv::GlDebug())
         sDebugMode |= DebugEnabled;
 
     // enables extra verbose output, informing of the start and finish of every GL call.
     // useful e.g. to record information to investigate graphics system crashes/lockups
-    if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
+    if (gfxEnv::GlDebugVerbose())
         sDebugMode |= DebugTrace;
 
     // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
-    if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
+    if (gfxEnv::GlDebugAbortOnError())
         sDebugMode |= DebugAbortOnError;
 #endif
 
     if (mInitialized) {
         if (ShouldSpew()) {
             const char* vendors[size_t(GLVendor::Other)] = {
                 "Intel",
                 "NVIDIA",
@@ -2577,18 +2578,17 @@ GLContext::FlushIfHeavyGLCallsSinceLastF
     }
     MakeCurrent();
     fFlush();
 }
 
 /*static*/ bool
 GLContext::ShouldDumpExts()
 {
-    static bool ret = PR_GetEnv("MOZ_GL_DUMP_EXTS");
-    return ret;
+    return gfxEnv::GlDumpExtensions();
 }
 
 bool
 DoesStringMatch(const char* aString, const char *aWantedString)
 {
     if (!aString || !aWantedString)
         return false;
 
@@ -2608,18 +2608,17 @@ DoesStringMatch(const char* aString, con
         return false;
 
     return true;
 }
 
 /*static*/ bool
 GLContext::ShouldSpew()
 {
-    static bool ret = PR_GetEnv("MOZ_GL_SPEW");
-    return ret;
+    return gfxEnv::GlSpew();
 }
 
 void
 SplitByChar(const nsACString& str, const char delim, std::vector<nsCString>* const out)
 {
     uint32_t start = 0;
     while (true) {
         int32_t end = str.FindChar(' ', start);
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -21,16 +21,17 @@
 #include "prenv.h"
 #include "GLContextProvider.h"
 #include "GLLibraryLoader.h"
 #include "nsDebug.h"
 #include "nsIWidget.h"
 #include "GLXLibrary.h"
 #include "gfxXlibSurface.h"
 #include "gfxContext.h"
+#include "gfxEnv.h"
 #include "gfxPlatform.h"
 #include "GLContextGLX.h"
 #include "gfxUtils.h"
 #include "gfx2DGlue.h"
 #include "GLScreenBuffer.h"
 
 #include "gfxCrashReporterUtils.h"
 
@@ -93,17 +94,17 @@ GLXLibrary::EnsureInitialized()
         mOGLLibrary = PR_LoadLibrary(libGLfilename);
         if (!mOGLLibrary) {
             NS_WARNING("Couldn't load OpenGL shared library.");
             return false;
         }
         reporter.SetSuccessful();
     }
 
-    if (PR_GetEnv("MOZ_GLX_DEBUG")) {
+    if (gfxEnv::GlxDebug()) {
         mDebug = true;
     }
 
     GLLibraryLoader::SymLoadStruct symbols[] = {
         /* functions that were in GLX 1.0 */
         { (PRFuncPtr*) &xDestroyContextInternal, { "glXDestroyContext", nullptr } },
         { (PRFuncPtr*) &xMakeCurrentInternal, { "glXMakeCurrent", nullptr } },
         { (PRFuncPtr*) &xSwapBuffersInternal, { "glXSwapBuffers", nullptr } },
@@ -1278,26 +1279,18 @@ GLContextProviderGLX::CreateOffscreen(co
         return nullptr;
 
     return gl.forget();
 }
 
 /*static*/ GLContext*
 GLContextProviderGLX::GetGlobalContext()
 {
-    static bool checkedContextSharing = false;
-    static bool useContextSharing = false;
-
-    if (!checkedContextSharing) {
-        useContextSharing = getenv("MOZ_DISABLE_CONTEXT_SHARING_GLX") == 0;
-        checkedContextSharing = true;
-    }
-
     // TODO: get GLX context sharing to work well with multiple threads
-    if (!useContextSharing) {
+    if (gfxEnv::DisableContextSharingGlx()) {
         return nullptr;
     }
 
     static bool triedToCreateContext = false;
     if (!triedToCreateContext && !gGlobalContext) {
         triedToCreateContext = true;
 
         IntSize dummySize = IntSize(16, 16);
--- a/gfx/layers/LayerSorter.cpp
+++ b/gfx/layers/LayerSorter.cpp
@@ -5,16 +5,17 @@
 
 #include "LayerSorter.h"
 #include <math.h>                       // for fabs
 #include <stdint.h>                     // for uint32_t
 #include <stdio.h>                      // for fprintf, stderr, FILE
 #include <stdlib.h>                     // for getenv
 #include "DirectedGraph.h"              // for DirectedGraph
 #include "Layers.h"                     // for Layer
+#include "gfxEnv.h"                     // for gfxEnv
 #include "gfxLineSegment.h"             // for gfxLineSegment
 #include "gfxPoint.h"                   // for gfxPoint
 #include "gfxQuad.h"                    // for gfxQuad
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxTypes.h"                   // for gfxFloat
 #include "mozilla/gfx/BasePoint3D.h"    // for BasePoint3D
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsTArray, etc
@@ -147,18 +148,16 @@ static LayerSortOrder CompareDepth(Layer
   if (fabs(highest) < 0.1 || highest >= 0) {
     return ABeforeB;
   } else {
     return BBeforeA;
   }
 }
 
 #ifdef DEBUG
-static bool gDumpLayerSortList = getenv("MOZ_DUMP_LAYER_SORT_LIST") != 0;
-
 // #define USE_XTERM_COLORING
 #ifdef USE_XTERM_COLORING
 // List of color values, which can be added to the xterm foreground offset or
 // background offset to generate a xterm color code.
 // NOTE: The colors that we don't explicitly use (by name) are commented out,
 // to avoid triggering Wunused-const-variable build warnings.
 static const int XTERM_FOREGROUND_COLOR_OFFSET = 30;
 static const int XTERM_BACKGROUND_COLOR_OFFSET = 40;
@@ -246,17 +245,17 @@ void SortLayersBy3DZOrder(nsTArray<Layer
 {
   uint32_t nodeCount = aLayers.Length();
   if (nodeCount > MAX_SORTABLE_LAYERS) {
     return;
   }
   DirectedGraph<Layer*> graph;
 
 #ifdef DEBUG
-  if (gDumpLayerSortList) {
+  if (gfxEnv::DumpLayerSortList()) {
     for (uint32_t i = 0; i < nodeCount; i++) {
       if (aLayers.ElementAt(i)->GetDebugColorIndex() == 0) {
         aLayers.ElementAt(i)->SetDebugColorIndex(gColorIndex++);
         if (gColorIndex > 7) {
           gColorIndex = 1;
         }
       }
     }
@@ -275,17 +274,17 @@ void SortLayersBy3DZOrder(nsTArray<Layer
         graph.AddEdge(a, b);
       } else if (order == BBeforeA) {
         graph.AddEdge(b, a);
       }
     }
   }
 
 #ifdef DEBUG
-  if (gDumpLayerSortList) {
+  if (gfxEnv::DumpLayerSortList()) {
     fprintf(stderr, " --- Edge List: --- \n");
     DumpEdgeList(graph);
   }
 #endif
 
   // Build a new array using the graph.
   nsTArray<Layer*> noIncoming;
   nsTArray<Layer*> sortedList;
@@ -342,17 +341,17 @@ void SortLayersBy3DZOrder(nsTArray<Layer
         // Remove all of them!
         graph.RemoveEdgesTo(minNode);
         noIncoming.AppendElement(minNode);
       }
     }
   } while (!noIncoming.IsEmpty());
   NS_ASSERTION(!graph.GetEdgeCount(), "Cycles detected!");
 #ifdef DEBUG
-  if (gDumpLayerSortList) {
+  if (gfxEnv::DumpLayerSortList()) {
     fprintf(stderr, " --- Layers after sorting: --- \n");
     DumpLayerList(sortedList);
   }
 #endif
 
   aLayers.Clear();
   aLayers.AppendElements(sortedList);
 }
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -10,16 +10,17 @@
 #include "apz/src/AsyncPanZoomController.h"
 #include "CompositableHost.h"           // for CompositableHost
 #include "ImageContainer.h"             // for ImageContainer, etc
 #include "ImageLayers.h"                // for ImageLayer
 #include "LayerSorter.h"                // for SortLayersBy3DZOrder
 #include "LayersLogging.h"              // for AppendToString
 #include "ReadbackLayer.h"              // for ReadbackLayer
 #include "UnitTransforms.h"             // for ViewAs
+#include "gfxEnv.h"
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxPrefs.h"
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "gfx2DGlue.h"
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/Telemetry.h"          // for Accumulate
 #include "mozilla/dom/Animation.h"      // for ComputedTimingFunction
 #include "mozilla/gfx/2D.h"             // for DrawTarget
@@ -1357,17 +1358,17 @@ ContainerLayer::DefaultComputeEffectiveT
     idealTransform.ProjectTo2D();
   }
 
   bool useIntermediateSurface;
   if (HasMaskLayers() ||
       GetForceIsolatedGroup()) {
     useIntermediateSurface = true;
 #ifdef MOZ_DUMP_PAINTING
-  } else if (gfxUtils::sDumpPaintingIntermediate && !Extend3DContext()) {
+  } else if (gfxEnv::DumpPaintIntermediate() && !Extend3DContext()) {
     useIntermediateSurface = true;
 #endif
   } else {
     float opacity = GetEffectiveOpacity();
     CompositionOp blendMode = GetEffectiveMixBlendMode();
     if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) ||
         (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
       useIntermediateSurface = true;
@@ -1680,19 +1681,19 @@ void WriteSnapshotToDumpFile(Compositor*
   WriteSnapshotToDumpFile_internal(aCompositor, dSurf);
 }
 #endif
 
 void
 Layer::Dump(std::stringstream& aStream, const char* aPrefix, bool aDumpHtml)
 {
 #ifdef MOZ_DUMP_PAINTING
-  bool dumpCompositorTexture = gfxUtils::sDumpCompositorTextures && AsLayerComposite() &&
+  bool dumpCompositorTexture = gfxEnv::DumpCompositorTextures() && AsLayerComposite() &&
                                AsLayerComposite()->GetCompositableHost();
-  bool dumpClientTexture = gfxUtils::sDumpPainting && AsShadowableLayer() &&
+  bool dumpClientTexture = gfxEnv::DumpPaint() && AsShadowableLayer() &&
                            AsShadowableLayer()->GetCompositableClient();
   nsCString layerId(Name());
   layerId.Append('-');
   layerId.AppendInt((uint64_t)this);
 #endif
   if (aDumpHtml) {
     aStream << nsPrintfCString("<li><a id=\"%p\" ", this).get();
 #ifdef MOZ_DUMP_PAINTING
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/ContentClient.h"
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "gfxEnv.h"                     // for gfxEnv
 #include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxPoint.h"                   // for IntSize, gfxPoint
 #include "gfxTeeSurface.h"              // for gfxTeeSurface
 #include "gfxUtils.h"                   // for gfxUtils
 #include "ipc/ShadowLayers.h"           // for ShadowLayerForwarder
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/gfx/2D.h"             // for DrawTarget, Factory
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
@@ -21,17 +22,16 @@
 #include "mozilla/layers/CompositorChild.h" // for CompositorChild
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersMessages.h"  // for ThebesBufferData
 #include "mozilla/layers/LayersTypes.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsIWidget.h"                  // for nsIWidget
-#include "prenv.h"                      // for PR_GetEnv
 #include "nsLayoutUtils.h"
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
 #endif
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPlatformGtk.h"
 #endif
 #include "ReadbackLayer.h"
@@ -83,17 +83,17 @@ ContentClient::CreateContentClient(Compo
       !gfxPlatformGtk::GetPlatform()->UseXRender())
 #endif
   {
     useDoubleBuffering = (LayerManagerComposite::SupportsDirectTexturing() &&
                          backend != LayersBackend::LAYERS_D3D9) ||
                          backend == LayersBackend::LAYERS_BASIC;
   }
 
-  if (useDoubleBuffering || PR_GetEnv("MOZ_FORCE_DOUBLE_BUFFERING")) {
+  if (useDoubleBuffering || gfxEnv::ForceDoubleBuffering()) {
     return MakeAndAddRef<ContentClientDoubleBuffered>(aForwarder);
   }
   return MakeAndAddRef<ContentClientSingleBuffered>(aForwarder);
 }
 
 void
 ContentClient::EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
 {
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CanvasLayerComposite.h"
 #include "composite/CompositableHost.h"  // for CompositableHost
 #include "gfx2DGlue.h"                  // for ToFilter
-#include "gfxUtils.h"                   // for gfxUtils, etc
+#include "gfxEnv.h"                     // for gfxEnv, etc
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
 #include "mozilla/RefPtr.h"                   // for nsRefPtr
@@ -83,17 +83,17 @@ CanvasLayerComposite::RenderLayer(const 
 {
   if (!mCompositableHost || !mCompositableHost->IsAttached()) {
     return;
   }
 
   mCompositor->MakeCurrent();
 
 #ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpCompositorTextures) {
+  if (gfxEnv::DumpCompositorTextures()) {
     RefPtr<gfx::DataSourceSurface> surf = mCompositableHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
   RenderWithAllMasks(this, mCompositor, aClipRect,
                      [&](EffectChain& effectChain, const Rect& clipRect) {
     mCompositableHost->Composite(this, effectChain,
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContainerLayerComposite.h"
 #include <algorithm>                    // for min
 #include "apz/src/AsyncPanZoomController.h"  // for AsyncPanZoomController
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for LayerRect, LayerPixel, etc
+#include "gfxEnv.h"                     // for gfxEnv
 #include "gfxPrefs.h"                   // for gfxPrefs
-#include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/UniquePtr.h"          // for UniquePtr
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor, etc
@@ -35,17 +35,17 @@
 #include "GeckoProfiler.h"              // for GeckoProfiler
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "ProfilerMarkers.h"            // for ProfilerMarkers
 #endif
 
 #define CULLING_LOG(...)
 // #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
 
-#define DUMP(...) do { if (getenv("DUMP_DEBUG")) { printf_stderr(__VA_ARGS__); } } while(0)
+#define DUMP(...) do { if (gfxEnv::DumpDebug()) { printf_stderr(__VA_ARGS__); } } while(0)
 #define XYWH(k)  (k).x, (k).y, (k).width, (k).height
 #define XY(k)    (k).x, (k).y
 #define WH(k)    (k).width, (k).height
 
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
@@ -158,17 +158,17 @@ ContainerRenderVR(ContainerT* aContainer
   // into max texture size limits
   gfx::IntRect surfaceRect = gfx::IntRect(0, 0, eyeResolution.width * 2, eyeResolution.height);
 
   int32_t maxTextureSize = compositor->GetMaxTextureSize();
   surfaceRect.width = std::min(maxTextureSize, surfaceRect.width);
   surfaceRect.height = std::min(maxTextureSize, surfaceRect.height);
 
   gfx::VRHMDRenderingSupport *vrRendering = aHMD->GetRenderingSupport();
-  if (PR_GetEnv("NO_VR_RENDERING")) vrRendering = nullptr;
+  if (gfxEnv::NoVRRendering()) vrRendering = nullptr;
   if (vrRendering) {
     if (!aContainer->mVRRenderTargetSet || aContainer->mVRRenderTargetSet->size != surfaceRect.Size()) {
       aContainer->mVRRenderTargetSet = vrRendering->CreateRenderTargetSet(compositor, surfaceRect.Size());
     }
 
     surface = aContainer->mVRRenderTargetSet->GetNextRenderTarget();
     if (!surface) {
       NS_WARNING("GetNextRenderTarget failed");
@@ -292,17 +292,17 @@ ContainerRenderVR(ContainerT* aContainer
   // to do this? (e.g. something like Cardboard would not require distortion so will fill
   // the entire rect)
   EffectChain solidEffect(aContainer);
   solidEffect.mPrimaryEffect = new EffectSolidColor(Color(0.0, 0.0, 0.0, 1.0));
   aManager->GetCompositor()->DrawQuad(rect, rect, solidEffect, 1.0, gfx::Matrix4x4());
 
   // draw the temporary surface with VR distortion to the original destination
   EffectChain vrEffect(aContainer);
-  bool skipDistortion = vrRendering || PR_GetEnv("MOZ_GFX_VR_NO_DISTORTION");
+  bool skipDistortion = vrRendering || gfxEnv::VRNoDistortion();
   if (skipDistortion) {
     vrEffect.mPrimaryEffect = new EffectRenderTarget(surface);
   } else {
     vrEffect.mPrimaryEffect = new EffectVRDistortion(aHMD, surface);
   }
 
   gfx::Matrix4x4 scaleTransform = aContainer->GetEffectiveTransform();
   scaleTransform.PreScale(rtBounds.width / float(surfaceRect.width),
@@ -703,17 +703,17 @@ ContainerRender(ContainerT* aContainer,
     if (!surface) {
       aContainer->mPrepared = nullptr;
       return;
     }
 
     gfx::Rect visibleRect(aContainer->GetEffectiveVisibleRegion().GetBounds());
     RefPtr<Compositor> compositor = aManager->GetCompositor();
 #ifdef MOZ_DUMP_PAINTING
-    if (gfxUtils::sDumpCompositorTextures) {
+    if (gfxEnv::DumpCompositorTextures()) {
       RefPtr<gfx::DataSourceSurface> surf = surface->Dump(compositor);
       if (surf) {
         WriteSnapshotToDumpFile(aContainer, surf);
       }
     }
 #endif
 
     RefPtr<ContainerT> container = aContainer;
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -2,18 +2,18 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ImageLayerComposite.h"
 #include "CompositableHost.h"           // for CompositableHost
 #include "Layers.h"                     // for WriteSnapshotToDumpFile, etc
 #include "gfx2DGlue.h"                  // for ToFilter
+#include "gfxEnv.h"                     // for gfxEnv
 #include "gfxRect.h"                    // for gfxRect
-#include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "mozilla/mozalloc.h"           // for operator delete
@@ -82,17 +82,17 @@ ImageLayerComposite::GetLayer()
 void
 ImageLayerComposite::RenderLayer(const IntRect& aClipRect)
 {
   if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
 #ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpCompositorTextures) {
+  if (gfxEnv::DumpCompositorTextures()) {
     RefPtr<gfx::DataSourceSurface> surf = mImageHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
   mCompositor->MakeCurrent();
 
   RenderWithAllMasks(this, mCompositor, aClipRect,
--- a/gfx/layers/composite/PaintedLayerComposite.cpp
+++ b/gfx/layers/composite/PaintedLayerComposite.cpp
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PaintedLayerComposite.h"
 #include "CompositableHost.h"           // for TiledLayerProperties, etc
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for CSSRect, LayerPixel, etc
-#include "gfxUtils.h"                   // for gfxUtils, etc
+#include "gfxEnv.h"                     // for gfxEnv
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for RoundedToInt, Rect
 #include "mozilla/gfx/Types.h"          // for Filter::Filter::LINEAR
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ContentHost.h"  // for ContentHost
 #include "mozilla/layers/Effects.h"     // for EffectChain
@@ -110,17 +110,17 @@ PaintedLayerComposite::RenderLayer(const
 
   MOZ_ASSERT(mBuffer->GetCompositor() == compositor &&
              mBuffer->GetLayer() == this,
              "buffer is corrupted");
 
   const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
 
 #ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpCompositorTextures) {
+  if (gfxEnv::DumpCompositorTextures()) {
     RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface();
     if (surf) {
       WriteSnapshotToDumpFile(this, surf);
     }
   }
 #endif
 
 
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
@@ -20,37 +20,37 @@
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorTypes.h"  // for OpenMode
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator, etc
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder, etc
 #include "mozilla/mozalloc.h"           // for operator new
+#include "gfxEnv.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ERROR
-#include "prenv.h"                      // for PR_GetEnv
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace gl {
 class GLContext;
 class TextureImage;
 }
 
 namespace layers {
 
 // Return true if we're likely compositing using X and so should use
 // Xlib surfaces in shadow layers.
 static bool
 UsingXCompositing()
 {
-  if (!PR_GetEnv("MOZ_LAYERS_ENABLE_XLIB_SURFACES")) {
+  if (!gfxEnv::LayersEnableXlibSurfaces()) {
       return false;
   }
   return (gfxSurfaceType::Xlib ==
           gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType());
 }
 
 // LookReturn a pointer to |aFormat| that lives in the Xrender library.
 // All code using render formats assumes it doesn't need to copy.
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -8,20 +8,21 @@
 #include <stdint.h>                     // for uint32_t, uint8_t
 #include <stdlib.h>                     // for free, malloc
 #include "GLContextProvider.h"          // for GLContextProvider
 #include "GLContext.h"                  // for GLContext
 #include "GLUploadHelpers.h"
 #include "Layers.h"                     // for WriteSnapshotToDumpFile
 #include "LayerScope.h"                 // for LayerScope
 #include "gfxCrashReporterUtils.h"      // for ScopedGfxFeatureReporter
+#include "gfxEnv.h"                     // for gfxEnv
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxPrefs.h"                   // for gfxPrefs
 #include "gfxRect.h"                    // for gfxRect
-#include "gfxUtils.h"                   // for NextPowerOfTwo, gfxUtils, etc
+#include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4, Matrix
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite, etc
 #include "mozilla/layers/CompositingRenderTargetOGL.h"
 #include "mozilla/layers/Effects.h"     // for EffectChain, TexturedEffect, etc
 #include "mozilla/layers/TextureHost.h"  // for TextureSource, etc
@@ -99,24 +100,24 @@ CompositorOGL::CreateContext()
   // Used by mock widget to create an offscreen context
   void* widgetOpenGLContext = mWidget->GetNativeData(NS_NATIVE_OPENGL_CONTEXT);
   if (widgetOpenGLContext) {
     GLContext* alreadyRefed = reinterpret_cast<GLContext*>(widgetOpenGLContext);
     return already_AddRefed<GLContext>(alreadyRefed);
   }
 
 #ifdef XP_WIN
-  if (PR_GetEnv("MOZ_LAYERS_PREFER_EGL")) {
+  if (gfxEnv::LayersPreferEGL()) {
     printf_stderr("Trying GL layers...\n");
     context = gl::GLContextProviderEGL::CreateForWindow(mWidget);
   }
 #endif
 
   // Allow to create offscreen GL context for main Layer Manager
-  if (!context && PR_GetEnv("MOZ_LAYERS_PREFER_OFFSCREEN")) {
+  if (!context && gfxEnv::LayersPreferOffscreen()) {
     SurfaceCaps caps = SurfaceCaps::ForRGB();
     caps.preserve = false;
     caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == gfxImageFormat::RGB16_565;
 
     context = GLContextProvider::CreateOffscreen(mSurfaceSize,
                                                  caps, CreateContextFlags::REQUIRE_COMPAT_PROFILE);
   }
 
@@ -1383,17 +1384,17 @@ void
 CompositorOGL::EndFrame()
 {
   PROFILER_LABEL("CompositorOGL", "EndFrame",
     js::ProfileEntry::Category::GRAPHICS);
 
   MOZ_ASSERT(mCurrentRenderTarget == mWindowRenderTarget, "Rendering target not properly restored");
 
 #ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpCompositorTextures) {
+  if (gfxEnv::DumpCompositorTextures()) {
     IntRect rect;
     if (mUseExternalSurfaceSize) {
       rect = IntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
     } else {
       mWidget->GetBounds(rect);
     }
     RefPtr<DrawTarget> target = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(rect.width, rect.height), SurfaceFormat::B8G8R8A8);
     if (target) {
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -1,21 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "OGLShaderProgram.h"
 #include <stdint.h>                     // for uint32_t
 #include <sstream>                      // for ostringstream
+#include "gfxEnv.h"
 #include "gfxRect.h"                    // for gfxRect
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsString.h"                   // for nsAutoCString
-#include "prenv.h"                      // for PR_GetEnv
 #include "Layers.h"
 #include "GLContext.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace std;
 
@@ -572,17 +572,17 @@ ShaderProgramOGL::CreateShader(GLenum aS
   mGL->fGetShaderiv(sh, LOCAL_GL_COMPILE_STATUS, &success);
   mGL->fGetShaderiv(sh, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
   /* Even if compiling is successful, there may still be warnings.  Print them
    * in a debug build.  The > 10 is to catch silly compilers that might put
    * some whitespace in the log but otherwise leave it empty.
    */
   if (!success
 #ifdef DEBUG
-      || (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS"))
+      || (len > 10 && gfxEnv::DebugShaders())
 #endif
       )
   {
     nsAutoCString log;
     log.SetCapacity(len);
     mGL->fGetShaderInfoLog(sh, len, (GLint*) &len, (char*) log.BeginWriting());
     log.SetLength(len);
 
@@ -625,17 +625,17 @@ ShaderProgramOGL::CreateProgram(const ch
   mGL->fGetProgramiv(result, LOCAL_GL_LINK_STATUS, &success);
   mGL->fGetProgramiv(result, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
   /* Even if linking is successful, there may still be warnings.  Print them
    * in a debug build.  The > 10 is to catch silly compilers that might put
    * some whitespace in the log but otherwise leave it empty.
    */
   if (!success
 #ifdef DEBUG
-      || (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS"))
+      || (len > 10 && gfxEnv::DebugShaders())
 #endif
       )
   {
     nsAutoCString log;
     log.SetCapacity(len);
     mGL->fGetProgramInfoLog(result, len, (GLint*) &len, (char*) log.BeginWriting());
     log.SetLength(len);
 
--- a/gfx/src/DriverCrashGuard.cpp
+++ b/gfx/src/DriverCrashGuard.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "DriverCrashGuard.h"
+#include "gfxEnv.h"
 #include "gfxPrefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
@@ -66,18 +67,17 @@ DriverCrashGuard::Initialize()
   // e10s it could conceivably work by dispatching the IPC calls via the main
   // thread. In the parent process this would be harder. For now, we simply
   // exit early instead.
   if (!NS_IsMainThread()) {
     return;
   }
 
   // Check to see if all guards have been disabled through the environment.
-  static bool sAllGuardsDisabled = !!PR_GetEnv("MOZ_DISABLE_CRASH_GUARD");
-  if (sAllGuardsDisabled) {
+  if (gfxEnv::DisableCrashGuard()) {
     return;
   }
 
   mGfxInfo = services::GetGfxInfo();
 
   if (XRE_IsContentProcess()) {
     // Ask the parent whether or not activating the guard is okay. The parent
     // won't bother if it detected a crash.
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/gfxEnv.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_ENV_H
+#define GFX_ENV_H
+
+#include "prenv.h"
+
+// To register the check for an environment variable existence (and not empty),
+// add a line in this file using the DECL_GFX_ENV macro.
+//
+// For example this line in the .h:
+//   DECL_GFX_ENV_ONCE("MOZ_DISABLE_CONTEXT_SHARING_GLX",DisableContextSharingGLX);
+// means that you can call
+//   bool var = gfxEnv::DisableContextSharingGLX();
+// and that the value will be checked only once, first time we call it, then cached.
+
+#define DECL_GFX_ENV_LIVE(Env, Name)  \
+  static bool Name() {                \
+    return IsEnvSet(Env);             \
+  }
+
+#define DECL_GFX_ENV_ONCE(Env, Name)  \
+  static bool Name() {                \
+    static bool isSet = IsEnvSet(Env);\
+    return isSet;                     \
+  }
+
+class gfxEnv final
+{
+public:
+  // This is where DECL_GFX_ENV for each of the environment variables should go.
+  // We will keep these in an alphabetical order by the environment variable,
+  // to make it easier to see if a method accessing an entry already exists.
+  // Just insert yours in the list.
+
+  // Debugging inside of ContainerLayerComposite
+  DECL_GFX_ENV_LIVE("DUMP_DEBUG", DumpDebug);
+
+  // OpenGL shader debugging in OGLShaderProgram, in DEBUG only
+  DECL_GFX_ENV_LIVE("MOZ_DEBUG_SHADERS", DebugShaders);
+
+  // Disabling context sharing in GLContextProviderGLX
+  DECL_GFX_ENV_ONCE("MOZ_DISABLE_CONTEXT_SHARING_GLX", DisableContextSharingGlx);
+
+  // Disabling the crash guard in DriverCrashGuard
+  DECL_GFX_ENV_ONCE("MOZ_DISABLE_CRASH_GUARD", DisableCrashGuard);
+
+  // Together with paint dumping, only when MOZ_DUMP_PAINTING is defined.
+  // Dumping compositor textures is broken pretty badly. For example,
+  // on Linux it crashes TextureHost::GetAsSurface() returns null.
+  // Expect to have to fix things like this if you turn it on.
+  // Meanwhile, content-side texture dumping
+  // (conditioned on DebugDumpPainting()) is a good replacement.
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_COMPOSITOR_TEXTURES", DumpCompositorTextures);
+
+  // Dumping the layer list in LayerSorter
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_LAYER_SORT_LIST", DumpLayerSortList);
+
+  // Paint dumping, only when MOZ_DUMP_PAINTING is defined.
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_PAINT", DumpPaint);
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_PAINT_INTERMEDIATE", DumpPaintIntermediate);
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_PAINT_ITEMS", DumpPaintItems);
+  DECL_GFX_ENV_ONCE("MOZ_DUMP_PAINT_TO_FILE", DumpPaintToFile);
+
+  // Force double buffering in ContentClient
+  DECL_GFX_ENV_LIVE("MOZ_FORCE_DOUBLE_BUFFERING", ForceDoubleBuffering);
+
+  // Force gfxCrash to use MOZ_CRASH in Beta and Release
+  DECL_GFX_ENV_ONCE("MOZ_GFX_CRASH_MOZ_CRASH", GfxCrashMozCrash);
+  // Force gfxCrash to use telemetry in Nightly and Aurora
+  DECL_GFX_ENV_ONCE("MOZ_GFX_CRASH_TELEMETRY", GfxCrashTelemetry);
+
+  DECL_GFX_ENV_LIVE("MOZ_GFX_VR_NO_DISTORTION", VRNoDistortion);
+
+  // Debugging in GLContext
+  DECL_GFX_ENV_LIVE("MOZ_GL_DEBUG", GlDebug);
+  DECL_GFX_ENV_LIVE("MOZ_GL_DEBUG_VERBOSE", GlDebugVerbose);
+  DECL_GFX_ENV_LIVE("MOZ_GL_DEBUG_ABORT_ON_ERROR", GlDebugAbortOnError);
+
+  // Count GL extensions
+  DECL_GFX_ENV_ONCE("MOZ_GL_DUMP_EXTS", GlDumpExtensions);
+
+  // Very noisy GLContext and GLContextProviderELG
+  DECL_GFX_ENV_ONCE("MOZ_GL_SPEW", GlSpew);
+
+  // Do extra work before and after each GLX call in GLContextProviderGLX 
+  DECL_GFX_ENV_LIVE("MOZ_GLX_DEBUG", GlxDebug);
+
+  // Use X compositing
+  DECL_GFX_ENV_LIVE("MOZ_LAYERS_ENABLE_XLIB_SURFACES", LayersEnableXlibSurfaces);
+
+  // GL compositing on Windows
+  DECL_GFX_ENV_LIVE("MOZ_LAYERS_PREFER_EGL", LayersPreferEGL);
+
+  // Offscreen GL context for main layer manager
+  DECL_GFX_ENV_LIVE("MOZ_LAYERS_PREFER_OFFSCREEN", LayersPreferOffscreen);
+
+  // Stop the VR rendering
+  DECL_GFX_ENV_LIVE("NO_VR_RENDERING", NoVRRendering);
+
+  // WARNING:
+  // Please make sure that you've added your new envvar to the list above in
+  // alphabetical order. Please do not just append it to the end of the list.
+
+private:
+  // Helper function, can be re-used in the other macros
+  static bool IsEnvSet(const char* aName) {
+    char* val = PR_GetEnv(aName);
+    return (val != 0 && *val != '\0');
+  }
+
+  gfxEnv() {};
+  ~gfxEnv() {};
+  gfxEnv(const gfxEnv&) = delete;
+  gfxEnv& operator=(const gfxEnv&) = delete;
+};
+
+#undef DECL_GFX_ENV_LIVE
+#undef DECL_GFX_ENV_ONCE
+
+#endif /* GFX_ENV_H */
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/Telemetry.h"
 
 #include "mozilla/Logging.h"
 #include "mozilla/Services.h"
 #include "prprf.h"
 
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
+#include "gfxEnv.h"
 #include "gfxTextRun.h"
 #include "gfxVR.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
@@ -305,22 +306,21 @@ protected:
 NS_IMPL_ISUPPORTS_INHERITED0(CrashTelemetryEvent, nsRunnable);
 
 void
 CrashStatsLogForwarder::CrashAction(LogReason aReason)
 {
 #ifndef RELEASE_BUILD
   // Non-release builds crash by default, but will use telemetry
   // if this environment variable is present.
-  static bool useTelemetry = getenv("MOZ_GFX_CRASH_TELEMETRY") != 0;
+  static bool useTelemetry = gfxEnv::GfxCrashTelemetry();
 #else
-  // Release builds use telemetry bu default, but will crash
-  // if this environment variable is present.  Double negative
-  // to make the intent clear.
-  static bool useTelemetry = !(getenv("MOZ_GFX_CRASH_MOZ_CRASH") != 0);
+  // Release builds use telemetry by default, but will crash instead
+  // if this environment variable is present.
+  static bool useTelemetry = !gfxEnv::GfxCrashMozCrash();
 #endif
 
   if (useTelemetry) {
     // The callers need to assure that aReason is in the range
     // that the telemetry call below supports.
     if (NS_IsMainThread()) {
       Telemetry::Accumulate(Telemetry::GFX_CRASH, (uint32_t)aReason);
     } else {
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxUtils.h"
 
 #include "cairo.h"
 #include "gfxContext.h"
+#include "gfxEnv.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxDrawable.h"
 #include "imgIEncoder.h"
 #include "mozilla/Base64.h"
 #include "mozilla/dom/ImageEncoder.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
@@ -1665,30 +1666,16 @@ gfxUtils::ThreadSafeGetFeatureStatus(con
 
 /* static */ bool
 gfxUtils::DumpDisplayList() {
   return gfxPrefs::LayoutDumpDisplayList();
 }
 
 FILE *gfxUtils::sDumpPaintFile = stderr;
 
-#ifdef MOZ_DUMP_PAINTING
-bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT") != 0;
-bool gfxUtils::sDumpPaintingIntermediate = getenv("MOZ_DUMP_PAINT_INTERMEDIATE") != 0;
-bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
-bool gfxUtils::sDumpPaintItems = getenv("MOZ_DUMP_PAINT_ITEMS") != 0;
-bool gfxUtils::sDumpCompositorTextures = getenv("MOZ_DUMP_COMPOSITOR_TEXTURES") != 0;
-#else
-bool gfxUtils::sDumpPainting = false;
-bool gfxUtils::sDumpPaintingIntermediate = false;
-bool gfxUtils::sDumpPaintingToFile = false;
-bool gfxUtils::sDumpPaintItems = false;
-bool gfxUtils::sDumpCompositorTextures = false;
-#endif
-
 namespace mozilla {
 namespace gfx {
 
 Color ToDeviceColor(Color aColor)
 {
   // aColor is pass-by-value since to get return value optimization goodness we
   // need to return the same object from all return points in this function. We
   // could declare a local Color variable and use that, but we might as well
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -300,26 +300,16 @@ public:
     /**
      * Copy to the clipboard as a PNG encoded Data URL.
      */
     static void CopyAsDataURI(SourceSurface* aSourceSurface);
     static void CopyAsDataURI(DrawTarget* aDT);
 
     static bool DumpDisplayList();
 
-    static bool sDumpPainting;
-    static bool sDumpPaintingIntermediate;
-    static bool sDumpPaintingToFile;
-    static bool sDumpPaintItems;
-    // TODO: Dumping compositor textures is broken pretty badly. For example,
-    //       on Linux it crashes because TextureHost::GetAsSurface() returns
-    //       null. Expect to have to fix things like this if you turn it on.
-    //       Meanwhile, content-side texture dumping (conditioned on
-    //       sDumpPainting) is a good replacement.
-    static bool sDumpCompositorTextures;
     static FILE* sDumpPaintFile;
 };
 
 namespace mozilla {
 namespace gfx {
 
 /**
  * If the CMS mode is eCMSMode_All, these functions transform the passed
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -10,16 +10,17 @@ EXPORTS += [
     'gfx2DGlue.h',
     'gfxAlphaRecovery.h',
     'gfxASurface.h',
     'gfxBaseSharedMemorySurface.h',
     'gfxBlur.h',
     'gfxColor.h',
     'gfxContext.h',
     'gfxDrawable.h',
+    'gfxEnv.h',
     'gfxFailure.h',
     'gfxFont.h',
     'gfxFontConstants.h',
     'gfxFontEntry.h',
     'gfxFontFamilyList.h',
     'gfxFontFeatures.h',
     'gfxFontInfoLoader.h',
     'gfxFontPrefLangList.h',
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -17,16 +17,17 @@
 #include "ImageLayers.h"
 #include "LayerTreeInvalidation.h"
 #include "Layers.h"
 #include "LayerUserData.h"
 #include "MaskLayerImageCache.h"
 #include "UnitTransforms.h"
 #include "Units.h"
 #include "gfx2DGlue.h"
+#include "gfxEnv.h"
 #include "gfxUtils.h"
 #include "nsDisplayList.h"
 #include "nsDocShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsImageFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
@@ -3648,17 +3649,17 @@ PaintInactiveLayer(nsDisplayListBuilder*
   BasicLayerManager* basic = static_cast<BasicLayerManager*>(aManager);
   RefPtr<gfxContext> context = aContext;
 #ifdef MOZ_DUMP_PAINTING
   int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
   nsIntRect itemVisibleRect =
     aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
 
   RefPtr<DrawTarget> tempDT;
-  if (gfxUtils::sDumpPainting) {
+  if (gfxEnv::DumpPaint()) {
     tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
                                       itemVisibleRect.Size(),
                                       SurfaceFormat::B8G8R8A8);
     if (tempDT) {
       context = new gfxContext(tempDT);
       context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x,
                                                 -itemVisibleRect.y));
     }
@@ -3678,17 +3679,17 @@ PaintInactiveLayer(nsDisplayListBuilder*
   FrameLayerBuilder *builder = static_cast<FrameLayerBuilder*>(basic->GetUserData(&gLayerManagerLayerBuilder));
   if (builder) {
     builder->DidEndTransaction();
   }
 
   basic->SetTarget(nullptr);
 
 #ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpPainting && tempDT) {
+  if (gfxEnv::DumpPaint() && tempDT) {
     RefPtr<SourceSurface> surface = tempDT->Snapshot();
     DumpPaintedImage(aItem, surface);
 
     DrawTarget* drawTarget = aContext->GetDrawTarget();
     Rect rect(itemVisibleRect.x, itemVisibleRect.y,
               itemVisibleRect.width, itemVisibleRect.height);
     drawTarget->DrawSurface(surface, rect, Rect(Point(0,0), rect.Size()));
 
@@ -4498,20 +4499,20 @@ FrameLayerBuilder::AddPaintedDisplayItem
         layerBuilder->StoreDataForFrame(aItem, tmpLayer, LAYER_ACTIVE);
       }
 
       tempManager->SetRoot(tmpLayer);
       layerBuilder->WillEndTransaction();
       tempManager->AbortTransaction();
 
 #ifdef MOZ_DUMP_PAINTING
-      if (gfxUtils::DumpDisplayList() || gfxUtils::sDumpPainting) {
+      if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) {
         fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem->Name(), aItem->Frame());
         std::stringstream stream;
-        tempManager->Dump(stream, "", gfxUtils::sDumpPaintingToFile);
+        tempManager->Dump(stream, "", gfxEnv::DumpPaintToFile());
         fprint_stderr(gfxUtils::sDumpPaintFile, stream);  // not a typo, fprint_stderr declared in LayersLogging.h
       }
 #endif
 
       nsIntPoint offset = GetLastPaintOffset(layer) - GetTranslationForPaintedLayer(layer);
       props->MoveBy(-offset);
       nsIntRegion invalid = props->ComputeDifferences(tmpLayer, nullptr);
       if (aLayerState == LAYER_SVG_EFFECTS) {
@@ -5714,17 +5715,17 @@ FrameLayerBuilder::PaintItems(nsTArray<C
     if (cdi->mInactiveLayerManager) {
       bool saved = aDrawTarget.GetPermitSubpixelAA();
       PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
       aDrawTarget.SetPermitSubpixelAA(saved);
     } else {
       nsIFrame* frame = cdi->mItem->Frame();
       frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
 #ifdef MOZ_DUMP_PAINTING
-      if (gfxUtils::sDumpPaintItems) {
+      if (gfxEnv::DumpPaintItems()) {
         DebugPaintItem(aDrawTarget, aPresContext, cdi->mItem, aBuilder);
       } else {
 #else
       {
 #endif
         cdi->mItem->Paint(aBuilder, aRC);
       }
     }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -68,16 +68,17 @@
 #include "imgIRequest.h"
 #include "nsIImageLoadingContent.h"
 #include "nsCOMPtr.h"
 #include "nsCSSProps.h"
 #include "nsListControlFrame.h"
 #include "mozilla/dom/Element.h"
 #include "nsCanvasFrame.h"
 #include "gfxDrawable.h"
+#include "gfxEnv.h"
 #include "gfxUtils.h"
 #include "nsDataHashtable.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
 #include "nsFontInflationData.h"
 #include "nsSVGUtils.h"
 #include "SVGImageContext.h"
 #include "SVGTextFrame.h"
@@ -3294,57 +3295,57 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
            builder, list, aFrame, canvasArea, aBackstop);
   }
 
   builder.LeavePresShell(aFrame);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,
                                  startBuildDisplayList);
 
   bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump");
-  bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxUtils::sDumpPainting;
+  bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint();
 #ifdef MOZ_DUMP_PAINTING
   FILE* savedDumpFile = gfxUtils::sDumpPaintFile;
 #endif
 
   UniquePtr<std::stringstream> ss;
   if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
     ss = MakeUnique<std::stringstream>();
 #ifdef MOZ_DUMP_PAINTING
-    if (gfxUtils::sDumpPaintingToFile) {
+    if (gfxEnv::DumpPaintToFile()) {
       nsCString string("dump-");
       // Include the process ID in the dump file name, to make sure that in an
       // e10s setup different processes don't clobber each other's dump files.
       string.AppendInt(getpid());
       for (int paintCount : *gPaintCountStack) {
         string.AppendLiteral("-");
         string.AppendInt(paintCount);
       }
       string.AppendLiteral(".html");
       gfxUtils::sDumpPaintFile = fopen(string.BeginReading(), "w");
     } else {
       gfxUtils::sDumpPaintFile = stderr;
     }
-    if (gfxUtils::sDumpPaintingToFile) {
+    if (gfxEnv::DumpPaintToFile()) {
       *ss << "<html><head><script>\n"
              "var array = {};\n"
              "function ViewImage(index) { \n"
              "  var image = document.getElementById(index);\n"
              "  if (image.src) {\n"
              "    image.removeAttribute('src');\n"
              "  } else {\n"
              "    image.src = array[index];\n"
              "  }\n"
              "}</script></head><body>";
     }
 #endif
     *ss << nsPrintfCString("Painting --- before optimization (dirty %d,%d,%d,%d):\n",
             dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height).get();
-    nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
-
-    if (gfxUtils::sDumpPainting || gfxUtils::sDumpPaintItems) {
+    nsFrame::PrintDisplayList(&builder, list, *ss, gfxEnv::DumpPaintToFile());
+
+    if (gfxEnv::DumpPaint() || gfxEnv::DumpPaintItems()) {
       // Flush stream now to avoid reordering dump output relative to
       // messages dumped by PaintRoot below.
       if (profilerNeedsDisplayList && !consoleNeedsDisplayList) {
         profiler_log(ss->str().c_str());
       } else {
         // Send to the console which will send to the profiler if required.
         fprint_stderr(gfxUtils::sDumpPaintFile, *ss);
       }
@@ -3377,36 +3378,36 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   TimeStamp paintStart = TimeStamp::Now();
   RefPtr<LayerManager> layerManager =
     list.PaintRoot(&builder, aRenderingContext, flags);
   Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME,
                                  paintStart);
 
   if (consoleNeedsDisplayList || profilerNeedsDisplayList) {
     *ss << "Painting --- after optimization:\n";
-    nsFrame::PrintDisplayList(&builder, list, *ss, gfxUtils::sDumpPaintingToFile);
+    nsFrame::PrintDisplayList(&builder, list, *ss, gfxEnv::DumpPaintToFile());
 
     *ss << "Painting --- layer tree:\n";
     if (layerManager) {
       FrameLayerBuilder::DumpRetainedLayerTree(layerManager, *ss,
-                                               gfxUtils::sDumpPaintingToFile);
+                                               gfxEnv::DumpPaintToFile());
     }
 
     if (profilerNeedsDisplayList && !consoleNeedsDisplayList) {
       profiler_log(ss->str().c_str());
     } else {
       // Send to the console which will send to the profiler if required.
       fprint_stderr(gfxUtils::sDumpPaintFile, *ss);
     }
 
 #ifdef MOZ_DUMP_PAINTING
-    if (gfxUtils::sDumpPaintingToFile) {
+    if (gfxEnv::DumpPaintToFile()) {
       *ss << "</body></html>";
     }
-    if (gfxUtils::sDumpPaintingToFile) {
+    if (gfxEnv::DumpPaintToFile()) {
       fclose(gfxUtils::sDumpPaintFile);
     }
     gfxUtils::sDumpPaintFile = savedDumpFile;
 #endif
 
     std::stringstream lsStream;
     nsFrame::PrintDisplayList(&builder, list, lsStream);
     layerManager->GetRoot()->SetDisplayListLog(lsStream.str().c_str());