Bug 1300682 - Part 1: Make sure we create a TextureClient for VideoBridge even if the layers::Image doesn't support GetTextureClient. r=nical
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 07 Oct 2016 21:13:32 +1300
changeset 316884 66adb66eeed57f304d0fc98de490e5714412e2b9
parent 316883 01fd505d5cc2621881fa344d977b5054ad055f3b
child 316885 9aec9ca6a65915dfbb370c3e7a5af3bbd1c6ed2e
push id82560
push usermwoodrow@mozilla.com
push dateFri, 07 Oct 2016 08:13:28 +0000
treeherdermozilla-inbound@4b28c86a0536 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1300682
milestone52.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 1300682 - Part 1: Make sure we create a TextureClient for VideoBridge even if the layers::Image doesn't support GetTextureClient. r=nical
dom/media/ipc/VideoDecoderParent.cpp
gfx/layers/client/ImageClient.cpp
gfx/layers/client/ImageClient.h
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -4,16 +4,17 @@
  * 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 "VideoDecoderParent.h"
 #include "mozilla/Unused.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "base/thread.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/VideoBridgeChild.h"
+#include "mozilla/layers/ImageClient.h"
 #include "MediaInfo.h"
 #include "VideoDecoderManagerParent.h"
 #ifdef XP_WIN
 #include "WMFDecoderModule.h"
 #endif
 
 namespace mozilla {
 namespace dom {
@@ -171,16 +172,22 @@ VideoDecoderParent::Output(MediaData* aD
 
     MOZ_ASSERT(data->mType == MediaData::VIDEO_DATA, "Can only decode videos using VideoDecoderParent!");
     VideoData* video = static_cast<VideoData*>(data.get());
 
     MOZ_ASSERT(video->mImage, "Decoded video must output a layer::Image to be used with VideoDecoderParent");
 
     RefPtr<TextureClient> texture = video->mImage->GetTextureClient(VideoBridgeChild::GetSingleton());
 
+    if (!texture) {
+      texture =
+        ImageClient::CreateTextureClientForImage(video->mImage,
+                                                 VideoBridgeChild::GetSingleton());
+    }
+
     if (texture && !texture->IsAddedToCompositableClient()) {
       texture->InitIPDLActor(VideoBridgeChild::GetSingleton());
       texture->SetAddedToCompositableClient();
     }
 
     VideoDataIPDL output(MediaDataIPDL(data->mOffset,
                                        data->mTime,
                                        data->mTimecode,
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -106,16 +106,92 @@ ImageClientSingle::FlushAllImages(AsyncT
   MOZ_ASSERT(GetForwarder()->GetTextureForwarder()->UsesImageBridge());
 
   for (auto& b : mBuffers) {
     RemoveTextureWithWaiter(b.mTextureClient, aAsyncTransactionWaiter);
   }
   mBuffers.Clear();
 }
 
+/* static */ already_AddRefed<TextureClient>
+ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwarder)
+{
+  RefPtr<TextureClient> texture;
+  if (aImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
+    PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(aImage);
+    const PlanarYCbCrData* data = ycbcr->GetData();
+    if (!data) {
+      return nullptr;
+    }
+    texture = TextureClient::CreateForYCbCr(aForwarder,
+                                            data->mYSize, data->mCbCrSize, data->mStereoMode,
+                                            TextureFlags::DEFAULT);
+    if (!texture) {
+      return nullptr;
+    }
+
+    TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
+    if (!autoLock.Succeeded()) {
+      return nullptr;
+    }
+
+    bool status = UpdateYCbCrTextureClient(texture, *data);
+    MOZ_ASSERT(status);
+    if (!status) {
+      return nullptr;
+    }
+  } else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
+             aImage->GetFormat() == ImageFormat::EGLIMAGE) {
+    gfx::IntSize size = aImage->GetSize();
+
+    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->GetSurfaceTexture(), size, typedImage->GetOriginPos(),
+        aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
+#endif
+    } else {
+      MOZ_ASSERT(false, "Bad ImageFormat.");
+    }
+  } else {
+    RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
+    MOZ_ASSERT(surface);
+    texture = TextureClient::CreateForDrawing(aForwarder, surface->GetFormat(), aImage->GetSize(),
+                                              BackendSelector::Content, TextureFlags::DEFAULT);
+    if (!texture) {
+      return nullptr;
+    }
+
+    MOZ_ASSERT(texture->CanExposeDrawTarget());
+
+    if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
+      return nullptr;
+    }
+
+    {
+      // We must not keep a reference to the DrawTarget after it has been unlocked.
+      DrawTarget* dt = texture->BorrowDrawTarget();
+      if (!dt) {
+        gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
+        return nullptr;
+      }
+      MOZ_ASSERT(surface.get());
+      dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
+    }
+
+    texture->Unlock();
+  }
+  return texture.forget();
+}
+
 bool
 ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
 {
   AutoTArray<ImageContainer::OwningImage,4> images;
   uint32_t generationCounter;
   aContainer->GetCurrentImages(&images, &generationCounter);
 
   if (mLastUpdateGenerationCounter == generationCounter) {
@@ -183,87 +259,17 @@ ImageClientSingle::UpdateImage(ImageCont
         mBuffers.RemoveElementAt(i);
       }
     }
 
     if (!texture) {
       // Slow path, we should not be hitting it very often and if we do it means
       // we are using an Image class that is not backed by textureClient and we
       // should fix it.
-      if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
-        PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
-        const PlanarYCbCrData* data = ycbcr->GetData();
-        if (!data) {
-          return false;
-        }
-        texture = TextureClient::CreateForYCbCr(GetForwarder(),
-          data->mYSize, data->mCbCrSize, data->mStereoMode,
-          TextureFlags::DEFAULT | mTextureFlags
-        );
-        if (!texture) {
-          return false;
-        }
-
-        TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
-        if (!autoLock.Succeeded()) {
-          return false;
-        }
-
-        bool status = UpdateYCbCrTextureClient(texture, *data);
-        MOZ_ASSERT(status);
-        if (!status) {
-          return false;
-        }
-      } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
-                 image->GetFormat() == ImageFormat::EGLIMAGE) {
-        gfx::IntSize size = image->GetSize();
-
-        if (image->GetFormat() == ImageFormat::EGLIMAGE) {
-          EGLImageImage* typedImage = image->AsEGLImageImage();
-          texture = EGLImageTextureData::CreateTextureClient(
-            typedImage, size, GetForwarder()->GetTextureForwarder(), mTextureFlags);
-#ifdef MOZ_WIDGET_ANDROID
-        } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
-          SurfaceTextureImage* typedImage = image->AsSurfaceTextureImage();
-          texture = AndroidSurfaceTextureData::CreateTextureClient(
-            typedImage->GetSurfaceTexture(), size, typedImage->GetOriginPos(),
-            GetForwarder()->GetTextureForwarder(), mTextureFlags
-          );
-#endif
-        } else {
-          MOZ_ASSERT(false, "Bad ImageFormat.");
-        }
-      } else {
-        RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
-        MOZ_ASSERT(surface);
-        texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
-                                                BackendSelector::Content, mTextureFlags);
-        if (!texture) {
-          return false;
-        }
-
-        MOZ_ASSERT(texture->CanExposeDrawTarget());
-
-        if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
-          return false;
-        }
-
-        {
-          // We must not keep a reference to the DrawTarget after it has been unlocked.
-          DrawTarget* dt = texture->BorrowDrawTarget();
-          if (!dt) {
-            gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
-            return false;
-          }
-          MOZ_ASSERT(surface.get());
-          dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
-        }
-
-        texture->Unlock();
-      }
+      texture = CreateTextureClientForImage(image, GetForwarder());
     }
     if (!texture || !AddTextureClient(texture)) {
       return false;
     }
 
 
     CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
     t->mTextureClient = texture;
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -68,16 +68,18 @@ public:
 
   virtual void RemoveTexture(TextureClient* aTexture) override;
 
   void RemoveTextureWithWaiter(TextureClient* aTexture,
                                AsyncTransactionWaiter* aAsyncTransactionWaiter = nullptr);
 
   virtual ImageClientSingle* AsImageClientSingle() { return nullptr; }
 
+  static already_AddRefed<TextureClient> CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwarder);
+
 protected:
   ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
               CompositableType aType);
 
   ClientLayer* mLayer;
   CompositableType mType;
   uint32_t mLastUpdateGenerationCounter;
 };