Commit 4c1386bc authored by Andrew Osmond's avatar Andrew Osmond
Browse files

Bug 1827024. r=gfx-reviewers,lsalzman a=RyanVM

parent 3569b64e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ bool D3D11YCbCrImage::SetData(KnowsCompositor* aAllocator,
  mColorRange = aData.mColorRange;
  mChromaSubsampling = aData.mChromaSubsampling;

  D3D11YCbCrRecycleAllocator* allocator =
  RefPtr<D3D11YCbCrRecycleAllocator> allocator =
      aContainer->GetD3D11YCbCrRecycleAllocator(aAllocator);
  if (!allocator) {
    return false;
+23 −14
Original line number Diff line number Diff line
@@ -325,18 +325,22 @@ void ImageContainer::SetCurrentImages(const nsTArray<NonOwningImage>& aImages) {
}

void ImageContainer::ClearAllImages() {
  mRecursiveMutex.Lock();
  if (mImageClient) {
    RefPtr<ImageClient> imageClient = mImageClient;
    mRecursiveMutex.Unlock();

    // Let ImageClient release all TextureClients. This doesn't return
    // until ImageBridge has called ClearCurrentImageFromImageBridge.
    if (RefPtr<ImageBridgeChild> imageBridge =
            ImageBridgeChild::GetSingleton()) {
      imageBridge->FlushAllImages(mImageClient, this);
      imageBridge->FlushAllImages(imageClient, this);
    }
    return;
  }

  RecursiveMutexAutoLock lock(mRecursiveMutex);
  SetCurrentImageInternal(nsTArray<NonOwningImage>());
  mRecursiveMutex.Unlock();
}

void ImageContainer::ClearCachedResources() {
@@ -360,7 +364,7 @@ void ImageContainer::SetCurrentImageInTransaction(Image* aImage) {
void ImageContainer::SetCurrentImagesInTransaction(
    const nsTArray<NonOwningImage>& aImages) {
  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
  NS_ASSERTION(!mImageClient,
  NS_ASSERTION(!HasImageClient(),
               "Should use async image transfer with ImageBridge.");

  SetCurrentImageInternal(aImages);
@@ -371,8 +375,8 @@ bool ImageContainer::IsAsync() const { return mIsAsync; }
CompositableHandle ImageContainer::GetAsyncContainerHandle() {
  NS_ASSERTION(IsAsync(),
               "Shared image ID is only relevant to async ImageContainers");
  NS_ASSERTION(mAsyncContainerHandle, "Should have a shared image ID");
  RecursiveMutexAutoLock mon(mRecursiveMutex);
  NS_ASSERTION(mAsyncContainerHandle, "Should have a shared image ID");
  EnsureImageClient();
  return mAsyncContainerHandle;
}
@@ -433,9 +437,11 @@ void ImageContainer::NotifyDropped(uint32_t aDropped) {
void ImageContainer::EnsureRecycleAllocatorForRDD(
    KnowsCompositor* aKnowsCompositor) {
  MOZ_ASSERT(!mIsAsync);
  MOZ_ASSERT(!mImageClient);
  MOZ_ASSERT(XRE_IsRDDProcess());

  RecursiveMutexAutoLock lock(mRecursiveMutex);
  MOZ_ASSERT(!mImageClient);

  if (mRecycleAllocator &&
      aKnowsCompositor == mRecycleAllocator->GetKnowsCompositor()) {
    return;
@@ -453,32 +459,35 @@ void ImageContainer::EnsureRecycleAllocatorForRDD(
}

#ifdef XP_WIN
D3D11YCbCrRecycleAllocator* ImageContainer::GetD3D11YCbCrRecycleAllocator(
already_AddRefed<D3D11YCbCrRecycleAllocator>
ImageContainer::GetD3D11YCbCrRecycleAllocator(
    KnowsCompositor* aKnowsCompositor) {
  if (mD3D11YCbCrRecycleAllocator &&
      aKnowsCompositor == mD3D11YCbCrRecycleAllocator->GetKnowsCompositor()) {
    return mD3D11YCbCrRecycleAllocator;
  }

  if (!aKnowsCompositor->SupportsD3D11() ||
      !gfx::DeviceManagerDx::Get()->GetImageDevice()) {
    return nullptr;
  }

  RecursiveMutexAutoLock lock(mRecursiveMutex);
  if (mD3D11YCbCrRecycleAllocator &&
      aKnowsCompositor == mD3D11YCbCrRecycleAllocator->GetKnowsCompositor()) {
    return do_AddRef(mD3D11YCbCrRecycleAllocator);
  }

  mD3D11YCbCrRecycleAllocator =
      new D3D11YCbCrRecycleAllocator(aKnowsCompositor);
  return mD3D11YCbCrRecycleAllocator;
  return do_AddRef(mD3D11YCbCrRecycleAllocator);
}
#endif

#ifdef XP_MACOSX
MacIOSurfaceRecycleAllocator*
already_AddRefed<MacIOSurfaceRecycleAllocator>
ImageContainer::GetMacIOSurfaceRecycleAllocator() {
  RecursiveMutexAutoLock lock(mRecursiveMutex);
  if (!mMacIOSurfaceRecycleAllocator) {
    mMacIOSurfaceRecycleAllocator = new MacIOSurfaceRecycleAllocator();
  }

  return mMacIOSurfaceRecycleAllocator;
  return do_AddRef(mMacIOSurfaceRecycleAllocator);
}
#endif

+65 −33
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "nsDebug.h"           // for NS_ASSERTION
#include "nsISupportsImpl.h"   // for Image::Release, etc
#include "nsTArray.h"          // for nsTArray
#include "nsThreadUtils.h"     // for NS_IsMainThread
#include "mozilla/Atomics.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/EnumeratedArray.h"
@@ -197,13 +198,13 @@ class BufferRecycleBin final {

  // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
  // and mRecycledTextureSizes
  Mutex mLock MOZ_UNANNOTATED;
  Mutex mLock;

  // We should probably do something to prune this list on a timer so we don't
  // eat excess memory while video is paused...
  nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers;
  nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers GUARDED_BY(mLock);
  // This is only valid if mRecycledBuffers is non-empty
  uint32_t mRecycledBufferSize;
  uint32_t mRecycledBufferSize GUARDED_BY(mLock);
};

/**
@@ -251,8 +252,8 @@ class ImageContainerListener final {

  ~ImageContainerListener();

  Mutex mLock MOZ_UNANNOTATED;
  ImageContainer* mImageContainer;
  Mutex mLock;
  ImageContainer* mImageContainer GUARDED_BY(mLock);
};

/**
@@ -442,36 +443,56 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
   * Can be called on any thread. This method takes mRecursiveMutex
   * when accessing thread-shared state.
   */
  void SetScaleHint(const gfx::IntSize& aScaleHint) { mScaleHint = aScaleHint; }
  void SetScaleHint(const gfx::IntSize& aScaleHint) {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    mScaleHint = aScaleHint;
  }

  const gfx::IntSize& GetScaleHint() const { return mScaleHint; }
  const gfx::IntSize GetScaleHint() const {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    return mScaleHint;
  }

  void SetTransformHint(const gfx::Matrix& aTransformHint) {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    mTransformHint = aTransformHint;
  }

  const gfx::Matrix& GetTransformHint() const { return mTransformHint; }
  const gfx::Matrix GetTransformHint() const {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    return mTransformHint;
  }

  void SetRotation(VideoInfo::Rotation aRotation) { mRotation = aRotation; }
  void SetRotation(VideoInfo::Rotation aRotation) {
    MOZ_ASSERT(NS_IsMainThread());
    mRotation = aRotation;
  }

  VideoInfo::Rotation GetRotation() const { return mRotation; }
  VideoInfo::Rotation GetRotation() const {
    MOZ_ASSERT(NS_IsMainThread());
    return mRotation;
  }

  void SetImageFactory(ImageFactory* aFactory) {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    mImageFactory = aFactory ? aFactory : new ImageFactory();
  }

  ImageFactory* GetImageFactory() const { return mImageFactory; }
  already_AddRefed<ImageFactory> GetImageFactory() const {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    return do_AddRef(mImageFactory);
  }

  void EnsureRecycleAllocatorForRDD(KnowsCompositor* aKnowsCompositor);

#ifdef XP_WIN
  D3D11YCbCrRecycleAllocator* GetD3D11YCbCrRecycleAllocator(
  already_AddRefed<D3D11YCbCrRecycleAllocator> GetD3D11YCbCrRecycleAllocator(
      KnowsCompositor* aKnowsCompositor);
#endif

#ifdef XP_MACOSX
  MacIOSurfaceRecycleAllocator* GetMacIOSurfaceRecycleAllocator();
  already_AddRefed<MacIOSurfaceRecycleAllocator>
  GetMacIOSurfaceRecycleAllocator();
#endif

  /**
@@ -509,8 +530,9 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
  void NotifyComposite(const ImageCompositeNotification& aNotification);
  void NotifyDropped(uint32_t aDropped);

  ImageContainerListener* GetImageContainerListener() {
    return mNotifyCompositeListener;
  already_AddRefed<ImageContainerListener> GetImageContainerListener() {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    return do_AddRef(mNotifyCompositeListener);
  }

  /**
@@ -538,33 +560,41 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
  // calling this function!
  void EnsureActiveImage();

  void EnsureImageClient();
  void EnsureImageClient() REQUIRES(mRecursiveMutex);

  bool HasImageClient() const {
    RecursiveMutexAutoLock lock(mRecursiveMutex);
    return !!mImageClient;
  }

  // RecursiveMutex to protect thread safe access to the "current
  // image", and any other state which is shared between threads.
  RecursiveMutex mRecursiveMutex MOZ_UNANNOTATED;
  mutable RecursiveMutex mRecursiveMutex;

  RefPtr<TextureClientRecycleAllocator> mRecycleAllocator;
  RefPtr<TextureClientRecycleAllocator> mRecycleAllocator
      GUARDED_BY(mRecursiveMutex);

#ifdef XP_WIN
  RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator;
  RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator
      GUARDED_BY(mRecursiveMutex);
#endif
#ifdef XP_MACOSX
  RefPtr<MacIOSurfaceRecycleAllocator> mMacIOSurfaceRecycleAllocator;
  RefPtr<MacIOSurfaceRecycleAllocator> mMacIOSurfaceRecycleAllocator
      GUARDED_BY(mRecursiveMutex);
#endif

  nsTArray<OwningImage> mCurrentImages;
  nsTArray<OwningImage> mCurrentImages GUARDED_BY(mRecursiveMutex);

  // Updates every time mActiveImage changes
  uint32_t mGenerationCounter;
  uint32_t mGenerationCounter GUARDED_BY(mRecursiveMutex);

  // Number of contained images that have been painted at least once.  It's up
  // to the ImageContainer implementation to ensure accesses to this are
  // threadsafe.
  uint32_t mPaintCount;
  uint32_t mPaintCount GUARDED_BY(mRecursiveMutex);

  // See GetPaintDelay. Accessed only with mRecursiveMutex held.
  TimeDuration mPaintDelay;
  TimeDuration mPaintDelay GUARDED_BY(mRecursiveMutex);

  // See GetDroppedImageCount.
  mozilla::Atomic<uint32_t> mDroppedImageCount;
@@ -572,15 +602,16 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
  // This is the image factory used by this container, layer managers using
  // this container can set an alternative image factory that will be used to
  // create images for this container.
  RefPtr<ImageFactory> mImageFactory;
  RefPtr<ImageFactory> mImageFactory GUARDED_BY(mRecursiveMutex);

  gfx::IntSize mScaleHint;
  gfx::IntSize mScaleHint GUARDED_BY(mRecursiveMutex);

  gfx::Matrix mTransformHint;
  gfx::Matrix mTransformHint GUARDED_BY(mRecursiveMutex);

  // Main thread only.
  VideoInfo::Rotation mRotation = VideoInfo::Rotation::kDegree_0;

  RefPtr<BufferRecycleBin> mRecycleBin;
  RefPtr<BufferRecycleBin> mRecycleBin GUARDED_BY(mRecursiveMutex);

  // This member points to an ImageClient if this ImageContainer was
  // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
@@ -589,15 +620,16 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
  // In this case the ImageContainer is perfectly usable, but it will forward
  // frames to the compositor through transactions in the main thread rather
  // than asynchronusly using the ImageBridge IPDL protocol.
  RefPtr<ImageClient> mImageClient;
  RefPtr<ImageClient> mImageClient GUARDED_BY(mRecursiveMutex);

  bool mIsAsync;
  CompositableHandle mAsyncContainerHandle;
  const bool mIsAsync;
  CompositableHandle mAsyncContainerHandle GUARDED_BY(mRecursiveMutex);

  // ProducerID for last current image(s)
  ProducerID mCurrentProducerID;
  ProducerID mCurrentProducerID GUARDED_BY(mRecursiveMutex);

  RefPtr<ImageContainerListener> mNotifyCompositeListener;
  RefPtr<ImageContainerListener> mNotifyCompositeListener
      GUARDED_BY(mRecursiveMutex);

  static mozilla::Atomic<uint32_t> sGenerationCounter;
};