Bug 1382985 - Support image animation for layers-free mode. r=kats draft
authorEthan Lin <ethlin@mozilla.com>
Mon, 24 Jul 2017 14:43:55 +0800
changeset 615504 0b6820537b6c43507c67f890af461363e4c7ca0f
parent 615492 9eddb0a92820c6445f9d1e680e4c239e888e93f0
child 639205 e7e8b27c6ec44650359e8ab69302f8eb8b0b1021
push id70388
push userbmo:ethlin@mozilla.com
push dateWed, 26 Jul 2017 03:49:18 +0000
reviewerskats
bugs1382985
milestone56.0a1
Bug 1382985 - Support image animation for layers-free mode. r=kats We should do SchedulePaint in nsImageFrame for layers-free mode and set invalid flag to make sure the image will be repainted. MozReview-Commit-ID: 2lXElZ151Qa
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderUserData.cpp
gfx/layers/wr/WebRenderUserData.h
layout/generic/nsImageFrame.cpp
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -432,17 +432,17 @@ WebRenderLayerManager::PushItemAsImage(n
 
       if (!lastBounds.IsEqualInterior(clippedBounds)) {
         invalidRegion.OrWith(lastBounds);
         invalidRegion.OrWith(clippedBounds);
       }
     }
   }
 
-  if (!geometry || !invalidRegion.IsEmpty()) {
+  if (!geometry || !invalidRegion.IsEmpty() || fallbackData->IsInvalid()) {
     if (gfxPrefs::WebRenderBlobImages()) {
       RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
       RefPtr<gfx::DrawTarget> dummyDt =
         gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8X8);
       RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
       PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
       recorder->Finish();
 
@@ -470,16 +470,17 @@ WebRenderLayerManager::PushItemAsImage(n
       // If not force update, fallbackData may reuse the original key because it
       // doesn't know UpdateImageHelper already updated the image container.
       if (!fallbackData->UpdateImageKey(imageContainer, true)) {
         return false;
       }
     }
 
     geometry = aItem->AllocateGeometry(aDisplayListBuilder);
+    fallbackData->SetInvalid(false);
   }
 
   // Update current bounds to fallback data
   fallbackData->SetGeometry(Move(geometry));
   fallbackData->SetBounds(clippedBounds);
 
   MOZ_ASSERT(fallbackData->GetKey());
 
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -143,22 +143,23 @@ WebRenderImageData::CreateImageClientIfN
 void
 WebRenderImageData::CreateExternalImageIfNeeded()
 {
   if (!mExternalImageId)  {
     mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient));
   }
 }
 
-WebRenderFallbackData::~WebRenderFallbackData()
+WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager)
+  : WebRenderImageData(aWRManager)
+  , mInvalid(false)
 {
 }
 
-WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager)
-  : WebRenderImageData(aWRManager)
+WebRenderFallbackData::~WebRenderFallbackData()
 {
 }
 
 nsAutoPtr<nsDisplayItemGeometry>
 WebRenderFallbackData::GetGeometry()
 {
   return mGeometry;
 }
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -13,28 +13,30 @@
 class nsDisplayItemGeometry;
 
 namespace mozilla {
 namespace layers {
 class ImageClient;
 class ImageContainer;
 class WebRenderBridgeChild;
 class WebRenderImageData;
+class WebRenderFallbackData;
 class WebRenderLayerManager;
 
 class WebRenderUserData
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(WebRenderUserData)
 
   explicit WebRenderUserData(WebRenderLayerManager* aWRManager)
     : mWRManager(aWRManager)
   { }
 
   virtual WebRenderImageData* AsImageData() { return nullptr; }
+  virtual WebRenderFallbackData* AsFallbackData() { return nullptr; }
 
   enum class UserDataType {
     eImage,
     eFallback,
     eAnimation,
   };
 
   virtual UserDataType GetType() = 0;
@@ -85,26 +87,30 @@ protected:
 };
 
 class WebRenderFallbackData : public WebRenderImageData
 {
 public:
   explicit WebRenderFallbackData(WebRenderLayerManager* aWRManager);
   virtual ~WebRenderFallbackData();
 
+  virtual WebRenderFallbackData* AsFallbackData() override { return this; }
   virtual UserDataType GetType() override { return UserDataType::eFallback; }
   static UserDataType Type() { return UserDataType::eFallback; }
   nsAutoPtr<nsDisplayItemGeometry> GetGeometry();
   void SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
   nsRect GetBounds() { return mBounds; }
   void SetBounds(const nsRect& aRect) { mBounds = aRect; }
+  void SetInvalid(bool aInvalid) { mInvalid = aInvalid; }
+  bool IsInvalid() { return mInvalid; }
 
 protected:
   nsAutoPtr<nsDisplayItemGeometry> mGeometry;
   nsRect mBounds;
+  bool mInvalid;
 };
 
 class WebRenderAnimationData : public WebRenderUserData
 {
 public:
   explicit WebRenderAnimationData(WebRenderLayerManager* aWRManager);
   virtual ~WebRenderAnimationData() {}
 
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -637,16 +637,28 @@ nsImageFrame::OnFrameUpdate(imgIRequest*
   InvalidateSelf(&layerInvalidRect, &frameInvalidRect);
   return NS_OK;
 }
 
 void
 nsImageFrame::InvalidateSelf(const nsIntRect* aLayerInvalidRect,
                              const nsRect* aFrameInvalidRect)
 {
+  if (HasProperty(nsIFrame::WebRenderUserDataProperty())) {
+    nsIFrame::WebRenderUserDataTable* userDataTable =
+      GetProperty(nsIFrame::WebRenderUserDataProperty());
+    RefPtr<WebRenderUserData> data;
+    userDataTable->Get(nsDisplayItem::TYPE_IMAGE, getter_AddRefs(data));
+    if (data && data->AsFallbackData()) {
+      data->AsFallbackData()->SetInvalid(true);
+    }
+    SchedulePaint();
+    return;
+  }
+
   InvalidateLayer(nsDisplayItem::TYPE_IMAGE,
                   aLayerInvalidRect,
                   aFrameInvalidRect);
 
   if (!mFirstFrameComplete) {
     InvalidateLayer(nsDisplayItem::TYPE_ALT_FEEDBACK,
                     aLayerInvalidRect,
                     aFrameInvalidRect);