Bug 1208513 - Resurrect SharedSurface_GLTexture for use on iOS r=jgilbert
authorJames Willcox <snorp@snorp.net>
Thu, 24 Sep 2015 09:11:53 -0500
changeset 305240 b5e9434723267baa67f3526564e9be843c97af70
parent 305239 ab686c0adbaa1313b87e79fba4c1ee3ddc5bc7a6
child 305241 2ff6d5250364999dd51bccf8d2e5468d551978e7
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1208513
milestone44.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 1208513 - Resurrect SharedSurface_GLTexture for use on iOS r=jgilbert
gfx/gl/GLScreenBuffer.cpp
gfx/gl/SharedSurfaceGL.cpp
gfx/gl/SharedSurfaceGL.h
gfx/gl/SurfaceTypes.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -77,16 +77,18 @@ GLScreenBuffer::CreateFactory(GLContext*
             case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
 #if defined(XP_MACOSX)
                 factory = SurfaceFactory_IOSurface::Create(gl, caps, forwarder, flags);
 #elif defined(MOZ_WIDGET_GONK)
                 factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps, forwarder, flags);
 #elif defined(GL_PROVIDER_GLX)
                 if (sGLXLibrary.UseSurfaceSharing())
                   factory = SurfaceFactory_GLXDrawable::Create(gl, caps, forwarder, flags);
+#elif defined(MOZ_WIDGET_UIKIT)
+                factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, forwarder, mFlags);
 #else
                 if (gl->GetContextType() == GLContextType::EGL) {
                     if (XRE_IsParentProcess()) {
                         factory = SurfaceFactory_EGLImage::Create(gl, caps, forwarder, flags);
                     }
                 }
 #endif
                 break;
--- a/gfx/gl/SharedSurfaceGL.cpp
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -90,18 +90,101 @@ SharedSurface_Basic::~SharedSurface_Basi
 
     if (mFB)
         mGL->fDeleteFramebuffers(1, &mFB);
 
     if (mOwnsTex)
         mGL->fDeleteTextures(1, &mTex);
 }
 
+
 ////////////////////////////////////////////////////////////////////////
 
 SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps,
                                            const layers::TextureFlags& flags)
     : SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags)
 { }
 
+
+////////////////////////////////////////////////////////////////////////
+// SharedSurface_GLTexture
+
+/*static*/ UniquePtr<SharedSurface_GLTexture>
+SharedSurface_GLTexture::Create(GLContext* prodGL,
+                                const GLFormats& formats,
+                                const IntSize& size,
+                                bool hasAlpha)
+{
+    MOZ_ASSERT(prodGL);
+
+    prodGL->MakeCurrent();
+
+    UniquePtr<SharedSurface_GLTexture> ret;
+    GLContext::LocalErrorScope localError(*prodGL);
+
+    GLuint tex = CreateTextureForOffscreen(prodGL, formats, size);
+
+    GLenum err = localError.GetError();
+    MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY);
+    if (err) {
+        prodGL->fDeleteTextures(1, &tex);
+        return Move(ret);
+    }
+
+    ret.reset(new SharedSurface_GLTexture(prodGL, size,
+                                          hasAlpha, tex));
+    return Move(ret);
+}
+
+SharedSurface_GLTexture::~SharedSurface_GLTexture()
+{
+    if (!mGL->MakeCurrent())
+        return;
+
+    if (mTex) {
+        mGL->fDeleteTextures(1, &mTex);
+    }
+
+    if (mSync) {
+        mGL->fDeleteSync(mSync);
+    }
+}
+
+void
+SharedSurface_GLTexture::ProducerReleaseImpl()
+{
+    mGL->MakeCurrent();
+
+    if (mGL->IsExtensionSupported(GLContext::ARB_sync)) {
+        if (mSync) {
+            mGL->fDeleteSync(mSync);
+            mSync = 0;
+        }
+
+        mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+        if (mSync) {
+            mGL->fFlush();
+            return;
+        }
+    }
+    MOZ_ASSERT(!mSync);
+
+    mGL->fFinish();
+}
+
+bool
+SharedSurface_GLTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
+{
+    *out_descriptor = layers::SurfaceDescriptorSharedGLTexture(ProdTexture(),
+                                                               ProdTextureTarget(),
+                                                               (uintptr_t)mSync,
+                                                               mSize,
+                                                               mHasAlpha);
+
+    // Transfer ownership of the fence to the host
+    mSync = nullptr;
+    return true;
+}
+
+
 } // namespace gl
 
 } /* namespace mozilla */
--- a/gfx/gl/SharedSurfaceGL.h
+++ b/gfx/gl/SharedSurfaceGL.h
@@ -88,13 +88,85 @@ public:
                          const layers::TextureFlags& flags);
 
     virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
         bool hasAlpha = mReadCaps.alpha;
         return SharedSurface_Basic::Create(mGL, mFormats, size, hasAlpha);
     }
 };
 
+
+// Using shared GL textures:
+class SharedSurface_GLTexture
+    : public SharedSurface
+{
+public:
+    static UniquePtr<SharedSurface_GLTexture> Create(GLContext* prodGL,
+                                                     const GLFormats& formats,
+                                                     const gfx::IntSize& size,
+                                                     bool hasAlpha);
+
+    static SharedSurface_GLTexture* Cast(SharedSurface* surf) {
+        MOZ_ASSERT(surf->mType == SharedSurfaceType::SharedGLTexture);
+
+        return (SharedSurface_GLTexture*)surf;
+    }
+
+protected:
+    const GLuint mTex;
+    GLsync mSync;
+
+    SharedSurface_GLTexture(GLContext* prodGL,
+                            const gfx::IntSize& size,
+                            bool hasAlpha,
+                            GLuint tex)
+        : SharedSurface(SharedSurfaceType::SharedGLTexture,
+                        AttachmentType::GLTexture,
+                        prodGL,
+                        size,
+                        hasAlpha, true)
+        , mTex(tex)
+        , mSync(0)
+    {
+    }
+
+public:
+    virtual ~SharedSurface_GLTexture();
+
+    virtual void LockProdImpl() override {}
+    virtual void UnlockProdImpl() override {}
+
+    virtual void ProducerReleaseImpl() override;
+
+    virtual void Fence() override {}
+    virtual bool WaitSync() override { MOZ_CRASH("should not be called"); }
+    virtual bool PollSync() override { MOZ_CRASH("should not be called"); }
+
+    virtual GLuint ProdTexture() override {
+        return mTex;
+    }
+
+    virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
+};
+
+class SurfaceFactory_GLTexture
+    : public SurfaceFactory
+{
+public:
+    SurfaceFactory_GLTexture(GLContext* prodGL,
+                             const SurfaceCaps& caps,
+                             const RefPtr<layers::ISurfaceAllocator>& allocator,
+                             const layers::TextureFlags& flags)
+        : SurfaceFactory(SharedSurfaceType::SharedGLTexture, prodGL, caps, allocator, flags)
+    {
+    }
+
+    virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
+        bool hasAlpha = mReadCaps.alpha;
+        return SharedSurface_GLTexture::Create(mGL, mFormats, size, hasAlpha);
+    }
+};
+
 } // namespace gl
 
 } /* namespace mozilla */
 
 #endif /* SHARED_SURFACE_GL_H_ */
--- a/gfx/gl/SurfaceTypes.h
+++ b/gfx/gl/SurfaceTypes.h
@@ -72,16 +72,17 @@ enum class SharedSurfaceType : uint8_t {
     Basic,
     EGLImageShare,
     EGLSurfaceANGLE,
     DXGLInterop,
     DXGLInterop2,
     Gralloc,
     IOSurface,
     GLXDrawable,
+    SharedGLTexture,
 
     Max
 };
 
 enum class AttachmentType : uint8_t {
     Screen = 0,
 
     GLTexture,
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -210,16 +210,17 @@ TextureHost::Create(const SurfaceDescrip
     case SurfaceDescriptor::TSurfaceDescriptorShmem:
     case SurfaceDescriptor::TSurfaceDescriptorMemory:
     case SurfaceDescriptor::TSurfaceDescriptorDIB:
     case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
       return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
 
     case SurfaceDescriptor::TEGLImageDescriptor:
     case SurfaceDescriptor::TSurfaceTextureDescriptor:
+    case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
       return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
 
     case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
       if (aBackend == LayersBackend::LAYERS_OPENGL) {
         return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
       } else {
         return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -77,16 +77,24 @@ struct SurfaceTextureDescriptor {
 
 struct EGLImageDescriptor {
   uintptr_t image; // `EGLImage` is a `void*`.
   uintptr_t fence;
   IntSize size;
   bool hasAlpha;
 };
 
+struct SurfaceDescriptorSharedGLTexture {
+  uint32_t texture;
+  uint32_t target;
+  uintptr_t fence;
+  IntSize size;
+  bool hasAlpha;
+};
+
 struct NewSurfaceDescriptorGralloc {
   MaybeMagicGrallocBufferHandle buffer;
   bool isOpaque;
 };
 
 /**
  * Used for shmem-backed YCbCr and (flavors of) RGBA textures
  */
@@ -111,13 +119,14 @@ union SurfaceDescriptor {
   SurfaceDescriptorD3D10;
   SurfaceDescriptorFileMapping;
   SurfaceDescriptorDXGIYCbCr;
   SurfaceDescriptorX11;
   SurfaceTextureDescriptor;
   EGLImageDescriptor;
   SurfaceDescriptorMacIOSurface;
   NewSurfaceDescriptorGralloc;
+  SurfaceDescriptorSharedGLTexture;
   null_t;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -99,16 +99,26 @@ CreateTextureHostOGL(const SurfaceDescri
 
 #ifdef GL_PROVIDER_GLX
     case SurfaceDescriptor::TSurfaceDescriptorX11: {
       const auto& desc = aDesc.get_SurfaceDescriptorX11();
       result = new X11TextureHost(aFlags, desc);
       break;
     }
 #endif
+
+    case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: {
+      const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture();
+      result = new GLTextureHost(aFlags, desc.texture(),
+                                 desc.target(),
+                                 (GLsync)desc.fence(),
+                                 desc.size(),
+                                 desc.hasAlpha());
+      break;
+    }
     default: return nullptr;
   }
   return result.forget();
 }
 
 static gl::TextureImage::Flags
 FlagsToGLFlags(TextureFlags aFlags)
 {
@@ -640,10 +650,81 @@ EGLImageTextureHost::SetCompositor(Compo
 
 gfx::SurfaceFormat
 EGLImageTextureHost::GetFormat() const
 {
   MOZ_ASSERT(mTextureSource);
   return mTextureSource->GetFormat();
 }
 
+//
+
+GLTextureHost::GLTextureHost(TextureFlags aFlags,
+                             GLuint aTextureHandle,
+                             GLenum aTarget,
+                             GLsync aSync,
+                             gfx::IntSize aSize,
+                             bool aHasAlpha)
+  : TextureHost(aFlags)
+  , mTexture(aTextureHandle)
+  , mTarget(aTarget)
+  , mSync(aSync)
+  , mSize(aSize)
+  , mHasAlpha(aHasAlpha)
+  , mCompositor(nullptr)
+{}
+
+GLTextureHost::~GLTextureHost()
+{}
+
+gl::GLContext*
+GLTextureHost::gl() const
+{
+  return mCompositor ? mCompositor->gl() : nullptr;
+}
+
+bool
+GLTextureHost::Lock()
+{
+  if (!mCompositor) {
+    return false;
+  }
+
+  if (mSync) {
+    gl()->MakeCurrent();
+    gl()->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED);
+    gl()->fDeleteSync(mSync);
+    mSync = 0;
+  }
+
+  if (!mTextureSource) {
+    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
+                                          : gfx::SurfaceFormat::R8G8B8X8;
+    mTextureSource = new GLTextureSource(mCompositor,
+                                         mTexture,
+                                         mTarget,
+                                         mSize,
+                                         format,
+                                         false /* owned by the client */);
+  }
+
+  return true;
+}
+void
+GLTextureHost::SetCompositor(Compositor* aCompositor)
+{
+  MOZ_ASSERT(aCompositor);
+  CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
+  mCompositor = glCompositor;
+  if (mTextureSource) {
+    mTextureSource->SetCompositor(glCompositor);
+  }
+}
+
+gfx::SurfaceFormat
+GLTextureHost::GetFormat() const
+{
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetFormat();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -274,16 +274,66 @@ protected:
   GLenum mTextureTarget;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   // If the texture is externally owned, the gl handle will not be deleted
   // in the destructor.
   bool mExternallyOwned;
 };
 
+class GLTextureHost : public TextureHost
+{
+public:
+  GLTextureHost(TextureFlags aFlags,
+                GLuint aTextureHandle,
+                GLenum aTarget,
+                GLsync aSync,
+                gfx::IntSize aSize,
+                bool aHasAlpha);
+
+  virtual ~GLTextureHost();
+
+  // We don't own anything.
+  virtual void DeallocateDeviceData() override {}
+
+  virtual void SetCompositor(Compositor* aCompositor) override;
+
+  virtual bool Lock() override;
+
+  virtual void Unlock() override {}
+
+  virtual gfx::SurfaceFormat GetFormat() const override;
+
+  virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
+  {
+    aTexture = mTextureSource;
+    return !!aTexture;
+  }
+
+  virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
+  {
+    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
+  }
+
+  gl::GLContext* gl() const;
+
+  virtual gfx::IntSize GetSize() const override { return mSize; }
+
+  virtual const char* Name() override { return "GLTextureHost"; }
+
+protected:
+  const GLuint mTexture;
+  const GLenum mTarget;
+  GLsync mSync;
+  const gfx::IntSize mSize;
+  const bool mHasAlpha;
+  RefPtr<CompositorOGL> mCompositor;
+  RefPtr<GLTextureSource> mTextureSource;
+};
+
 ////////////////////////////////////////////////////////////////////////
 // SurfaceTexture
 
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureSource : public TextureSource
                            , public TextureSourceOGL
 {