Bug 1322650 - Support a 'continuous' mode for SurfaceTexture r=jgilbert
☠☠ backed out by d3e4300c8976 ☠ ☠
authorJames Willcox <snorp@snorp.net>
Thu, 09 Mar 2017 17:50:21 -0600
changeset 404904 0c01bf8a1bd94de932c384cd51f5843922a82058
parent 404903 b79cbaa5cf1a149ef9e06f8dd07fe43a56634679
child 404905 d6516a10c8088a6ce872c888d88bc98a545a7fee
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1322650
milestone55.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 1322650 - Support a 'continuous' mode for SurfaceTexture r=jgilbert This is needed to support Flash on Android MozReview-Commit-ID: 5yNIoZHonla
dom/media/platforms/android/RemoteDataDecoder.cpp
gfx/gl/SharedSurfaceEGL.cpp
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/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -128,17 +128,17 @@ public:
       InputInfo inputInfo;
       if (!mDecoder->mInputInfos.Find(presentationTimeUs, inputInfo)
           && !isEOS) {
         return;
       }
 
       if (size > 0) {
         RefPtr<layers::Image> img = new SurfaceTextureImage(
-          mDecoder->mSurfaceHandle, inputInfo.mImageSize,
+          mDecoder->mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,
           gl::OriginPos::BottomLeft);
 
         RefPtr<VideoData> v = VideoData::CreateFromImage(
           inputInfo.mDisplaySize, offset,
           TimeUnit::FromMicroseconds(presentationTimeUs),
           TimeUnit::FromMicroseconds(inputInfo.mDurationUs),
           img, !!(flags & MediaCodec::BUFFER_FLAG_SYNC_FRAME),
           TimeUnit::FromMicroseconds(presentationTimeUs));
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -267,17 +267,17 @@ SharedSurface_SurfaceTexture::WaitForBuf
 {
     MOZ_RELEASE_ASSERT(!mSurface->GetAvailable());
     mSurface->SetAvailable(true);
 }
 
 bool
 SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
 {
-    *out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize);
+    *out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize, false /* NOT continuous */);
     return true;
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 /*static*/ UniquePtr<SurfaceFactory_SurfaceTexture>
 SurfaceFactory_SurfaceTexture::Create(GLContext* prodGL, const SurfaceCaps& caps,
                                       const RefPtr<layers::LayersIPCChannel>& allocator,
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -95,20 +95,22 @@ GLImage::GetAsSourceSurface()
   ScopedBindFramebuffer bind(sSnapshotContext, autoFBForTex.FB());
   ReadPixelsIntoDataSurface(sSnapshotContext, source);
   return source.forget();
 }
 
 #ifdef MOZ_WIDGET_ANDROID
 SurfaceTextureImage::SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
                                          const gfx::IntSize& aSize,
+                                         bool aContinuous,
                                          gl::OriginPos aOriginPos)
  : GLImage(ImageFormat::SURFACE_TEXTURE),
    mHandle(aHandle),
    mSize(aSize),
+   mContinuous(aContinuous),
    mOriginPos(aOriginPos)
 {
   MOZ_ASSERT(mHandle);
 }
 #endif
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -61,33 +61,38 @@ private:
 };
 
 #ifdef MOZ_WIDGET_ANDROID
 
 class SurfaceTextureImage : public GLImage {
 public:
   SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
                       const gfx::IntSize& aSize,
+                      bool aContinuous,
                       gl::OriginPos aOriginPos);
 
   gfx::IntSize GetSize() override { return mSize; }
   AndroidSurfaceTextureHandle GetHandle() const {
     return mHandle;
   }
+  bool GetContinuous() const {
+    return mContinuous;
+  }
   gl::OriginPos GetOriginPos() const {
     return mOriginPos;
   }
 
   SurfaceTextureImage* AsSurfaceTextureImage() override {
     return this;
   }
 
 private:
   AndroidSurfaceTextureHandle mHandle;
   gfx::IntSize mSize;
+  bool mContinuous;
   gl::OriginPos mOriginPos;
 };
 
 #endif // MOZ_WIDGET_ANDROID
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -127,17 +127,17 @@ ImageClient::CreateTextureClientForImage
     if (aImage->GetFormat() == ImageFormat::EGLIMAGE) {
       EGLImageImage* typedImage = aImage->AsEGLImageImage();
       texture = EGLImageTextureData::CreateTextureClient(
         typedImage, size, aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
 #ifdef MOZ_WIDGET_ANDROID
     } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
       SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
       texture = AndroidSurfaceTextureData::CreateTextureClient(
-        typedImage->GetHandle(), size, typedImage->GetOriginPos(),
+        typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
         aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
 #endif
     } else {
       MOZ_ASSERT(false, "Bad ImageFormat.");
     }
   } else {
     RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
     MOZ_ASSERT(surface);
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -57,16 +57,17 @@ struct SurfaceDescriptorMacIOSurface {
   uint32_t surfaceId;
   double scaleFactor;
   bool isOpaque;
 };
 
 struct SurfaceTextureDescriptor {
   uint64_t handle;
   IntSize size;
+  bool continuous;
 };
 
 struct EGLImageDescriptor {
   uintptr_t image; // `EGLImage` is a `void*`.
   uintptr_t fence;
   IntSize size;
   bool hasAlpha;
 };
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -76,34 +76,36 @@ EGLImageTextureData::Serialize(SurfaceDe
 ////////////////////////////////////////////////////////////////////////
 // AndroidSurface
 
 #ifdef MOZ_WIDGET_ANDROID
 
 already_AddRefed<TextureClient>
 AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
                                                gfx::IntSize aSize,
+                                               bool aContinuous,
                                                gl::OriginPos aOriginPos,
                                                LayersIPCChannel* aAllocator,
                                                TextureFlags aFlags)
 {
   if (aOriginPos == gl::OriginPos::BottomLeft) {
     aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
   }
 
   return TextureClient::CreateWithData(
-    new AndroidSurfaceTextureData(aHandle, aSize),
+    new AndroidSurfaceTextureData(aHandle, aSize, aContinuous),
     aFlags, aAllocator
   );
 }
 
 AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
-                                                     gfx::IntSize aSize)
+                                                     gfx::IntSize aSize, bool aContinuous)
   : mHandle(aHandle)
   , mSize(aSize)
+  , mContinuous(aContinuous)
 {
   MOZ_ASSERT(mHandle);
 }
 
 AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
 {}
 
 void
@@ -115,16 +117,16 @@ AndroidSurfaceTextureData::FillInfo(Text
   aInfo.hasSynchronization = false;
   aInfo.supportsMoz2D = false;
   aInfo.canExposeMappedData = false;
 }
 
 bool
 AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
-  aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize);
+  aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize, mContinuous);
   return true;
 }
 
 #endif // MOZ_WIDGET_ANDROID
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -51,16 +51,17 @@ protected:
 #ifdef MOZ_WIDGET_ANDROID
 
 class AndroidSurfaceTextureData : public TextureData
 {
 public:
   static already_AddRefed<TextureClient>
   CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
                       gfx::IntSize aSize,
+                      bool aContinuous,
                       gl::OriginPos aOriginPos,
                       LayersIPCChannel* aAllocator,
                       TextureFlags aFlags);
 
   ~AndroidSurfaceTextureData();
 
   virtual void FillInfo(TextureData::Info& aInfo) const override;
 
@@ -70,20 +71,21 @@ public:
   virtual bool Lock(OpenMode) override { return true; }
 
   virtual void Unlock() override {}
 
   // Our data is always owned externally.
   virtual void Deallocate(LayersIPCChannel*) override {}
 
 protected:
-  AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize);
+  AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous);
 
   const AndroidSurfaceTextureHandle mHandle;
   const gfx::IntSize mSize;
+  const bool mContinuous;
 };
 
 #endif // MOZ_WIDGET_ANDROID
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -57,17 +57,18 @@ CreateTextureHostOGL(const SurfaceDescri
     case SurfaceDescriptor::TSurfaceTextureDescriptor: {
       const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
       java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
 
       MOZ_RELEASE_ASSERT(surfaceTexture);
 
       result = new SurfaceTextureHost(aFlags,
                                       surfaceTexture,
-                                      desc.size());
+                                      desc.size(),
+                                      desc.continuous());
       break;
     }
 #endif
 
     case SurfaceDescriptor::TEGLImageDescriptor: {
       const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
       result = new EGLImageTextureHost(aFlags,
                                        (EGLImage)desc.image(),
@@ -406,38 +407,46 @@ SurfaceTextureSource::DeallocateDeviceDa
 {
   mSurfTex = nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
                                        mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
-                                       gfx::IntSize aSize)
+                                       gfx::IntSize aSize,
+                                       bool aContinuousUpdate)
   : TextureHost(aFlags)
   , mSurfTex(aSurfTex)
   , mSize(aSize)
+  , mContinuousUpdate(aContinuousUpdate)
 {
+  // Continuous update makes no sense with single buffer mode
+  MOZ_ASSERT(!mSurfTex->IsSingleBuffer() || !mContinuousUpdate);
 }
 
 SurfaceTextureHost::~SurfaceTextureHost()
 {
 }
 
 void
 SurfaceTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
 {
   GLContext* gl = this->gl();
   if (!gl || !gl->MakeCurrent()) {
     return;
   }
 
-  // This advances the SurfaceTexture's internal buffer queue. We only want to do this
-  // once per transaction. We can then composite that texture as many times as needed.
-  mSurfTex->UpdateTexImage();
+  if (!mContinuousUpdate) {
+    // UpdateTexImage() advances the internal buffer queue, so we only want to call this
+    // once per transactionwhen we are not in continuous mode (as we are here). Otherwise,
+    // the SurfaceTexture content will be de-synced from the rest of the page in subsequent
+    // compositor passes.
+    mSurfTex->UpdateTexImage();
+  }
 }
 
 gl::GLContext*
 SurfaceTextureHost::gl() const
 {
   return mProvider ? mProvider->GetGLContext() : nullptr;
 }
 
@@ -445,16 +454,20 @@ bool
 SurfaceTextureHost::Lock()
 {
   MOZ_ASSERT(mSurfTex);
   GLContext* gl = this->gl();
   if (!gl || !gl->MakeCurrent()) {
     return false;
   }
 
+  if (mContinuousUpdate) {
+    mSurfTex->UpdateTexImage();
+  }
+
   if (!mTextureSource) {
     gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
     GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
     GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
     mTextureSource = new SurfaceTextureSource(mProvider,
                                               mSurfTex,
                                               format,
                                               target,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -384,17 +384,18 @@ protected:
   const gfx::IntSize mSize;
 };
 
 class SurfaceTextureHost : public TextureHost
 {
 public:
   SurfaceTextureHost(TextureFlags aFlags,
                      mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
-                     gfx::IntSize aSize);
+                     gfx::IntSize aSize,
+                     bool aContinuousUpdate);
 
   virtual ~SurfaceTextureHost();
 
   virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override;
 
   virtual void DeallocateDeviceData() override;
 
   virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
@@ -420,16 +421,17 @@ public:
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual const char* Name() override { return "SurfaceTextureHost"; }
 
 protected:
   mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
   const gfx::IntSize mSize;
+  bool mContinuousUpdate;
   RefPtr<CompositorOGL> mCompositor;
   RefPtr<SurfaceTextureSource> mTextureSource;
 };
 
 #endif // MOZ_WIDGET_ANDROID
 
 ////////////////////////////////////////////////////////////////////////
 // EGLImage