Bug 983157: Backout bug 980647 (31844306c2f1, dcd632ee9a3e). r=backout
authorBas Schouten <bschouten@mozilla.com>
Thu, 13 Mar 2014 18:55:52 +0100
changeset 191648 d7e998c17c498d724682113871bc61cc836fc23b
parent 191647 beb1b8402d96c3137ce7aeecab7e1f7a7a024945
child 191649 ecedfea04ffc5ae69aa61dced95dbf5082322cb9
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs983157, 980647
milestone30.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 983157: Backout bug 980647 (31844306c2f1, dcd632ee9a3e). r=backout
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/GrallocTextureHost.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -129,16 +129,82 @@ DrawQuads(GLContext *aGLContext,
     aGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
   }
 
   aGLContext->fDrawArrays(aMode, 0, aRects.elements());
 
   aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 }
 
+#ifdef MOZ_WIDGET_GONK
+CompositorOGLGonkBackendSpecificData::CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor)
+  : mCompositor(aCompositor)
+{
+}
+
+CompositorOGLGonkBackendSpecificData::~CompositorOGLGonkBackendSpecificData()
+{
+  // Delete all textures by calling EndFrame twice
+  gl()->MakeCurrent();
+  EndFrame();
+  EndFrame();
+}
+
+GLContext*
+CompositorOGLGonkBackendSpecificData::gl() const
+{
+  return mCompositor->gl();
+}
+
+GLuint
+CompositorOGLGonkBackendSpecificData::GetTexture()
+{
+  GLuint texture = 0;
+
+  if (!mUnusedTextures.IsEmpty()) {
+    // Try to reuse one from the unused pile first
+    texture = mUnusedTextures[0];
+    mUnusedTextures.RemoveElementAt(0);
+  } else if (gl()->MakeCurrent()) {
+    // There isn't one to reuse, create one.
+    gl()->fGenTextures(1, &texture);
+  }
+
+  if (texture) {
+    mCreatedTextures.AppendElement(texture);
+  }
+
+  return texture;
+}
+
+void
+CompositorOGLGonkBackendSpecificData::EndFrame()
+{
+  gl()->MakeCurrent();
+
+  // Some platforms have issues unlocking Gralloc buffers even when they're
+  // rebound.
+  if (gfxPrefs::OverzealousGrallocUnlocking()) {
+    mUnusedTextures.AppendElements(mCreatedTextures);
+    mCreatedTextures.Clear();
+  }
+
+  // Delete unused textures
+  for (size_t i = 0; i < mUnusedTextures.Length(); i++) {
+    GLuint texture = mUnusedTextures[i];
+    gl()->fDeleteTextures(1, &texture);
+  }
+  mUnusedTextures.Clear();
+
+  // Move all created textures into the unused pile
+  mUnusedTextures.AppendElements(mCreatedTextures);
+  mCreatedTextures.Clear();
+}
+#endif
+
 CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
                              int aSurfaceHeight, bool aUseExternalSurfaceSize)
   : mWidget(aWidget)
   , mWidgetSize(-1, -1)
   , mSurfaceSize(aSurfaceWidth, aSurfaceHeight)
   , mHasBGRA(0)
   , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
   , mFrameInProgress(false)
@@ -172,28 +238,48 @@ CompositorOGL::CreateContext()
 
   if (!context) {
     NS_WARNING("Failed to create CompositorOGL context");
   }
 
   return context.forget();
 }
 
+GLuint
+CompositorOGL::GetTemporaryTexture(GLenum aTextureUnit)
+{
+  size_t index = aTextureUnit - LOCAL_GL_TEXTURE0;
+  // lazily grow the array of temporary textures
+  if (mTextures.Length() <= index) {
+    size_t prevLength = mTextures.Length();
+    mTextures.SetLength(index + 1);
+    for(unsigned int i = prevLength; i <= index; ++i) {
+      mTextures[i] = 0;
+    }
+  }
+  // lazily initialize the temporary textures
+  if (!mTextures[index]) {
+    if (!gl()->MakeCurrent()) {
+      return 0;
+    }
+    gl()->fGenTextures(1, &mTextures[index]);
+  }
+  return mTextures[index];
+}
+
 void
 CompositorOGL::Destroy()
 {
   if (gl() && gl()->MakeCurrent()) {
+    if (mTextures.Length() > 0) {
+      gl()->fDeleteTextures(mTextures.Length(), &mTextures[0]);
+    }
     mVBOs.Flush(gl());
   }
-
-  if (mTexturePool) {
-    mTexturePool->Clear();
-    mTexturePool = nullptr;
-  }
-
+  mTextures.SetLength(0);
   if (!mDestroyed) {
     mDestroyed = true;
     CleanupResources();
   }
 }
 
 void
 CompositorOGL::CleanupResources()
@@ -1171,19 +1257,21 @@ CompositorOGL::EndFrame()
     CopyToTarget(mTarget, mCurrentRenderTarget->GetTransform());
     mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     mCurrentRenderTarget = nullptr;
     return;
   }
 
   mCurrentRenderTarget = nullptr;
 
-  if (mTexturePool) {
-    mTexturePool->EndFrame();
+#ifdef MOZ_WIDGET_GONK
+  if (mCompositorBackendSpecificData) {
+    static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositorBackendSpecificData.get())->EndFrame();
   }
+#endif
 
   mGLContext->SwapBuffers();
   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 
   // Unbind all textures
   mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
   mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
   mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
@@ -1294,16 +1382,27 @@ CompositorOGL::Resume()
     return false;
 
   // RenewSurface internally calls MakeCurrent.
   return gl()->RenewSurface();
 #endif
   return true;
 }
 
+#ifdef MOZ_WIDGET_GONK
+CompositorBackendSpecificData*
+CompositorOGL::GetCompositorBackendSpecificData()
+{
+  if (!mCompositorBackendSpecificData) {
+    mCompositorBackendSpecificData = new CompositorOGLGonkBackendSpecificData(this);
+  }
+  return mCompositorBackendSpecificData;
+}
+#endif
+
 TemporaryRef<DataTextureSource>
 CompositorOGL::CreateDataTextureSource(TextureFlags aFlags)
 {
   RefPtr<DataTextureSource> result =
     new TextureImageTextureSourceOGL(mGLContext, aFlags);
   return result;
 }
 
@@ -1391,125 +1490,10 @@ CompositorOGL::BindAndDrawQuad(ShaderPro
                                GLuint aDrawMode)
 {
   NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
   BindAndDrawQuad(aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib),
                   aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib),
                   aFlipped, aDrawMode);
 }
 
-GLuint
-CompositorOGL::GetTemporaryTexture(GLenum aUnit)
-{
-  if (!mTexturePool) {
-#ifdef MOZ_WIDGET_GONK
-    mTexturePool = new PerFrameTexturePoolOGL(gl());
-#else
-    mTexturePool = new PerUnitTexturePoolOGL(gl());
-#endif
-  }
-  return mTexturePool->GetTexture(aUnit);
-}
-
-GLuint
-PerUnitTexturePoolOGL::GetTexture(GLenum aTextureUnit)
-{
-  size_t index = aTextureUnit - LOCAL_GL_TEXTURE0;
-  // lazily grow the array of temporary textures
-  if (mTextures.Length() <= index) {
-    size_t prevLength = mTextures.Length();
-    mTextures.SetLength(index + 1);
-    for(unsigned int i = prevLength; i <= index; ++i) {
-      mTextures[i] = 0;
-    }
-  }
-  // lazily initialize the temporary textures
-  if (!mTextures[index]) {
-    if (!mGL->MakeCurrent()) {
-      return 0;
-    }
-    mGL->fGenTextures(1, &mTextures[index]);
-  }
-  return mTextures[index];
-}
-
-void
-PerUnitTexturePoolOGL::DestroyTextures()
-{
-  if (mGL && mGL->MakeCurrent()) {
-    if (mTextures.Length() > 0) {
-      mGL->fDeleteTextures(mTextures.Length(), &mTextures[0]);
-    }
-  }
-  mTextures.SetLength(0);
-}
-
-void
-PerFrameTexturePoolOGL::DestroyTextures()
-{
-  if (!mGL->MakeCurrent()) {
-    return;
-  }
-
-  if (mUnusedTextures.Length() > 0) {
-    mGL->fDeleteTextures(mUnusedTextures.Length(), &mUnusedTextures[0]);
-    mUnusedTextures.Clear();
-  }
-
-  if (mCreatedTextures.Length() > 0) {
-    mGL->fDeleteTextures(mCreatedTextures.Length(), &mCreatedTextures[0]);
-    mCreatedTextures.Clear();
-  }
-}
-
-GLuint
-PerFrameTexturePoolOGL::GetTexture(GLenum)
-{
-  GLuint texture = 0;
-
-  if (!mUnusedTextures.IsEmpty()) {
-    // Try to reuse one from the unused pile first
-    texture = mUnusedTextures[0];
-    mUnusedTextures.RemoveElementAt(0);
-  } else if (mGL->MakeCurrent()) {
-    // There isn't one to reuse, create one.
-    mGL->fGenTextures(1, &texture);
-  }
-
-  if (texture) {
-    mCreatedTextures.AppendElement(texture);
-  }
-
-  return texture;
-}
-
-void
-PerFrameTexturePoolOGL::EndFrame()
-{
-  if (!mGL->MakeCurrent()) {
-    // this means the context got destroyed underneith us somehow, and the driver
-    // already has destroyed the textures.
-    mCreatedTextures.Clear();
-    mUnusedTextures.Clear();
-    return;
-  }
-
-  // Some platforms have issues unlocking Gralloc buffers even when they're
-  // rebound.
-  if (gfxPrefs::OverzealousGrallocUnlocking()) {
-    mUnusedTextures.AppendElements(mCreatedTextures);
-    mCreatedTextures.Clear();
-  }
-
-  // Delete unused textures
-  for (size_t i = 0; i < mUnusedTextures.Length(); i++) {
-    GLuint texture = mUnusedTextures[i];
-    mGL->fDeleteTextures(1, &texture);
-  }
-  mUnusedTextures.Clear();
-
-  // Move all created textures into the unused pile
-  mUnusedTextures.AppendElements(mCreatedTextures);
-  mCreatedTextures.Clear();
-}
-
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -50,109 +50,16 @@ namespace layers {
 class CompositingRenderTarget;
 class CompositingRenderTargetOGL;
 class DataTextureSource;
 class GLManagerCompositor;
 class TextureSource;
 struct Effect;
 struct EffectChain;
 
-/**
- * Interface for pools of temporary gl textures for the compositor.
- * The textures are fully owned by the pool, so the latter is responsible
- * calling fDeleteTextures accordingly.
- * Users of GetTexture receive a texture that is only valid for the duration
- * of the current frame.
- * This is primarily intended for direct texturing APIs that need to attach
- * shared objects (such as an EGLImage) to a gl texture.
- */
-class CompositorTexturePoolOGL : public RefCounted<CompositorTexturePoolOGL>
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorTexturePoolOGL)
-
-  virtual ~CompositorTexturePoolOGL() {}
-
-  virtual void Clear() = 0;
-
-  virtual GLuint GetTexture(GLenum aUnit) = 0;
-
-  virtual void EndFrame() = 0;
-};
-
-/**
- * Agressively reuses textures. One gl texture per texture unit in total.
- * So far this hasn't shown the best results on b2g.
- */
-class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL
-{
-public:
-  PerUnitTexturePoolOGL(gl::GLContext* aGL)
-  : mGL(aGL)
-  {}
-
-  virtual ~PerUnitTexturePoolOGL()
-  {
-    DestroyTextures();
-  }
-
-  virtual void Clear() MOZ_OVERRIDE
-  {
-    DestroyTextures();
-  }
-
-  virtual GLuint GetTexture(GLenum aUnit) MOZ_OVERRIDE;
-
-  virtual void EndFrame() MOZ_OVERRIDE {}
-
-protected:
-  void DestroyTextures();
-
-  nsTArray<GLuint> mTextures;
-  RefPtr<gl::GLContext> mGL;
-};
-
-/**
- * Reuse gl textures from a pool of textures that haven't yet been
- * used during the current frame.
- * All the textures that are not used at the end of a frame are
- * deleted.
- * This strategy seems to work well with gralloc textures because destroying
- * unused textures which are bound to gralloc buffers let drivers know that it
- * can unlock the gralloc buffers.
- */
-class PerFrameTexturePoolOGL : public CompositorTexturePoolOGL
-{
-public:
-  PerFrameTexturePoolOGL(gl::GLContext* aGL)
-  : mGL(aGL)
-  {}
-
-  virtual ~PerFrameTexturePoolOGL()
-  {
-    DestroyTextures();
-  }
-
-  virtual void Clear() MOZ_OVERRIDE
-  {
-    DestroyTextures();
-  }
-
-  virtual GLuint GetTexture(GLenum aUnit) MOZ_OVERRIDE;
-
-  virtual void EndFrame() MOZ_OVERRIDE;
-
-protected:
-  void DestroyTextures();
-
-  RefPtr<gl::GLContext> mGL;
-  nsTArray<GLuint> mCreatedTextures;
-  nsTArray<GLuint> mUnusedTextures;
-};
-
 class CompositorOGL : public Compositor
 {
   typedef mozilla::gl::GLContext GLContext;
   
   friend class GLManagerCompositor;
 
   std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
 public:
@@ -250,16 +157,20 @@ public:
     return LayersBackend::LAYERS_OPENGL;
   }
 
   virtual void Pause() MOZ_OVERRIDE;
   virtual bool Resume() MOZ_OVERRIDE;
 
   virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
 
+#ifdef MOZ_WIDGET_GONK
+  virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() MOZ_OVERRIDE;
+#endif
+
   GLContext* gl() const { return mGLContext; }
   gfx::SurfaceFormat GetFBOFormat() const {
     return gfx::SurfaceFormat::R8G8B8A8;
   }
 
   /**
    * The compositor provides with temporary textures for use with direct
    * textruing like gralloc texture.
@@ -393,23 +304,49 @@ private:
    *
    * Indeed, the only coordinate system that OpenGL knows has the y-axis
    * pointing upwards, but the layers/compositor coordinate system has the
    * y-axis pointing downwards, for good reason as Web pages are typically
    * scrolled downwards. So, some flipping has to take place; FlippedY does it.
    */
   GLint FlipY(GLint y) const { return mHeight - y; }
 
-  RefPtr<CompositorTexturePoolOGL> mTexturePool;
+  bool mDestroyed;
 
-  bool mDestroyed;
+  // Textures used for direct texturing of buffers like gralloc.
+  // The index of the texture in this array must correspond to the texture unit.
+  nsTArray<GLuint> mTextures;
 
   /**
    * Height of the OpenGL context's primary framebuffer in pixels. Used by
    * FlipY for the y-flipping calculation.
    */
   GLint mHeight;
+
+#ifdef MOZ_WIDGET_GONK
+  RefPtr<CompositorBackendSpecificData> mCompositorBackendSpecificData;
+#endif
 };
 
+#ifdef MOZ_WIDGET_GONK
+class CompositorOGLGonkBackendSpecificData : public CompositorBackendSpecificData
+{
+public:
+  CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor);
+  virtual ~CompositorOGLGonkBackendSpecificData();
+
+  GLuint GetTexture();
+  void EndFrame();
+
+private:
+  gl::GLContext* gl() const;
+
+  RefPtr<CompositorOGL> mCompositor;
+
+  nsTArray<GLuint> mCreatedTextures;
+  nsTArray<GLuint> mUnusedTextures;
+};
+#endif
+
 }
 }
 
 #endif /* MOZILLA_GFX_COMPOSITOROGL_H */
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -88,73 +88,89 @@ TextureTargetForAndroidPixelFormat(andro
 
 GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
                                                  android::GraphicBuffer* aGraphicBuffer,
                                                  gfx::SurfaceFormat aFormat)
   : mCompositor(aCompositor)
   , mGraphicBuffer(aGraphicBuffer)
   , mEGLImage(0)
   , mFormat(aFormat)
+  , mNeedsReset(true)
 {
   MOZ_ASSERT(mGraphicBuffer.get());
 }
 
 GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
 {
   DeallocateDeviceData();
   mCompositor = nullptr;
 }
 
 void
 GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
 {
+  /*
+   * 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 EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
+   * texture using fEGLImageTargetTexture2D.
+   */
   MOZ_ASSERT(gl());
   if (!IsValid()) {
     return;
   }
   gl()->MakeCurrent();
 
   GLuint tex = GetGLTexture();
   GLuint textureTarget = GetTextureTarget();
 
   gl()->fActiveTexture(aTextureUnit);
   gl()->fBindTexture(textureTarget, tex);
 
+  if (mCompositableBackendData) {
+    // There are two paths for locking/unlocking - if mCompositableBackendData is
+    // set, we use the texture on there, otherwise we use
+    // CompositorBackendSpecificData from the compositor and bind the EGLImage
+    // only in Lock().
+    if (!mEGLImage) {
+      mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
+    }
+    gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+  }
+
   ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
 }
 
 void GrallocTextureSourceOGL::Lock()
 {
-  /*
-   * 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 EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
-   * texture using fEGLImageTargetTexture2D.
-   */
+  if (mCompositableBackendData) return;
+
   MOZ_ASSERT(IsValid());
 
-  mTexture = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
+  CompositorOGLGonkBackendSpecificData* backendData =
+    static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositor->GetCompositorBackendSpecificData());
+  mTexture = backendData->GetTexture();
 
   GLuint textureTarget = GetTextureTarget();
 
   gl()->MakeCurrent();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(textureTarget, mTexture);
   if (!mEGLImage) {
     mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
 }
 
 bool
 GrallocTextureSourceOGL::IsValid() const
 {
-  return !!gl() && !!mGraphicBuffer.get();
+  return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mCompositableBackendData);
 }
 
 gl::GLContext*
 GrallocTextureSourceOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
 }
 
@@ -184,16 +200,61 @@ GrallocTextureSourceOGL::GetFormat() con
     return gfx::SurfaceFormat::UNKNOWN;
   }
   if (GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL) {
     return gfx::SurfaceFormat::R8G8B8A8;
   }
   return mFormat;
 }
 
+void
+GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+{
+  if (!aBackendData) {
+    mCompositableBackendData = nullptr;
+    DeallocateDeviceData();
+    return;
+  }
+
+  if (mCompositableBackendData != aBackendData) {
+    mNeedsReset = true;
+  }
+
+  if (!mNeedsReset) {
+    // Update binding to the EGLImage
+    gl()->MakeCurrent();
+    GLuint tex = GetGLTexture();
+    GLuint textureTarget = GetTextureTarget();
+    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+    gl()->fBindTexture(textureTarget, tex);
+    gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+    return;
+  }
+
+  mCompositableBackendData = aBackendData;
+
+  if (!mCompositor) {
+    return;
+  }
+
+  // delete old EGLImage
+  DeallocateDeviceData();
+
+  gl()->MakeCurrent();
+  GLuint tex = GetGLTexture();
+  GLuint textureTarget = GetTextureTarget();
+
+  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  gl()->fBindTexture(textureTarget, tex);
+  // create new EGLImage
+  mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
+  gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+  mNeedsReset = false;
+}
+
 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());
@@ -352,16 +413,21 @@ GrallocTextureSourceOGL::GetAsSurface() 
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   return surf.forget();
 }
 
 GLuint
 GrallocTextureSourceOGL::GetGLTexture()
 {
+  if (mCompositableBackendData) {
+    mCompositableBackendData->SetCompositor(mCompositor);
+    return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
+  }
+
   return mTexture;
 }
 
 void
 GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
   mCompositableBackendData = aBackendData;
   if (mTextureSource) {
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -40,16 +40,18 @@ public:
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return LOCAL_GL_CLAMP_TO_EDGE;
   }
 
+  virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
+
   void DeallocateDeviceData();
 
   gl::GLContext* gl() const;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   void ForgetBuffer()
   {
@@ -63,16 +65,17 @@ public:
   void Lock();
 
 protected:
   CompositorOGL* mCompositor;
   android::sp<android::GraphicBuffer> mGraphicBuffer;
   EGLImage mEGLImage;
   GLuint mTexture;
   gfx::SurfaceFormat mFormat;
+  bool mNeedsReset;
 };
 
 class GrallocTextureHostOGL : public TextureHost
 #if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
                             , public TextureHostOGL
 #endif
 {
   friend class GrallocBufferActor;
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -150,36 +150,60 @@ WrapMode(gl::GLContext *aGl, bool aAllow
       (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;
 }
 
 CompositableDataGonkOGL::CompositableDataGonkOGL()
+ : mTexture(0)
 {
 }
 CompositableDataGonkOGL::~CompositableDataGonkOGL()
 {
+  DeleteTextureIfPresent();
 }
 
 gl::GLContext*
 CompositableDataGonkOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
 }
 
 void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = static_cast<CompositorOGL*>(aCompositor);
 }
 
 void CompositableDataGonkOGL::ClearData()
 {
   CompositableBackendSpecificData::ClearData();
+  DeleteTextureIfPresent();
+}
+
+GLuint CompositableDataGonkOGL::GetTexture()
+{
+  if (!mTexture) {
+    if (gl()->MakeCurrent()) {
+      gl()->fGenTextures(1, &mTexture);
+    }
+  }
+  return mTexture;
+}
+
+void
+CompositableDataGonkOGL::DeleteTextureIfPresent()
+{
+  if (mTexture) {
+    if (gl()->MakeCurrent()) {
+      gl()->fDeleteTextures(1, &mTexture);
+    }
+    mTexture = 0;
+  }
 }
 
 #if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
 bool
 TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
 {
   if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
     return false;
@@ -707,16 +731,29 @@ TextureImageDeprecatedTextureHostOGL::Up
                                        nsIntRegion* aRegion,
                                        nsIntPoint* aOffset)
 {
   if (!mGL) {
     NS_WARNING("trying to update TextureImageDeprecatedTextureHostOGL without a compositor?");
     return;
   }
 
+#ifdef MOZ_WIDGET_GONK
+  if (mCompositableBackendData) {
+    // on gonk, this class is used as a fallback from gralloc buffer.
+    // There is a case this class is used with GrallocDeprecatedTextureHostOGL
+    // under same CompositableHost. if it happens, a gralloc buffer of
+    // GrallocDeprecatedTextureHostOGL needs to be unbounded from a texture,
+    // when the gralloc buffer is not rendered.
+    // Establish the unbound by deleting the texture.
+    // See Bug 916264.
+    static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->DeleteTextureIfPresent();
+  }
+#endif
+
   AutoOpenSurface surf(OPEN_READ_ONLY, aImage);
   gfx::IntSize size = surf.Size();
   TextureImage::ImageFormat format = surf.ImageFormat();
 
   if (!mTexture ||
       (mTexture->GetSize() != size && !aOffset) ||
       mTexture->GetContentType() != surf.ContentType() ||
       (mTexture->GetImageFormat() != format &&
@@ -1159,17 +1196,17 @@ GrallocDeprecatedTextureHostOGL::GetRend
 
   return LayerRenderState();
 }
 
 GLuint
 GrallocDeprecatedTextureHostOGL::GetGLTexture()
 {
   mCompositableBackendData->SetCompositor(mCompositor);
-  return mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
+  return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
 }
 
 #endif // MOZ_WIDGET_GONK
 
 TemporaryRef<gfx::DataSourceSurface>
 TextureImageDeprecatedTextureHostOGL::GetAsSurface() {
   RefPtr<gfx::DataSourceSurface> surf =
     IsValid() ? ReadBackSurface(mGL, mTexture->GetTextureID(),
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -67,19 +67,22 @@ class TextureImageDeprecatedTextureHostO
 class CompositableDataGonkOGL : public CompositableBackendSpecificData
 {
 public:
   CompositableDataGonkOGL();
   virtual ~CompositableDataGonkOGL();
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
   virtual void ClearData() MOZ_OVERRIDE;
+  GLuint GetTexture();
+  void DeleteTextureIfPresent();
   gl::GLContext* gl() const;
 protected:
   RefPtr<CompositorOGL> mCompositor;
+  GLuint mTexture;
 };
 
 inline void ApplyFilterToBoundTexture(gl::GLContext* aGL,
                                       gfx::Filter aFilter,
                                       GLuint aTarget = LOCAL_GL_TEXTURE_2D)
 {
   GLenum filter =
     (aFilter == gfx::Filter::POINT ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR);