Bug 1005908 - Avoid unnecessary fEGLImageTargetTexture2D'ing r=nical
authorSotaro Ikeda <sikeda@mozilla.com>
Wed, 14 May 2014 09:59:25 -0700
changeset 183217 6e20f63f33a6a21ade411b0930bd1dd7ee778db3
parent 183216 79b35bc4e692e6353a343b9345607024e0a31a86
child 183218 fb55e55a303b9d84a6003811e5cb80c687fc45cb
push idunknown
push userunknown
push dateunknown
reviewersnical
bugs1005908
milestone32.0a1
Bug 1005908 - Avoid unnecessary fEGLImageTargetTexture2D'ing r=nical
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/GrallocTextureHost.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -133,17 +133,17 @@ GrallocTextureSourceOGL::BindTexture(GLe
   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);
+    BindEGLImage();
   }
 
   ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
 }
 
 void GrallocTextureSourceOGL::Lock()
 {
   if (mCompositableBackendData) return;
@@ -207,54 +207,57 @@ GrallocTextureSourceOGL::GetTextureTarge
 
   return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
 }
 
 void
 GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
   if (!aBackendData) {
+    DeallocateDeviceData();
+    // Update mCompositableBackendData after calling DeallocateDeviceData().
     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);
+    BindEGLImage();
     return;
   }
 
-  mCompositableBackendData = aBackendData;
-
   if (!mCompositor) {
+    mCompositableBackendData = aBackendData;
     return;
   }
 
   // delete old EGLImage
   DeallocateDeviceData();
 
+  // Update mCompositableBackendData after calling DeallocateDeviceData().
+  mCompositableBackendData = aBackendData;
+
   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);
+  BindEGLImage();
   mNeedsReset = false;
 }
 
 gfx::IntSize
 GrallocTextureSourceOGL::GetSize() const
 {
   if (!IsValid()) {
     NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
@@ -264,16 +267,20 @@ GrallocTextureSourceOGL::GetSize() const
 }
 
 void
 GrallocTextureSourceOGL::DeallocateDeviceData()
 {
   if (mEGLImage) {
     MOZ_ASSERT(gl());
     gl()->MakeCurrent();
+    if (mCompositableBackendData) {
+      CompositableDataGonkOGL* backend = static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get());
+      backend->ClearBoundEGLImage(mEGLImage);
+    }
     EGLImageDestroy(gl(), mEGLImage);
     mEGLImage = EGL_NO_IMAGE;
   }
 }
 
 GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
                                              const NewSurfaceDescriptorGralloc& aDescriptor)
   : TextureHost(aFlags)
@@ -402,17 +409,17 @@ GrallocTextureSourceOGL::GetAsSurface() 
   gl()->MakeCurrent();
 
   GLuint tex = GetGLTexture();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(GetTextureTarget(), tex);
   if (!mEGLImage) {
     mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   }
-  gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
+  BindEGLImage();
 
   RefPtr<gfx::DataSourceSurface> surf =
     IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat())
               : nullptr;
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   return surf.forget();
 }
@@ -424,16 +431,27 @@ GrallocTextureSourceOGL::GetGLTexture()
     mCompositableBackendData->SetCompositor(mCompositor);
     return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
   }
 
   return mTexture;
 }
 
 void
+GrallocTextureSourceOGL::BindEGLImage()
+{
+  if (mCompositableBackendData) {
+    CompositableDataGonkOGL* backend = static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get());
+    backend->BindEGLImage(GetTextureTarget(), mEGLImage);
+  } else {
+    gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
+  }
+}
+
+void
 GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
   mCompositableBackendData = aBackendData;
   if (mTextureSource) {
     mTextureSource->SetCompositableBackendSpecificData(aBackendData);
   }
   // Register this object to CompositableBackendSpecificData
   // as current TextureHost.
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -57,16 +57,18 @@ public:
   {
     mGraphicBuffer = nullptr;
   }
 
   TemporaryRef<gfx::DataSourceSurface> GetAsSurface();
 
   GLuint GetGLTexture();
 
+  void BindEGLImage();
+
   void Lock();
 
 protected:
   CompositorOGL* mCompositor;
   android::sp<android::GraphicBuffer> mGraphicBuffer;
   EGLImage mEGLImage;
   GLuint mTexture;
   gfx::SurfaceFormat mFormat;
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -124,16 +124,17 @@ WrapMode(gl::GLContext *aGl, TextureFlag
        aGl->IsExtensionSupported(GLContext::OES_texture_npot))) {
     return LOCAL_GL_REPEAT;
   }
   return LOCAL_GL_CLAMP_TO_EDGE;
 }
 
 CompositableDataGonkOGL::CompositableDataGonkOGL()
  : mTexture(0)
+ , mBoundEGLImage(EGL_NO_IMAGE)
 {
 }
 CompositableDataGonkOGL::~CompositableDataGonkOGL()
 {
   DeleteTextureIfPresent();
 }
 
 gl::GLContext*
@@ -166,16 +167,35 @@ GLuint CompositableDataGonkOGL::GetTextu
 void
 CompositableDataGonkOGL::DeleteTextureIfPresent()
 {
   if (mTexture) {
     if (gl()->MakeCurrent()) {
       gl()->fDeleteTextures(1, &mTexture);
     }
     mTexture = 0;
+    mBoundEGLImage = EGL_NO_IMAGE;
+  }
+}
+
+void
+CompositableDataGonkOGL::BindEGLImage(GLuint aTarget, EGLImage aImage)
+{
+  if (mBoundEGLImage != aImage) {
+    gl()->fEGLImageTargetTexture2D(aTarget, aImage);
+    mBoundEGLImage = aImage;
+  }
+}
+
+void
+CompositableDataGonkOGL::ClearBoundEGLImage(EGLImage aImage)
+{
+  if (mBoundEGLImage == aImage) {
+    DeleteTextureIfPresent();
+    mBoundEGLImage = EGL_NO_IMAGE;
   }
 }
 
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 bool
 TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
 {
   if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -69,19 +69,22 @@ public:
   CompositableDataGonkOGL();
   virtual ~CompositableDataGonkOGL();
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
   virtual void ClearData() MOZ_OVERRIDE;
   GLuint GetTexture();
   void DeleteTextureIfPresent();
   gl::GLContext* gl() const;
+  void BindEGLImage(GLuint aTarget, EGLImage aImage);
+  void ClearBoundEGLImage(EGLImage aImage);
 protected:
   RefPtr<CompositorOGL> mCompositor;
   GLuint mTexture;
+  EGLImage mBoundEGLImage;
 };
 
 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);