Bug 1097116 - Add fencing and better lifetime management for EGLImage Images r=jgilbert
authorJames Willcox <snorp@snorp.net>
Fri, 21 Nov 2014 09:28:19 -0600
changeset 241236 4812033a4b2171b9e07b67087ce3dc78a3696de0
parent 241235 38f5bfa0e2f7819f51518b5ca01e11fcf674c8be
child 241237 3ca93d9075fa27e438aab60085134043ab077dc9
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1097116
milestone36.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 1097116 - Add fencing and better lifetime management for EGLImage Images r=jgilbert
gfx/layers/GLImages.cpp
gfx/layers/GLImages.h
gfx/layers/client/ImageClient.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/opengl/TextureClientOGL.cpp
gfx/layers/opengl/TextureClientOGL.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -3,25 +3,43 @@
 #include "GLImages.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "ScopedGLHelpers.h"
 #include "GLImages.h"
 #include "GLBlitHelper.h"
 #include "GLReadTexImageHelper.h"
 #include "AndroidSurfaceTexture.h"
+#include "GLLibraryEGL.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 static nsRefPtr<GLContext> sSnapshotContext;
 
+EGLImageImage::~EGLImageImage()
+{
+  if (!mData.mOwns) {
+    return;
+  }
+
+  if (mData.mImage) {
+    sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mData.mImage);
+    mData.mImage = nullptr;
+  }
+
+  if (mData.mSync) {
+    sEGLLibrary.fDestroySync(EGL_DISPLAY(), mData.mSync);
+    mData.mSync = nullptr;
+  }
+}
+
 TemporaryRef<gfx::SourceSurface>
 SurfaceTextureImage::GetAsSourceSurface()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");
 
   if (!sSnapshotContext) {
     SurfaceCaps caps = SurfaceCaps::ForRGBA();
     sSnapshotContext = GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps);
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -17,32 +17,37 @@ namespace gl {
 class AndroidSurfaceTexture;
 }
 namespace layers {
 
 class EGLImageImage : public Image {
 public:
   struct Data {
     EGLImage mImage;
+    EGLSync mSync;
     gfx::IntSize mSize;
     bool mInverted;
+    bool mOwns;
   };
 
   void SetData(const Data& aData) { mData = aData; }
   const Data* GetData() { return &mData; }
 
   gfx::IntSize GetSize() { return mData.mSize; }
 
   virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE
   {
     return nullptr;
   }
 
   EGLImageImage() : Image(nullptr, ImageFormat::EGLIMAGE) {}
 
+protected:
+  virtual ~EGLImageImage();
+
 private:
   Data mData;
 };
 
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureImage : public Image {
 public:
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -187,20 +187,19 @@ ImageClientSingle::UpdateImage(ImageCont
       }
 
     } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
                image->GetFormat() == ImageFormat::EGLIMAGE) {
       gfx::IntSize size = image->GetSize();
 
       if (image->GetFormat() == ImageFormat::EGLIMAGE) {
         EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
-        const EGLImageImage::Data* data = typedImage->GetData();
-
-        texture = new EGLImageTextureClient(mTextureFlags, data->mImage,
-                                           size, data->mInverted);
+        texture = new EGLImageTextureClient(mTextureFlags,
+                                           typedImage,
+                                           size);
 #ifdef MOZ_WIDGET_ANDROID
       } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
         SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
         const SurfaceTextureImage::Data* data = typedImage->GetData();
         texture = new SurfaceTextureClient(mTextureFlags, data->mSurfTex,
                                           size, data->mInverted);
 #endif
       } else {
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -58,16 +58,17 @@ struct SurfaceDescriptorMacIOSurface {
 
 struct SurfaceTextureDescriptor {
   uintptr_t surfTex;
   IntSize size;
 };
 
 struct EGLImageDescriptor {
   uintptr_t image; // `EGLImage` is a `void*`.
+  uintptr_t fence;
   IntSize size;
 };
 
 struct NewSurfaceDescriptorGralloc {
   MaybeMagicGrallocBufferHandle buffer;
   /**
    * android::GraphicBuffer has a size information. But there are cases
    * that GraphicBuffer's size and actual video's size are different.
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -3,59 +3,54 @@
  * 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 "GLContext.h"                  // for GLContext, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/TextureClientOGL.h"
 #include "nsSize.h"                     // for nsIntSize
+#include "GLLibraryEGL.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
 
 ////////////////////////////////////////////////////////////////////////
 // EGLImageTextureClient
 
 EGLImageTextureClient::EGLImageTextureClient(TextureFlags aFlags,
-                                             EGLImage aImage,
-                                             gfx::IntSize aSize,
-                                             bool aInverted)
+                                             EGLImageImage* aImage,
+                                             gfx::IntSize aSize)
   : TextureClient(aFlags)
   , mImage(aImage)
   , mSize(aSize)
   , mIsLocked(false)
 {
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
              "Can't pass an `EGLImage` between processes.");
 
-  // Our data is always owned externally.
   AddFlags(TextureFlags::DEALLOCATE_CLIENT);
 
-  if (aInverted) {
+  if (aImage->GetData()->mInverted) {
     AddFlags(TextureFlags::NEEDS_Y_FLIP);
   }
 }
 
-EGLImageTextureClient::~EGLImageTextureClient()
-{
-  // Our data is always owned externally.
-}
-
 bool
 EGLImageTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(IsAllocated());
 
-  aOutDescriptor = EGLImageDescriptor((uintptr_t)mImage, mSize);
+  const EGLImageImage::Data* data = mImage->GetData();
+  aOutDescriptor = EGLImageDescriptor((uintptr_t)data->mImage, (uintptr_t)data->mSync, mSize);
   return true;
 }
 
 bool
 EGLImageTextureClient::Lock(OpenMode mode)
   {
     MOZ_ASSERT(!mIsLocked);
     if (!IsValid() || !IsAllocated()) {
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -2,16 +2,17 @@
 //  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTURECLIENTOGL_H
 #define MOZILLA_GFX_TEXTURECLIENTOGL_H
 
 #include "GLContextTypes.h"             // for SharedTextureHandle, etc
+#include "GLImages.h"
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "AndroidSurfaceTexture.h"
 
@@ -20,21 +21,18 @@ namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
 
 class EGLImageTextureClient : public TextureClient
 {
 public:
   EGLImageTextureClient(TextureFlags aFlags,
-                        EGLImage aImage,
-                        gfx::IntSize aSize,
-                        bool aInverted);
-
-  ~EGLImageTextureClient();
+                        EGLImageImage* aImage,
+                        gfx::IntSize aSize);
 
   virtual bool IsAllocated() const MOZ_OVERRIDE { return true; }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
@@ -59,17 +57,17 @@ public:
   }
 
   virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
   {
     return false;
   }
 
 protected:
-  const EGLImage mImage;
+  RefPtr<EGLImageImage> mImage;
   const gfx::IntSize mSize;
   bool mIsLocked;
 };
 
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureClient : public TextureClient
 {
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -63,16 +63,17 @@ CreateTextureHostOGL(const SurfaceDescri
       break;
     }
 #endif
 
     case SurfaceDescriptor::TEGLImageDescriptor: {
       const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
       result = new EGLImageTextureHost(aFlags,
                                        (EGLImage)desc.image(),
+                                       (EGLSync)desc.fence(),
                                        desc.size());
       break;
     }
 
 #ifdef XP_MACOSX
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
       const SurfaceDescriptorMacIOSurface& desc =
         aDesc.get_SurfaceDescriptorMacIOSurface();
@@ -628,19 +629,21 @@ EGLImageTextureSource::GetTextureTransfo
   gfx::Matrix4x4 ret;
   return ret;
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
                                          EGLImage aImage,
+                                         EGLSync aSync,
                                          gfx::IntSize aSize)
   : TextureHost(aFlags)
   , mImage(aImage)
+  , mSync(aSync)
   , mSize(aSize)
   , mCompositor(nullptr)
 {
 }
 
 EGLImageTextureHost::~EGLImageTextureHost()
 {
 }
@@ -653,16 +656,21 @@ EGLImageTextureHost::gl() const
 
 bool
 EGLImageTextureHost::Lock()
 {
   if (!mCompositor) {
     return false;
   }
 
+  EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
+  if (status != LOCAL_EGL_CONDITION_SATISFIED) {
+    return false;
+  }
+
   if (!mTextureSource) {
     gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
     GLenum target = LOCAL_GL_TEXTURE_2D;
     GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
     mTextureSource = new EGLImageTextureSource(mCompositor,
                                                mImage,
                                                format,
                                                target,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -471,16 +471,17 @@ protected:
   const gfx::IntSize mSize;
 };
 
 class EGLImageTextureHost : public TextureHost
 {
 public:
   EGLImageTextureHost(TextureFlags aFlags,
                      EGLImage aImage,
+                     EGLSync aSync,
                      gfx::IntSize aSize);
 
   virtual ~EGLImageTextureHost();
 
   // We don't own anything.
   virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
@@ -504,16 +505,17 @@ public:
   gl::GLContext* gl() const;
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   virtual const char* Name() { return "EGLImageTextureHost"; }
 
 protected:
   const EGLImage mImage;
+  const EGLSync mSync;
   const gfx::IntSize mSize;
   RefPtr<CompositorOGL> mCompositor;
   RefPtr<EGLImageTextureSource> mTextureSource;
 };
 
 } // namespace
 } // namespace