Bug 1374548 - Implement the frame selection in BasicImageLayer. r=mattwoodrow a=relanding
authorJerryShih <hshih@mozilla.com>
Fri, 30 Jun 2017 11:57:14 -0700
changeset 602839 57b57379c60c6b938881f80cd58a62479358465a
parent 602765 abd8809269675a9c5efb6778b19ba6e6607f626d
child 602840 4140a976847a901ad2c2b40209767b3af4297457
child 602909 f8a62747c51c862b6e2f5c0af543ef21d34abf3b
child 602934 9905ca4801263f730311b26d17dbcbb6bfdc5189
child 602935 604efb7f53fc5fad2420f04315861d1edeb295b4
child 677488 19cb4ef6798fe330f0a320b04f7918550df2a8b2
push id66575
push userbmo:gijskruitbosch+bugs@gmail.com
push dateFri, 30 Jun 2017 21:02:30 +0000
reviewersmattwoodrow, relanding
bugs1374548
milestone56.0a1
Bug 1374548 - Implement the frame selection in BasicImageLayer. r=mattwoodrow a=relanding The BasicImageLayer always picks the first frame in image container which is not desired for video playback. MozReview-Commit-ID: q4QkBT2a7w
gfx/layers/ImageContainer.h
gfx/layers/basic/BasicImageLayer.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -688,16 +688,33 @@ public:
   }
 
   bool HasImage() const { return !mImages.IsEmpty(); }
   Image* GetImage() const
   {
     return mImages.IsEmpty() ? nullptr : mImages[0].mImage.get();
   }
 
+  Image* GetImage(TimeStamp aTimeStamp) const
+  {
+    if (mImages.IsEmpty()) {
+      return nullptr;
+    }
+
+    MOZ_ASSERT(!aTimeStamp.IsNull());
+    uint32_t chosenIndex = 0;
+
+    while (chosenIndex + 1 < mImages.Length() &&
+           mImages[chosenIndex + 1].mTimeStamp <= aTimeStamp) {
+      ++chosenIndex;
+    }
+
+    return mImages[chosenIndex].mImage.get();
+  }
+
 private:
   AutoTArray<ImageContainer::OwningImage,4> mImages;
 };
 
 struct PlanarYCbCrData {
   // Luminance buffer
   uint8_t* mYChannel;
   int32_t mYStride;
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -67,17 +67,17 @@ BasicImageLayer::Paint(DrawTarget* aDT,
   if (IsHidden() || !mContainer) {
     return;
   }
 
   RefPtr<ImageFactory> originalIF = mContainer->GetImageFactory();
   mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nullptr : BasicManager()->GetImageFactory());
 
   AutoLockImage autoLock(mContainer);
-  Image *image = autoLock.GetImage();
+  Image *image = autoLock.GetImage(BasicManager()->GetCompositionTime());
   if (!image) {
     mContainer->SetImageFactory(originalIF);
     return;
   }
   RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
   if (!surface || !surface->IsValid()) {
     mContainer->SetImageFactory(originalIF);
     return;
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -567,16 +567,18 @@ BasicLayerManager::EndTransactionInterna
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
   mPhase = PHASE_DRAWING;
 
+  SetCompositionTime(TimeStamp::Now());
+
   RenderTraceLayers(mRoot, "FF00");
 
   mTransactionIncomplete = false;
 
   if (mRoot) {
     if (aFlags & END_NO_COMPOSITE) {
       // Apply pending tree updates before recomputing effective
       // properties.
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -8,16 +8,17 @@
 
 #include <stdint.h>                     // for INT32_MAX, int32_t
 #include "Layers.h"                     // for Layer (ptr only), etc
 #include "gfxTypes.h"
 #include "gfxContext.h"                 // for gfxContext
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/WidgetUtils.h"        // for ScreenRotation
 #include "mozilla/layers/LayersTypes.h"  // for BufferMode, LayersBackend, etc
+#include "mozilla/TimeStamp.h"
 #include "nsAString.h"
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for gfxContext::AddRef, etc
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nscore.h"                     // for nsAString, etc
 
 class nsIWidget;
 
@@ -163,16 +164,21 @@ public:
   bool PushGroupForLayer(gfxContext* aContext, Layer* aLayerContext, const nsIntRegion& aRegion, PushedGroup& aGroupResult);
 
   void PopGroupForLayer(PushedGroup& aGroup);
 
   virtual bool IsCompositingCheap() override { return false; }
   virtual int32_t GetMaxTextureSize() const override { return INT32_MAX; }
   bool CompositorMightResample() { return mCompositorMightResample; }
 
+  TimeStamp GetCompositionTime() const
+  {
+    return mCompositionTime;
+  }
+
 protected:
   enum TransactionPhase {
     PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
   };
   TransactionPhase mPhase;
 
   // This is the main body of the PaintLayer routine which will if it has
   // children, recurse into PaintLayer() otherwise it will paint using the
@@ -193,29 +199,36 @@ protected:
   void ClearLayer(Layer* aLayer);
 
   bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT);
 
   void FlashWidgetUpdateArea(gfxContext* aContext);
 
+  void SetCompositionTime(TimeStamp aTimeStamp)
+  {
+    mCompositionTime = aTimeStamp;
+  }
+
   // Widget whose surface should be used as the basis for PaintedLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   RefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   RefPtr<gfxContext> mTarget;
   // Image factory we use.
   RefPtr<ImageFactory> mFactory;
 
   BufferMode mDoubleBuffering;
   BasicLayerManagerType mType;
   bool mUsingDefaultTarget;
   bool mTransactionIncomplete;
   bool mCompositorMightResample;
+
+  TimeStamp mCompositionTime;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_BASICLAYERS_H */