Bug 912974 - Split two classes out of GLContext.h, and remove many #includes in GLContext.h - r=jrmuizel
authorBenoit Jacob <bjacob@mozilla.com>
Fri, 06 Sep 2013 22:13:37 -0400
changeset 154037 e2f23b6aaf7530ca242aecb52b20f81f280b89cb
parent 154036 59d8b8c4f9f650470525e0871e13747b46fbe249
child 154038 d39afeecef6602ecb8704e82fd4661d1a8e9a594
push idunknown
push userunknown
push dateunknown
reviewersjrmuizel
bugs912974
milestone26.0a1
Bug 912974 - Split two classes out of GLContext.h, and remove many #includes in GLContext.h - r=jrmuizel
content/canvas/src/WebGL2Context.cpp
content/canvas/src/WebGLContextExtensions.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextUtils.cpp
gfx/gl/GfxTexturesReporter.cpp
gfx/gl/GfxTexturesReporter.h
gfx/gl/SharedSurfaceEGL.cpp
gfx/gl/SharedSurfaceEGL.h
gfx/gl/TextureGarbageBin.cpp
gfx/gl/TextureGarbageBin.h
gfx/gl/moz.build
gfx/layers/opengl/TextureHostOGL.cpp
--- a/content/canvas/src/WebGL2Context.cpp
+++ b/content/canvas/src/WebGL2Context.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "WebGL2Context.h"
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
-
+#include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
 // -----------------------------------------------------------------------------
 // CONSTRUCTOR & DESTRUCTOR
 
--- a/content/canvas/src/WebGLContextExtensions.cpp
+++ b/content/canvas/src/WebGLContextExtensions.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
 #include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
 #include "GLContext.h"
 
 #include "nsString.h"
-
+#include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
 // must match WebGLContext::WebGLExtensionID
 static const char *sExtensionNames[] = {
     "EXT_texture_filter_anisotropic",
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -53,16 +53,17 @@ using mozilla::DefaultXDisplay;
 #include "nsAttrName.h"
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
 #include "ImageContainer.h"
 #include "nsIDOMHTMLCollection.h"
+#include "GLContext.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2,30 +2,32 @@
 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
 /* 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 <algorithm>
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "GLContext.h"
 
 #include "gfxCrashReporterUtils.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "GLContextProvider.h"
 #include "GLTextureImage.h"
-#include "nsIMemoryReporter.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "prlink.h"
 #include "SurfaceStream.h"
+#include "GfxTexturesReporter.h"
+#include "TextureGarbageBin.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
 
 #ifdef XP_MACOSX
 #include <CoreServices/CoreServices.h>
 #endif
 
@@ -109,31 +111,16 @@ static const char *sExtensionNames[] = {
     "GL_ANGLE_instanced_arrays",
     "GL_EXT_occlusion_query_boolean",
     "GL_ARB_occlusion_query2",
     "GL_EXT_transform_feedback",
     "GL_NV_transform_feedback",
     nullptr
 };
 
-int64_t GfxTexturesReporter::sAmount = 0;
-
-/* static */ void
-GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format,
-                                  GLenum type, uint16_t tileSize)
-{
-    uint32_t bytesPerTexel = mozilla::gl::GetBitsPerTexel(format, type) / 8;
-    int64_t bytes = (int64_t)(tileSize * tileSize * bytesPerTexel);
-    if (action == MemoryFreed) {
-        sAmount -= bytes;
-    } else {
-        sAmount += bytes;
-    }
-}
-
 static bool
 ParseGLVersion(GLContext* gl, unsigned int* version)
 {
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
         MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
         return false;
     }
@@ -242,16 +229,72 @@ ParseGLVersion(GLContext* gl, unsigned i
         MOZ_ASSERT(false, "Invalid minor version.");
         return false;
     }
 
     *version = (unsigned int)(majorVersion * 100 + minorVersion * 10);
     return true;
 }
 
+GLContext::GLContext(const SurfaceCaps& caps,
+          GLContext* sharedContext,
+          bool isOffscreen)
+  : mInitialized(false),
+    mIsOffscreen(isOffscreen),
+    mIsGlobalSharedContext(false),
+    mContextLost(false),
+    mVersion(0),
+    mProfile(ContextProfile::Unknown),
+    mVendor(-1),
+    mRenderer(-1),
+    mHasRobustness(false),
+#ifdef DEBUG
+    mGLError(LOCAL_GL_NO_ERROR),
+#endif
+    mTexBlit_Buffer(0),
+    mTexBlit_VertShader(0),
+    mTex2DBlit_FragShader(0),
+    mTex2DRectBlit_FragShader(0),
+    mTex2DBlit_Program(0),
+    mTex2DRectBlit_Program(0),
+    mTexBlit_UseDrawNotCopy(false),
+    mSharedContext(sharedContext),
+    mFlipped(false),
+    mBlitProgram(0),
+    mBlitFramebuffer(0),
+    mCaps(caps),
+    mScreen(nullptr),
+    mLockedSurface(nullptr),
+    mMaxTextureSize(0),
+    mMaxCubeMapTextureSize(0),
+    mMaxTextureImageSize(0),
+    mMaxRenderbufferSize(0),
+    mNeedsTextureSizeChecks(false),
+    mWorkAroundDriverBugs(true)
+{
+    mOwningThread = NS_GetCurrentThread();
+
+    mTexBlit_UseDrawNotCopy = Preferences::GetBool("gl.blit-draw-not-copy", false);
+}
+
+GLContext::~GLContext() {
+    NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
+#ifdef DEBUG
+    if (mSharedContext) {
+        GLContext *tip = mSharedContext;
+        while (tip->mSharedContext)
+            tip = tip->mSharedContext;
+        tip->SharedContextDestroyed(this);
+        tip->ReportOutstandingNames();
+    } else {
+        ReportOutstandingNames();
+    }
+#endif
+}
+
 bool
 GLContext::InitWithPrefix(const char *prefix, bool trygl)
 {
     ScopedGfxFeatureReporter reporter("GL Context");
 
     if (mInitialized) {
         reporter.SetSuccessful();
         return true;
@@ -3393,44 +3436,60 @@ GLContext::CleanDirtyScreen()
 }
 
 void
 GLContext::EmptyTexGarbageBin()
 {
    TexGarbageBin()->EmptyGarbage();
 }
 
-
-void
-TextureGarbageBin::GLContextTeardown()
+bool
+GLContext::IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
+  int32_t biggerDimension = std::max(aSize.width, aSize.height);
+  int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
+  return biggerDimension <= maxAllowed;
+}
+
+bool
+GLContext::IsOwningThreadCurrent()
 {
-    EmptyGarbage();
-
-    MutexAutoLock lock(mMutex);
-    mGL = nullptr;
+  return NS_GetCurrentThread() == mOwningThread;
 }
 
 void
-TextureGarbageBin::Trash(GLuint tex)
+GLContext::DispatchToOwningThread(nsIRunnable *event)
 {
-    MutexAutoLock lock(mMutex);
-    if (!mGL)
-        return;
-
-    mGarbageTextures.push(tex);
+    // Before dispatching, we need to ensure we're not in the middle of
+    // shutting down. Dispatching runnables in the middle of shutdown
+    // (that is, when the main thread is no longer get-able) can cause them
+    // to leak. See Bug 741319, and Bug 744115.
+    nsCOMPtr<nsIThread> mainThread;
+    if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
+        mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
+    }
 }
 
-void
-TextureGarbageBin::EmptyGarbage()
+bool
+DoesStringMatch(const char* aString, const char *aWantedString)
 {
-    MutexAutoLock lock(mMutex);
-    if (!mGL)
-        return;
-
-    while (!mGarbageTextures.empty()) {
-        GLuint tex = mGarbageTextures.top();
-        mGarbageTextures.pop();
-        mGL->fDeleteTextures(1, &tex);
-    }
+    if (!aString || !aWantedString)
+        return false;
+
+    const char *occurrence = strstr(aString, aWantedString);
+
+    // aWanted not found
+    if (!occurrence)
+        return false;
+
+    // aWantedString preceded by alpha character
+    if (occurrence != aString && isalpha(*(occurrence-1)))
+        return false;
+
+    // aWantedVendor followed by alpha character
+    const char *afterOccurrence = occurrence + strlen(aWantedString);
+    if (isalpha(*afterOccurrence))
+        return false;
+
+    return true;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -3,65 +3,51 @@
 /* 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 GLCONTEXT_H_
 #define GLCONTEXT_H_
 
 #include <stdio.h>
-#include <algorithm>
-#if defined(XP_UNIX)
 #include <stdint.h>
-#endif
-#include <string.h>
 #include <ctype.h>
-#include <set>
-#include <stack>
 #include <map>
 #include <bitset>
 
+#ifdef DEBUG
+#include <string.h>
+#endif
+
 #ifdef WIN32
 #include <windows.h>
 #endif
 
 #ifdef GetClassName
 #undef GetClassName
 #endif
 
 #include "GLDefs.h"
 #include "GLLibraryLoader.h"
-#include "gfxASurface.h"
 #include "gfxImageSurface.h"
-#include "gfxContext.h"
-#include "gfxRect.h"
 #include "gfx3DMatrix.h"
 #include "nsISupportsImpl.h"
-#include "prlink.h"
 #include "plstr.h"
-
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
-#include "nsRegion.h"
 #include "nsAutoPtr.h"
-#include "nsIMemoryReporter.h"
-#include "nsThreadUtils.h"
 #include "GLContextTypes.h"
 #include "GLTextureImage.h"
 #include "SurfaceTypes.h"
 #include "GLScreenBuffer.h"
-
 #include "GLContextSymbols.h"
-
-#include "mozilla/mozalloc.h"
-#include "mozilla/Preferences.h"
-#include <stdint.h>
-#include "mozilla/Mutex.h"
 #include "mozilla/GenericRefCounted.h"
 
+class nsIntRegion;
+
 namespace android {
     class GraphicBuffer;
 }
 
 namespace mozilla {
     namespace gfx {
         class SharedSurface;
         class DataSourceSurface;
@@ -2276,73 +2262,23 @@ public:
 public:
 
     typedef struct gfx::SurfaceCaps SurfaceCaps;
 
 
 protected:
     GLContext(const SurfaceCaps& caps,
               GLContext* sharedContext = nullptr,
-              bool isOffscreen = false)
-      : mInitialized(false),
-        mIsOffscreen(isOffscreen),
-        mIsGlobalSharedContext(false),
-        mContextLost(false),
-        mVersion(0),
-        mProfile(ContextProfile::Unknown),
-        mVendor(-1),
-        mRenderer(-1),
-        mHasRobustness(false),
-#ifdef DEBUG
-        mGLError(LOCAL_GL_NO_ERROR),
-#endif
-        mTexBlit_Buffer(0),
-        mTexBlit_VertShader(0),
-        mTex2DBlit_FragShader(0),
-        mTex2DRectBlit_FragShader(0),
-        mTex2DBlit_Program(0),
-        mTex2DRectBlit_Program(0),
-        mTexBlit_UseDrawNotCopy(false),
-        mSharedContext(sharedContext),
-        mFlipped(false),
-        mBlitProgram(0),
-        mBlitFramebuffer(0),
-        mCaps(caps),
-        mScreen(nullptr),
-        mLockedSurface(nullptr),
-        mMaxTextureSize(0),
-        mMaxCubeMapTextureSize(0),
-        mMaxTextureImageSize(0),
-        mMaxRenderbufferSize(0),
-        mNeedsTextureSizeChecks(false),
-        mWorkAroundDriverBugs(true)
-    {
-        mOwningThread = NS_GetCurrentThread();
-
-        mTexBlit_UseDrawNotCopy = Preferences::GetBool("gl.blit-draw-not-copy", false);
-    }
+              bool isOffscreen = false);
 
 
 // -----------------------------------------------------------------------------
 // Destructor
 public:
-    virtual ~GLContext() {
-        NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
-#ifdef DEBUG
-        if (mSharedContext) {
-            GLContext *tip = mSharedContext;
-            while (tip->mSharedContext)
-                tip = tip->mSharedContext;
-            tip->SharedContextDestroyed(this);
-            tip->ReportOutstandingNames();
-        } else {
-            ReportOutstandingNames();
-        }
-#endif
-    }
+    virtual ~GLContext();
 
 
 // -----------------------------------------------------------------------------
 // Everything that isn't standard GL APIs
 protected:
 
     typedef class gfx::SharedSurface SharedSurface;
     typedef gfx::SharedSurfaceType SharedSurfaceType;
@@ -2412,28 +2348,18 @@ public:
 
     bool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
     void SetIsGlobalSharedContext(bool aIsOne) { mIsGlobalSharedContext = aIsOne; }
 
     /**
      * Returns true if the thread on which this context was created is the currently
      * executing thread.
      */
-    bool IsOwningThreadCurrent() { return NS_GetCurrentThread() == mOwningThread; }
-
-    void DispatchToOwningThread(nsIRunnable *event) {
-        // Before dispatching, we need to ensure we're not in the middle of
-        // shutting down. Dispatching runnables in the middle of shutdown
-        // (that is, when the main thread is no longer get-able) can cause them
-        // to leak. See Bug 741319, and Bug 744115.
-        nsCOMPtr<nsIThread> mainThread;
-        if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
-            mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
-        }
-    }
+    bool IsOwningThreadCurrent();
+    void DispatchToOwningThread(nsIRunnable *event);
 
     virtual EGLContext GetEGLContext() { return nullptr; }
     virtual GLLibraryEGL* GetLibraryEGL() { return nullptr; }
 
     virtual void MakeCurrent_EGLSurface(void* surf) {
         MOZ_CRASH("Must be called against a GLContextEGL.");
     }
 
@@ -3197,21 +3123,17 @@ public:
 
 protected:
     nsDataHashtable<nsPtrHashKey<void>, void*> mUserData;
 
     bool InitWithPrefix(const char *prefix, bool trygl);
 
     void InitExtensions();
 
-    bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const {
-        int32_t biggerDimension = std::max(aSize.width, aSize.height);
-        int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
-        return biggerDimension <= maxAllowed;
-    }
+    bool IsOffscreenSizeAllowed(const gfxIntSize& aSize) const;
 
     nsTArray<nsIntRect> mViewportStack;
     nsTArray<nsIntRect> mScissorStack;
 
     GLint mMaxTextureSize;
     GLint mMaxCubeMapTextureSize;
     GLint mMaxTextureImageSize;
     GLint mMaxRenderbufferSize;
@@ -3389,73 +3311,17 @@ public:
     nsTArray<NamedResource> mTrackedTextures;
     nsTArray<NamedResource> mTrackedFramebuffers;
     nsTArray<NamedResource> mTrackedRenderbuffers;
     nsTArray<NamedResource> mTrackedBuffers;
     nsTArray<NamedResource> mTrackedQueries;
 #endif
 };
 
-class GfxTexturesReporter MOZ_FINAL : public MemoryReporterBase
-{
-public:
-    GfxTexturesReporter()
-      : MemoryReporterBase("gfx-textures", KIND_OTHER, UNITS_BYTES,
-                           "Memory used for storing GL textures.")
-    {
-#ifdef DEBUG
-        // There must be only one instance of this class, due to |sAmount|
-        // being static.  Assert this.
-        static bool hasRun = false;
-        MOZ_ASSERT(!hasRun);
-        hasRun = true;
-#endif
-    }
-
-    enum MemoryUse {
-        // when memory being allocated is reported to a memory reporter
-        MemoryAllocated,
-        // when memory being freed is reported to a memory reporter
-        MemoryFreed
-    };
-
-    // When memory is used/freed for tile textures, call this method to update
-    // the value reported by this memory reporter.
-    static void UpdateAmount(MemoryUse action, GLenum format, GLenum type,
-                             uint16_t tileSize);
-
-private:
-    int64_t Amount() MOZ_OVERRIDE { return sAmount; }
-
-    static int64_t sAmount;
-};
-
-inline bool
-DoesStringMatch(const char* aString, const char *aWantedString)
-{
-    if (!aString || !aWantedString)
-        return false;
-
-    const char *occurrence = strstr(aString, aWantedString);
-
-    // aWanted not found
-    if (!occurrence)
-        return false;
-
-    // aWantedString preceded by alpha character
-    if (occurrence != aString && isalpha(*(occurrence-1)))
-        return false;
-
-    // aWantedVendor followed by alpha character
-    const char *afterOccurrence = occurrence + strlen(aWantedString);
-    if (isalpha(*afterOccurrence))
-        return false;
-
-    return true;
-}
+bool DoesStringMatch(const char* aString, const char *aWantedString);
 
 //RAII via CRTP!
 template <class Derived>
 struct ScopedGLWrapper
 {
 private:
     bool mIsUnwrapped;
 
@@ -3792,34 +3658,12 @@ public:
         return mFB;
     }
 
     bool IsComplete() const {
         return mComplete;
     }
 };
 
-
-class TextureGarbageBin {
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureGarbageBin)
-
-protected:
-    GLContext* mGL;
-    Mutex mMutex;
-    std::stack<GLuint> mGarbageTextures;
-
-public:
-    TextureGarbageBin(GLContext* gl)
-        : mGL(gl)
-        , mMutex("TextureGarbageBin mutex")
-    {}
-
-    void GLContextTeardown();
-    void Trash(GLuint tex);
-    void EmptyGarbage();
-};
-
-uint32_t GetBitsPerTexel(GLenum format, GLenum type);
-
 } /* namespace gl */
 } /* namespace mozilla */
 
 #endif /* GLCONTEXT_H_ */
--- a/gfx/gl/GLContextUtils.cpp
+++ b/gfx/gl/GLContextUtils.cpp
@@ -492,68 +492,11 @@ GLContext::BlitTextureToTexture(GLuint s
 
     // Generally, just use the CopyTexSubImage path
     ScopedFramebufferForTexture srcWrapper(this, srcTex, srcTarget);
 
     BlitFramebufferToTexture(srcWrapper.FB(), destTex,
                              srcSize, destSize, destTarget);
 }
 
-uint32_t GetBitsPerTexel(GLenum format, GLenum type)
-{
-    // If there is no defined format or type, we're not taking up any memory
-    if (!format || !type) {
-        return 0;
-    }
-
-    if (format == LOCAL_GL_DEPTH_COMPONENT) {
-        if (type == LOCAL_GL_UNSIGNED_SHORT)
-            return 2;
-        else if (type == LOCAL_GL_UNSIGNED_INT)
-            return 4;
-    } else if (format == LOCAL_GL_DEPTH_STENCIL) {
-        if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
-            return 4;
-    }
-
-    if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
-        int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
-        switch (format) {
-            case LOCAL_GL_ALPHA:
-            case LOCAL_GL_LUMINANCE:
-                return 1 * multiplier;
-            case LOCAL_GL_LUMINANCE_ALPHA:
-                return 2 * multiplier;
-            case LOCAL_GL_RGB:
-                return 3 * multiplier;
-            case LOCAL_GL_RGBA:
-                return 4 * multiplier;
-            case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
-            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
-                return 2;
-            case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-            case LOCAL_GL_ATC_RGB:
-            case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
-            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
-                return 4;
-            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-            case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
-            case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
-                return 8;
-            default:
-                break;
-        }
-    } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
-               type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
-               type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
-    {
-        return 16;
-    }
-
-    MOZ_ASSERT(false);
-    return 0;
-}
-
 
 } /* namespace gl */
 } /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GfxTexturesReporter.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 "GfxTexturesReporter.h"
+#include "GLDefs.h"
+
+using namespace mozilla;
+using namespace mozilla::gl;
+
+int64_t GfxTexturesReporter::sAmount = 0;
+
+static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
+{
+    // If there is no defined format or type, we're not taking up any memory
+    if (!format || !type) {
+        return 0;
+    }
+
+    if (format == LOCAL_GL_DEPTH_COMPONENT) {
+        if (type == LOCAL_GL_UNSIGNED_SHORT)
+            return 2;
+        else if (type == LOCAL_GL_UNSIGNED_INT)
+            return 4;
+    } else if (format == LOCAL_GL_DEPTH_STENCIL) {
+        if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
+            return 4;
+    }
+
+    if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
+        int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
+        switch (format) {
+            case LOCAL_GL_ALPHA:
+            case LOCAL_GL_LUMINANCE:
+                return 1 * multiplier;
+            case LOCAL_GL_LUMINANCE_ALPHA:
+                return 2 * multiplier;
+            case LOCAL_GL_RGB:
+                return 3 * multiplier;
+            case LOCAL_GL_RGBA:
+                return 4 * multiplier;
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+                return 2;
+            case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            case LOCAL_GL_ATC_RGB:
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+                return 4;
+            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+            case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+            case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+            case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+                return 8;
+            default:
+                break;
+        }
+    } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
+               type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
+               type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
+    {
+        return 16;
+    }
+
+    MOZ_ASSERT(false);
+    return 0;
+}
+
+/* static */ void
+GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format,
+                                  GLenum type, uint16_t tileSize)
+{
+    uint32_t bytesPerTexel = GetBitsPerTexel(format, type) / 8;
+    int64_t bytes = (int64_t)(tileSize * tileSize * bytesPerTexel);
+    if (action == MemoryFreed) {
+        sAmount -= bytes;
+    } else {
+        sAmount += bytes;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GfxTexturesReporter.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 "nsIMemoryReporter.h"
+#include "GLTypes.h"
+
+namespace mozilla {
+namespace gl {
+
+class GfxTexturesReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    GfxTexturesReporter()
+      : MemoryReporterBase("gfx-textures", KIND_OTHER, UNITS_BYTES,
+                           "Memory used for storing GL textures.")
+    {
+#ifdef DEBUG
+        // There must be only one instance of this class, due to |sAmount|
+        // being static.  Assert this.
+        static bool hasRun = false;
+        MOZ_ASSERT(!hasRun);
+        hasRun = true;
+#endif
+    }
+
+    enum MemoryUse {
+        // when memory being allocated is reported to a memory reporter
+        MemoryAllocated,
+        // when memory being freed is reported to a memory reporter
+        MemoryFreed
+    };
+
+    // When memory is used/freed for tile textures, call this method to update
+    // the value reported by this memory reporter.
+    static void UpdateAmount(MemoryUse action, GLenum format, GLenum type,
+                             uint16_t tileSize);
+
+private:
+    int64_t Amount() MOZ_OVERRIDE { return sAmount; }
+
+    static int64_t sAmount;
+};
+
+}
+}
\ No newline at end of file
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SharedSurfaceEGL.h"
 
 #include "GLContext.h"
 #include "SharedSurfaceGL.h"
 #include "SurfaceFactory.h"
 #include "GLLibraryEGL.h"
+#include "TextureGarbageBin.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 SharedSurface_EGLImage*
 SharedSurface_EGLImage::Create(GLContext* prodGL,
@@ -42,16 +43,41 @@ SharedSurface_EGLImage::Create(GLContext
 bool
 SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
 {
     return egl->HasKHRImageBase() &&
            egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) &&
            gl->IsExtensionSupported(GLContext::OES_EGL_image);
 }
 
+SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl,
+                                               GLLibraryEGL* egl,
+                                               const gfxIntSize& size,
+                                               bool hasAlpha,
+                                               const GLFormats& formats,
+                                               GLuint prodTex)
+    : SharedSurface_GL(SharedSurfaceType::EGLImageShare,
+                        AttachmentType::GLTexture,
+                        gl,
+                        size,
+                        hasAlpha)
+    , mMutex("SharedSurface_EGLImage mutex")
+    , mEGL(egl)
+    , mFormats(formats)
+    , mProdTex(prodTex)
+    , mProdTexForPipe(0)
+    , mImage(0)
+    , mCurConsGL(nullptr)
+    , mConsTex(0)
+    , mSync(0)
+    , mPipeFailed(false)
+    , mPipeComplete(false)
+    , mPipeActive(false)
+{}
+
 SharedSurface_EGLImage::~SharedSurface_EGLImage()
 {
     mEGL->fDestroyImage(Display(), mImage);
     mImage = 0;
 
     mGL->MakeCurrent();
     mGL->fDeleteTextures(1, &mProdTex);
     mProdTex = 0;
--- a/gfx/gl/SharedSurfaceEGL.h
+++ b/gfx/gl/SharedSurfaceEGL.h
@@ -51,35 +51,17 @@ protected:
     bool mPipeComplete; // Pipe connects (mPipeActive ? mProdTex : mProdTexForPipe) to mConsTex.
     bool mPipeActive;   // Pipe is complete and in use for production.
 
     SharedSurface_EGLImage(GLContext* gl,
                            GLLibraryEGL* egl,
                            const gfxIntSize& size,
                            bool hasAlpha,
                            const GLFormats& formats,
-                           GLuint prodTex)
-        : SharedSurface_GL(SharedSurfaceType::EGLImageShare,
-                           AttachmentType::GLTexture,
-                           gl,
-                           size,
-                           hasAlpha)
-        , mMutex("SharedSurface_EGLImage mutex")
-        , mEGL(egl)
-        , mFormats(formats)
-        , mProdTex(prodTex)
-        , mProdTexForPipe(0)
-        , mImage(0)
-        , mCurConsGL(nullptr)
-        , mConsTex(0)
-        , mSync(0)
-        , mPipeFailed(false)
-        , mPipeComplete(false)
-        , mPipeActive(false)
-    {}
+                           GLuint prodTex);
 
     EGLDisplay Display() const;
 
     static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
 
 public:
     virtual ~SharedSurface_EGLImage();
 
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureGarbageBin.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 "TextureGarbageBin.h"
+#include "GLContext.h"
+
+using namespace mozilla;
+using namespace mozilla::gl;
+
+void
+TextureGarbageBin::GLContextTeardown()
+{
+    EmptyGarbage();
+
+    MutexAutoLock lock(mMutex);
+    mGL = nullptr;
+}
+
+void
+TextureGarbageBin::Trash(GLuint tex)
+{
+    MutexAutoLock lock(mMutex);
+    if (!mGL)
+        return;
+
+    mGarbageTextures.push(tex);
+}
+
+void
+TextureGarbageBin::EmptyGarbage()
+{
+    MutexAutoLock lock(mMutex);
+    if (!mGL)
+        return;
+
+    while (!mGarbageTextures.empty()) {
+        GLuint tex = mGarbageTextures.top();
+        mGarbageTextures.pop();
+        mGL->fDeleteTextures(1, &tex);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureGarbageBin.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 <stack>
+
+#include "mozilla/Mutex.h"
+#include "nsISupportsImpl.h"
+
+#include "GLContextTypes.h"
+
+namespace mozilla {
+namespace gl {
+
+class TextureGarbageBin {
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureGarbageBin)
+
+protected:
+    GLContext* mGL;
+    Mutex mMutex;
+    std::stack<GLuint> mGarbageTextures;
+
+public:
+    TextureGarbageBin(GLContext* gl)
+        : mGL(gl)
+        , mMutex("TextureGarbageBin mutex")
+    {}
+
+    void GLContextTeardown();
+    void Trash(GLuint tex);
+    void EmptyGarbage();
+};
+
+}
+}
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -36,22 +36,24 @@ EXPORTS += [
     'GLContextSymbols.h',
     'GLContextTypes.h',
     'GLDefs.h',
     'GLLibraryEGL.h',
     'GLLibraryLoader.h',
     'GLScreenBuffer.h',
     'GLTextureImage.h',
     'GLTypes.h',
+    'GfxTexturesReporter.h',
     'SharedSurface.h',
     'SharedSurfaceEGL.h',
     'SharedSurfaceGL.h',
     'SurfaceFactory.h',
     'SurfaceStream.h',
     'SurfaceTypes.h',
+    'TextureGarbageBin.h',
     'VBOArena.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS += ['GLXLibrary.h']
 
 # Win32 is a special snowflake, for ANGLE
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
@@ -91,23 +93,25 @@ else:
 CPP_SOURCES += [
     'GLContext.cpp',
     'GLContextFeatures.cpp',
     'GLContextTypes.cpp',
     'GLContextUtils.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
     'GLTextureImage.cpp',
+    'GfxTexturesReporter.cpp',
     'SharedSurface.cpp',
     'GLLibraryEGL.cpp',
     'SharedSurfaceEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceFactory.cpp',
     'SurfaceStream.cpp',
     'VBOArena.cpp',
+    'TextureGarbageBin.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LIBXUL_LIBRARY = True
 
 MSVC_ENABLE_PGO = True
 
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "mozilla/layers/GrallocTextureHost.h"
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRegion.h"                   // for nsIntRegion
+#include "GfxTexturesReporter.h"        // for GfxTexturesReporter
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
 #endif
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {