Bug 1097116 - Add fencing and better lifetime management for EGLImage Images r=jgilbert
authorJames Willcox <snorp@snorp.net>
Wed, 26 Nov 2014 15:16:07 -0600
changeset 233980 fd893f3651e2d8d91f03d34de51d52d564173a0d
parent 233979 7ee7e774e19fa150b64745c65d01768f5b88549a
child 233981 493ea6a11a879f224ba51a77ebb9b0b7b483622c
push id7326
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:58:42 +0000
treeherdermozilla-aurora@d3a3b2a0f2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1097116
milestone36.0a1
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