Bug 912134 - allocate texture per CompositableHost. r=jmuizelaar,bjacob
authorSotaro Ikeda <sikeda@mozilla.com>
Thu, 12 Sep 2013 22:39:26 -0400
changeset 146959 732bb76aad5a8dd243147946e19d89ed3c2379fd
parent 146958 54247b7b87e6de61adaab87989d86b5bd8abfb42
child 146960 6c097bdfc0790f22e44432b073163ea1af432fa3
push id25279
push useremorley@mozilla.com
push dateFri, 13 Sep 2013 14:01:29 +0000
treeherdermozilla-central@2b4aa0f8515e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmuizelaar, bjacob
bugs912134, 875211
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 912134 - allocate texture per CompositableHost. r=jmuizelaar,bjacob The fundamental change of approach in this patch is that now the temporary texture is per-compositable. Originally, the temporary texture was per-TextureHost. That was too many temporary textures. With Nical's work in bug 875211, that switched to having a temporary texture per compositor only. That's what turned out to be too few. Now we have one per compositable which is fewer than one per TextureHost, because e.g. a ContentHost, which is a single Compositable, may have 2 TextureHosts to implement double-buffering.
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/composite/TiledContentHost.cpp
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/GrallocTextureHost.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -157,45 +157,53 @@ CompositableHost::RemoveMaskEffect()
   } else {
     RefPtr<TextureHost> host = GetTextureHost();
     if (host) {
       host->Unlock();
     }
   }
 }
 
+// implemented in TextureHostOGL.cpp
+TemporaryRef<CompositableQuirks> CreateCompositableQuirksOGL();
+
 /* static */ TemporaryRef<CompositableHost>
 CompositableHost::Create(const TextureInfo& aTextureInfo)
 {
   RefPtr<CompositableHost> result;
   switch (aTextureInfo.mCompositableType) {
   case COMPOSITABLE_IMAGE:
     result = new ImageHost(aTextureInfo);
-    return result;
+    break;
   case BUFFER_IMAGE_BUFFERED:
     result = new DeprecatedImageHostBuffered(aTextureInfo);
-    return result;
+    break;
   case BUFFER_IMAGE_SINGLE:
     result = new DeprecatedImageHostSingle(aTextureInfo);
-    return result;
+    break;
   case BUFFER_TILED:
     result = new TiledContentHost(aTextureInfo);
-    return result;
+    break;
   case BUFFER_CONTENT:
     result = new ContentHostSingleBuffered(aTextureInfo);
-    return result;
+    break;
   case BUFFER_CONTENT_DIRECT:
     result = new ContentHostDoubleBuffered(aTextureInfo);
-    return result;
+    break;
   case BUFFER_CONTENT_INC:
     result = new ContentHostIncremental(aTextureInfo);
-    return result;
+    break;
   default:
     MOZ_CRASH("Unknown CompositableType");
   }
+  if (result) {
+    RefPtr<CompositableQuirks> quirks = CreateCompositableQuirksOGL();
+    result->SetCompositableQuirks(quirks);
+  }
+  return result;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
 CompositableHost::DumpDeprecatedTextureHost(FILE* aFile, DeprecatedTextureHost* aTexture)
 {
   if (!aTexture) {
     return;
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -53,16 +53,33 @@ class TextureHost;
 class SurfaceDescriptor;
 class Compositor;
 class ISurfaceAllocator;
 class ThebesBufferData;
 class TiledLayerComposer;
 struct EffectChain;
 
 /**
+ * A base class for doing CompositableHost and platform dependent task on TextureHost.
+ */
+class CompositableQuirks : public RefCounted<CompositableQuirks>
+{
+public:
+  CompositableQuirks()
+  {
+    MOZ_COUNT_CTOR(CompositableQuirks);
+  }
+  virtual ~CompositableQuirks()
+  {
+    MOZ_COUNT_DTOR(CompositableQuirks);
+  }
+  virtual void SetCompositor(Compositor* aCompositor) {}
+};
+
+/**
  * The compositor-side counterpart to CompositableClient. Responsible for
  * updating textures and data about textures from IPC and how textures are
  * composited (tiling, double buffering, etc.).
  *
  * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
  * the layers transaction to update the Compositbale's textures from the
  * content side. The actual update (and any syncronous upload) is done by the
  * TextureHost, but it is coordinated by the CompositableHost.
@@ -77,16 +94,23 @@ public:
   CompositableHost(const TextureInfo& aTextureInfo);
 
   virtual ~CompositableHost();
 
   static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo);
 
   virtual CompositableType GetType() = 0;
 
+  virtual CompositableQuirks* GetCompositableQuirks() { return mQuirks; }
+
+  virtual void SetCompositableQuirks(CompositableQuirks* aQuirks)
+  {
+    mQuirks = aQuirks;
+  }
+
   // If base class overrides, it should still call the parent implementation
   virtual void SetCompositor(Compositor* aCompositor);
 
   // composite the contents of this buffer host to the compositor's surface
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Point& aOffset,
@@ -263,16 +287,17 @@ public:
   virtual void UseTextureHost(TextureHost* aTexture) {}
   virtual void RemoveTextureHost(uint64_t aTextureID);
   TextureHost* GetTextureHost(uint64_t aTextureID);
 
 protected:
   TextureInfo mTextureInfo;
   Compositor* mCompositor;
   Layer* mLayer;
+  RefPtr<CompositableQuirks> mQuirks;
   RefPtr<TextureHost> mFirstTexture;
   bool mAttached;
   bool mKeepAttached;
 };
 
 class CompositableParentManager;
 
 class CompositableParent : public PCompositableParent
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -269,17 +269,18 @@ ContentHostSingleBuffered::EnsureDepreca
 {
   MOZ_ASSERT(aTextureId == TextureFront ||
              aTextureId == TextureOnWhiteFront);
   RefPtr<DeprecatedTextureHost> *newHost =
     (aTextureId == TextureFront) ? &mNewFrontHost : &mNewFrontHostOnWhite;
 
   *newHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
                                             aTextureInfo.mDeprecatedTextureHostFlags,
-                                            aTextureInfo.mTextureFlags);
+                                            aTextureInfo.mTextureFlags,
+                                            this);
 
   (*newHost)->SetBuffer(new SurfaceDescriptor(aSurface), aAllocator);
   Compositor* compositor = GetCompositor();
   if (compositor) {
     (*newHost)->SetCompositor(compositor);
   }
 }
 
@@ -360,17 +361,18 @@ ContentHostDoubleBuffered::~ContentHostD
 void
 ContentHostDoubleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                              const SurfaceDescriptor& aSurface,
                                              ISurfaceAllocator* aAllocator,
                                              const TextureInfo& aTextureInfo)
 {
   RefPtr<DeprecatedTextureHost> newHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
                                                                aTextureInfo.mDeprecatedTextureHostFlags,
-                                                               aTextureInfo.mTextureFlags);
+                                                               aTextureInfo.mTextureFlags,
+                                                               this);
 
   newHost->SetBuffer(new SurfaceDescriptor(aSurface), aAllocator);
 
   Compositor* compositor = GetCompositor();
   if (compositor) {
     newHost->SetCompositor(compositor);
   }
 
@@ -517,27 +519,29 @@ ContentHostIncremental::ProcessTextureUp
 }
 
 void
 ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental* aHost)
 {
   RefPtr<DeprecatedTextureHost> newHost =
     DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptor::TShmem,
                                    mTextureInfo.mDeprecatedTextureHostFlags,
-                                   mTextureInfo.mTextureFlags);
+                                   mTextureInfo.mTextureFlags,
+                                   nullptr);
   Compositor* compositor = aHost->GetCompositor();
   if (compositor) {
     newHost->SetCompositor(compositor);
   }
   RefPtr<DeprecatedTextureHost> newHostOnWhite;
   if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) {
     newHostOnWhite =
       DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptor::TShmem,
                                      mTextureInfo.mDeprecatedTextureHostFlags,
-                                     mTextureInfo.mTextureFlags);
+                                     mTextureInfo.mTextureFlags,
+                                     nullptr);
     Compositor* compositor = aHost->GetCompositor();
     if (compositor) {
       newHostOnWhite->SetCompositor(compositor);
     }
   }
 
   if (mTextureInfo.mDeprecatedTextureHostFlags & TEXTURE_HOST_COPY_PREVIOUS) {
     nsIntRect bufferRect = aHost->mBufferRect;
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -236,17 +236,18 @@ DeprecatedImageHostSingle::EnsureDepreca
 void
 DeprecatedImageHostSingle::MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
                                                      const SurfaceDescriptor& aSurface,
                                                      ISurfaceAllocator* aAllocator,
                                                      const TextureInfo& aTextureInfo)
 {
   mDeprecatedTextureHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
                                                 mTextureInfo.mDeprecatedTextureHostFlags,
-                                                mTextureInfo.mTextureFlags);
+                                                mTextureInfo.mTextureFlags,
+                                                this);
 
   NS_ASSERTION(mDeprecatedTextureHost, "Failed to create texture host");
 
   Compositor* compositor = GetCompositor();
   if (compositor && mDeprecatedTextureHost) {
     mDeprecatedTextureHost->SetCompositor(compositor);
   }
 }
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "mozilla/layers/TextureHost.h"
+#include "CompositableHost.h"           // for CompositableHost
 #include "LayersLogging.h"              // for AppendToString
 #include "gfx2DGlue.h"                  // for ToIntSize
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface, Factory
 #include "mozilla/ipc/Shmem.h"          // for Shmem
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageDataSerializer.h"
@@ -40,23 +41,31 @@ TemporaryRef<DeprecatedTextureHost> Crea
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostD3D11(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
 #endif
 
 /* static */ TemporaryRef<DeprecatedTextureHost>
 DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                            uint32_t aDeprecatedTextureHostFlags,
-                                           uint32_t aTextureFlags)
+                                           uint32_t aTextureFlags,
+                                           CompositableHost* aCompositableHost)
 {
   switch (Compositor::GetBackend()) {
     case LAYERS_OPENGL:
-      return CreateDeprecatedTextureHostOGL(aDescriptorType,
+      {
+      RefPtr<DeprecatedTextureHost> result;
+      result = CreateDeprecatedTextureHostOGL(aDescriptorType,
                                         aDeprecatedTextureHostFlags,
                                         aTextureFlags);
+      if (aCompositableHost) {
+        result->SetCompositableQuirks(aCompositableHost->GetCompositableQuirks());
+      }
+      return result;
+      }
 #ifdef XP_WIN
     case LAYERS_D3D9:
       return CreateDeprecatedTextureHostD3D9(aDescriptorType,
                                          aDeprecatedTextureHostFlags,
                                          aTextureFlags);
     case LAYERS_D3D11:
       return CreateDeprecatedTextureHostD3D11(aDescriptorType,
                                           aDeprecatedTextureHostFlags,
@@ -130,16 +139,47 @@ CreateBackendIndependentTextureHost(uint
     }
     default: {
       NS_WARNING("No backend independent TextureHost for this descriptor type");
     }
   }
   return result;
 }
 
+void TextureHost::SetCompositableQuirks(CompositableQuirks* aQuirks)
+{
+    mQuirks = aQuirks;
+}
+
+
+TextureHost::TextureHost(uint64_t aID,
+                         TextureFlags aFlags)
+    : mID(aID)
+    , mNextTexture(nullptr)
+    , mFlags(aFlags)
+{}
+
+TextureHost::~TextureHost()
+{
+}
+
+void TextureSource::SetCompositableQuirks(CompositableQuirks* aQuirks)
+{
+    mQuirks = aQuirks;
+}
+
+TextureSource::TextureSource()
+{
+    MOZ_COUNT_CTOR(TextureSource);
+}
+TextureSource::~TextureSource()
+{
+    MOZ_COUNT_DTOR(TextureSource);
+}
+
 DeprecatedTextureHost::DeprecatedTextureHost()
   : mFlags(0)
   , mBuffer(nullptr)
   , mDeAllocator(nullptr)
   , mFormat(gfx::FORMAT_UNKNOWN)
 {
   MOZ_COUNT_CTOR(DeprecatedTextureHost);
 }
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -33,16 +33,18 @@ struct nsIntRect;
 namespace mozilla {
 namespace ipc {
 class Shmem;
 }
 
 namespace layers {
 
 class Compositor;
+class CompositableHost;
+class CompositableQuirks;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
 class TextureSourceOGL;
 class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
 class TextureParent;
 class DataTextureSource;
@@ -72,24 +74,18 @@ public:
  * interfaces (TextureSourceOGL, etc.), and TextureSource mostly provide
  * access to these interfaces.
  *
  * This class is used on the compositor side.
  */
 class TextureSource : public RefCounted<TextureSource>
 {
 public:
-  TextureSource()
-  {
-    MOZ_COUNT_CTOR(TextureSource);
-  }
-  virtual ~TextureSource()
-  {
-    MOZ_COUNT_DTOR(TextureSource);
-  }
+  TextureSource();
+  virtual ~TextureSource();
 
   /**
    * Return the size of the texture in texels.
    * If this is a tile iterator, GetSize must return the size of the current tile.
    */
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
@@ -117,19 +113,24 @@ public:
   virtual TextureSource* GetSubSource(int index) { return nullptr; }
 
   /**
    * Overload this if the TextureSource supports big textures that don't fit in
    * one device texture and must be tiled internally.
    */
   virtual TileIterator* AsTileIterator() { return nullptr; }
 
+  virtual void SetCompositableQuirks(CompositableQuirks* aQuirks);
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 #endif
+
+protected:
+  RefPtr<CompositableQuirks> mQuirks;
 };
 
 
 /**
  * XXX - merge this class with TextureSource when deprecated texture classes
  * are completely removed.
  */
 class NewTextureSource : public TextureSource
@@ -259,23 +260,19 @@ private:
  *
  * The Lock/Unlock mecanism here mirrors Lock/Unlock in TextureClient.
  *
  */
 class TextureHost : public RefCounted<TextureHost>
 {
 public:
   TextureHost(uint64_t aID,
-              TextureFlags aFlags)
-    : mID(aID)
-    , mNextTexture(nullptr)
-    , mFlags(aFlags)
-  {}
+              TextureFlags aFlags);
 
-  virtual ~TextureHost() {}
+  virtual ~TextureHost();
 
   /**
    * Factory method.
    */
   static TemporaryRef<TextureHost> Create(uint64_t aID,
                                           const SurfaceDescriptor& aDesc,
                                           ISurfaceAllocator* aDeallocator,
                                           TextureFlags aFlags);
@@ -384,30 +381,33 @@ public:
    */
   virtual LayerRenderState GetRenderState()
   {
     // By default we return an empty render state, this should be overridden
     // by the TextureHost implementations that are used on B2G with Composer2D
     return LayerRenderState();
   }
 
+  virtual void SetCompositableQuirks(CompositableQuirks* aQuirks);
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix)
   {
     RefPtr<TextureSource> source = GetTextureSources();
     if (source) {
       source->PrintInfo(aTo, aPrefix);
     }
   }
 #endif
 
 protected:
   uint64_t mID;
   RefPtr<TextureHost> mNextTexture;
   TextureFlags mFlags;
+  RefPtr<CompositableQuirks> mQuirks;
 };
 
 /**
  * TextureHost that wraps a random access buffer such as a Shmem or some raw
  * memory.
  *
  * This TextureHost is backend-independent and the backend-specific bits are
  * in the TextureSource.
@@ -577,17 +577,18 @@ public:
    *
    * @param aDescriptorType The SurfaceDescriptor type being passed
    * @param aDeprecatedTextureHostFlags Modifier flags that specify changes in
    * the usage of a aDescriptorType, see DeprecatedTextureHostFlags
    * @param aTextureFlags Flags to pass to the new DeprecatedTextureHost
    */
   static TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                                      uint32_t aDeprecatedTextureHostFlags,
-                                                     uint32_t aTextureFlags);
+                                                     uint32_t aTextureFlags,
+                                                     CompositableHost* aCompositableHost);
 
   DeprecatedTextureHost();
   virtual ~DeprecatedTextureHost();
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   virtual bool IsValid() const { return true; }
 
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -295,17 +295,18 @@ TiledContentHost::RenderLayerBuffer(Tile
 void
 TiledTexture::Validate(gfxReusableSurfaceWrapper* aReusableSurface, Compositor* aCompositor, uint16_t aSize)
 {
   TextureFlags flags = 0;
   if (!mDeprecatedTextureHost) {
     // convert placeholder tile to a real tile
     mDeprecatedTextureHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptor::Tnull_t,
                                                   TEXTURE_HOST_TILED,
-                                                  flags);
+                                                  flags,
+                                                  nullptr);
     mDeprecatedTextureHost->SetCompositor(aCompositor);
     flags |= TEXTURE_NEW_TILE;
   }
 
   mDeprecatedTextureHost->Update(aReusableSurface, flags, gfx::IntSize(aSize, aSize));
 }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -234,16 +234,21 @@ CompositableParentManager::ReceiveCompos
       }
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::Create(op.textureID(),
                                                     op.data(),
                                                     this,
                                                     op.textureFlags());
       MOZ_ASSERT(tex.get());
       tex->SetCompositor(compositable->GetCompositor());
+      // set CompositableQuirks
+      // on gonk, create EGLImage if possible.
+      // create EGLImage during buffer swap could reduce the graphic driver's task
+      // during rendering.
+      tex->SetCompositableQuirks(compositable->GetCompositableQuirks());
       compositable->AddTextureHost(tex);
       MOZ_ASSERT(compositable->GetTextureHost(op.textureID()) == tex.get());
       break;
     }
     case CompositableOperation::TOpRemoveTexture: {
       const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
       if (op.textureID() == 0) {
         NS_WARNING("Invalid texture ID");
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -93,58 +93,66 @@ GrallocTextureSourceOGL::GrallocTextureS
   : mCompositor(aCompositor)
   , mGraphicBuffer(aGraphicBuffer)
   , mEGLImage(0)
   , mFormat(aFormat)
 {
   MOZ_ASSERT(mGraphicBuffer.get());
 }
 
+GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
+{
+  DeallocateDeviceData();
+  mCompositor = nullptr;
+}
+
 void GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
 {
   /*
    * The job of this function is to ensure that the texture is tied to the
    * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
    *
    * To this effect we create an EGLImage wrapping this GraphicBuffer,
    * using CreateEGLImageForNativeBuffer, and then we tie this EGLImage to our
    * texture using fEGLImageTargetTexture2D.
    */
   MOZ_ASSERT(gl());
   gl()->MakeCurrent();
 
-
-  GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
   GLuint textureTarget = GetTextureTarget();
 
   gl()->fActiveTexture(aTextureUnit);
   gl()->fBindTexture(textureTarget, tex);
-  if (!mEGLImage) {
-    mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
-  }
-  gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-  // XXX - Bug 909356
-  // This is a temporary fix to a bad lock/unlock race with the camera.
-  // It is bad for performances so we need to find a better way asap.
-  DeallocateDeviceData();
 }
 
 bool
 GrallocTextureSourceOGL::IsValid() const
 {
   return !!gl() && !!mGraphicBuffer.get();
 }
 
 gl::GLContext*
 GrallocTextureSourceOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
 }
 
+void
+GrallocTextureSourceOGL::SetCompositor(CompositorOGL* aCompositor)
+{
+  if (mCompositor && !aCompositor) {
+    DeallocateDeviceData();
+  }
+  mCompositor = aCompositor;
+}
+
+
 GLenum
 GrallocTextureSourceOGL::GetTextureTarget() const
 {
   MOZ_ASSERT(mGraphicBuffer.get());
   return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
 }
 
 gfx::SurfaceFormat
@@ -153,16 +161,40 @@ GrallocTextureSourceOGL::GetFormat() con
     return gfx::FORMAT_UNKNOWN;
   }
   if (GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL) {
     return gfx::FORMAT_R8G8B8A8;
   }
   return mFormat;
 }
 
+void
+GrallocTextureSourceOGL::SetCompositableQuirks(CompositableQuirks* aQuirks)
+{
+  mQuirks = aQuirks;
+
+  if (!mCompositor) {
+    return;
+  }
+
+  // delete old EGLImage
+  DeallocateDeviceData();
+
+  gl()->MakeCurrent();
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
+  GLuint textureTarget = GetTextureTarget();
+
+  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  gl()->fBindTexture(textureTarget, tex);
+  // create new EGLImage
+  mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+  gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+}
+
 gfx::IntSize
 GrallocTextureSourceOGL::GetSize() const
 {
   if (!IsValid()) {
     NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
     return gfx::IntSize(0, 0);
   }
   return gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
@@ -195,20 +227,16 @@ GrallocTextureHostOGL::GrallocTextureHos
                                      aFlags & TEXTURE_RB_SWAPPED);
   mTextureSource = new GrallocTextureSourceOGL(nullptr,
                                                graphicBuffer,
                                                format);
 }
 
 GrallocTextureHostOGL::~GrallocTextureHostOGL()
 {
-  if (mTextureSource) {
-    mTextureSource->mGraphicBuffer = nullptr;
-    mTextureSource->SetCompositor(nullptr);
-  }
   mTextureSource = nullptr;
 }
 
 void
 GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
 {
   mTextureSource->SetCompositor(static_cast<CompositorOGL*>(aCompositor));
 }
@@ -277,25 +305,35 @@ GrallocTextureHostOGL::GetAsSurface() {
                         : nullptr;
 }
 
 already_AddRefed<gfxImageSurface>
 GrallocTextureSourceOGL::GetAsSurface() {
   MOZ_ASSERT(gl());
   gl()->MakeCurrent();
 
-  GLuint tex = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(GetTextureTarget(), tex);
   if (!mEGLImage) {
     mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
 
   nsRefPtr<gfxImageSurface> surf = IsValid() ? gl()->GetTexImage(tex, false, GetFormat())
                                              : nullptr;
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   return surf.forget();
 }
 
+void
+GrallocTextureHostOGL::SetCompositableQuirks(CompositableQuirks* aQuirks)
+{
+  mQuirks = aQuirks;
+  if (mTextureSource) {
+    mTextureSource->SetCompositableQuirks(aQuirks);
+  }
+}
+
 } // namepsace layers
 } // namepsace mozilla
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -21,16 +21,18 @@ class GrallocTextureSourceOGL : public N
 {
 public:
   friend class GrallocTextureHostOGL;
 
   GrallocTextureSourceOGL(CompositorOGL* aCompositor,
                           android::GraphicBuffer* aGraphicBuffer,
                           gfx::SurfaceFormat aFormat);
 
+  virtual ~GrallocTextureSourceOGL();
+
   virtual bool IsValid() const MOZ_OVERRIDE;
 
   virtual void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE;
 
   virtual void UnbindTexture() MOZ_OVERRIDE {}
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
@@ -40,24 +42,23 @@ public:
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return LOCAL_GL_CLAMP_TO_EDGE;
   }
 
+  virtual void SetCompositableQuirks(CompositableQuirks* aQuirks) MOZ_OVERRIDE;
+
   void DeallocateDeviceData();
 
   gl::GLContext* gl() const;
 
-  void SetCompositor(CompositorOGL* aCompositor)
-  {
-    mCompositor = aCompositor;
-  }
+  void SetCompositor(CompositorOGL* aCompositor);
 
   void ForgetBuffer()
   {
     mGraphicBuffer = nullptr;
   }
 
   already_AddRefed<gfxImageSurface> GetAsSurface();
 
@@ -98,16 +99,18 @@ public:
 
   virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
   {
     return mTextureSource;
   }
 
   virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
 
+  virtual void SetCompositableQuirks(CompositableQuirks* aQuirks) MOZ_OVERRIDE;
+
   bool IsValid() const;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "GrallocTextureHostOGL"; }
 #endif
 
 private:
   GrallocBufferActor* mGrallocActor;
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -36,16 +36,26 @@
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 class Compositor; 
 
+TemporaryRef<CompositableQuirks>
+CreateCompositableQuirksOGL()
+{
+#ifdef MOZ_WIDGET_GONK
+  return new CompositableQuirksGonkOGL();
+#else
+  return nullptr;
+#endif
+}
+
 TemporaryRef<DeprecatedTextureHost>
 CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                      uint32_t aDeprecatedTextureHostFlags,
                      uint32_t aTextureFlags)
 {
   RefPtr<DeprecatedTextureHost> result = nullptr;
 
   if (aDescriptorType == SurfaceDescriptor::TYCbCrImage) {
@@ -151,16 +161,48 @@ WrapMode(gl::GLContext *aGl, bool aAllow
   if (aAllowRepeat &&
       (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
        aGl->IsExtensionSupported(GLContext::OES_texture_npot))) {
     return LOCAL_GL_REPEAT;
   }
   return LOCAL_GL_CLAMP_TO_EDGE;
 }
 
+CompositableQuirksGonkOGL::CompositableQuirksGonkOGL()
+ : mTexture(0)
+{
+}
+CompositableQuirksGonkOGL::~CompositableQuirksGonkOGL()
+{
+  if (mTexture) {
+    gl()->MakeCurrent();
+    gl()->fDeleteTextures(1, &mTexture);
+  }
+}
+
+gl::GLContext*
+CompositableQuirksGonkOGL::gl() const
+{
+  return mCompositor ? mCompositor->gl() : nullptr;
+}
+
+void CompositableQuirksGonkOGL::SetCompositor(Compositor* aCompositor)
+{
+  mCompositor = static_cast<CompositorOGL*>(aCompositor);
+}
+
+GLuint CompositableQuirksGonkOGL::GetTexture()
+{
+  if (!mTexture) {
+    gl()->MakeCurrent();
+    gl()->fGenTextures(1, &mTexture);
+  }
+  return mTexture;
+}
+
 bool
 TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
                                      TextureFlags aFlags,
                                      nsIntRegion* aDestRegion,
                                      gfx::IntPoint* aSrcOffset)
 {
   MOZ_ASSERT(mGL);
   if (!mGL) {
@@ -1076,18 +1118,30 @@ GrallocDeprecatedTextureHostOGL::SwapTex
 
   const SurfaceDescriptorGralloc& desc = aImage.get_SurfaceDescriptorGralloc();
   mGraphicBuffer = GrallocBufferActor::GetFrom(desc);
   mIsRBSwapped = desc.isRBSwapped();
   mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat(),
                                                mIsRBSwapped);
 
   mTextureTarget = TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
-
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
+  // delete old EGLImage
   DeleteTextures();
+#if 1
+  gl()->MakeCurrent();
+  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  gl()->fBindTexture(mTextureTarget, tex);
+  // create new EGLImage
+  // create EGLImage during buffer swap could reduce the graphic driver's task
+  // during rendering.
+  mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+  gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
+#endif
 
 }
 
 gl::GLContext*
 GrallocDeprecatedTextureHostOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
 }
@@ -1104,24 +1158,21 @@ void GrallocDeprecatedTextureHostOGL::Bi
    * texture using fEGLImageTargetTexture2D.
    *
    * We try to avoid re-creating the EGLImage everytime, by keeping it around
    * as the mEGLImage member of this class.
    */
   MOZ_ASSERT(gl());
   gl()->MakeCurrent();
 
-  GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
 
   gl()->fActiveTexture(aTextureUnit);
   gl()->fBindTexture(mTextureTarget, tex);
-  if (!mEGLImage) {
-    mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
-  }
-  gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
 bool
 GrallocDeprecatedTextureHostOGL::IsValid() const
 {
   return !!gl() && !!mGraphicBuffer.get();
 }
@@ -1244,17 +1295,18 @@ TiledDeprecatedTextureHostOGL::GetAsSurf
   return surf.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 already_AddRefed<gfxImageSurface>
 GrallocDeprecatedTextureHostOGL::GetAsSurface() {
   gl()->MakeCurrent();
 
-  GLuint tex = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
+  mQuirks->SetCompositor(mCompositor);
+  GLuint tex = static_cast<CompositableQuirksGonkOGL*>(mQuirks.get())->GetTexture();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(mTextureTarget, tex);
   if (!mEGLImage) {
     mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
 
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -3,16 +3,17 @@
  * 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 MOZILLA_GFX_TEXTUREOGL_H
 #define MOZILLA_GFX_TEXTUREOGL_H
 
 #include <stddef.h>                     // for size_t
 #include <stdint.h>                     // for uint64_t
+#include "CompositableHost.h"
 #include "GLContextTypes.h"             // for GLContext
 #include "GLDefs.h"                     // for GLenum, LOCAL_GL_CLAMP_TO_EDGE, etc
 #include "GLTextureImage.h"             // for TextureImage
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "mozilla/GfxMessageUtils.h"    // for gfxContentType
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
@@ -48,16 +49,39 @@ class SurfaceStream;
 }
 
 namespace layers {
 
 class Compositor;
 class CompositorOGL;
 class TextureImageDeprecatedTextureHostOGL;
 
+/**
+ * CompositableQuirks implementation for the Gonk OpenGL backend.
+ * Share a same texture between TextureHosts in the same CompositableHost.
+ * By shareing the texture among the TextureHosts, number of texture allocations
+ * can be reduced than texture allocation in every TextureHosts.
+ * From Bug 912134, use only one texture among all TextureHosts degrade
+ * the rendering performance.
+ * CompositableQuirksGonkOGL chooses in a middile of them.
+ */
+class CompositableQuirksGonkOGL : public CompositableQuirks
+{
+public:
+  CompositableQuirksGonkOGL();
+  virtual ~CompositableQuirksGonkOGL();
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+  GLuint GetTexture();
+  gl::GLContext* gl() const;
+protected:
+  RefPtr<CompositorOGL> mCompositor;
+  GLuint mTexture;
+};
+
 /*
  * TextureHost implementations for the OpenGL backend.
  *
  * Note that it is important to be careful about the ownership model with
  * the OpenGL backend, due to some widget limitation on Linux: before
  * the nsBaseWidget associated with our OpenGL context has been completely
  * deleted, every resource belonging to the OpenGL context MUST have been
  * released. At the moment the teardown sequence happens in the middle of