Bug 1128225 (Part 3) - Add infrastructure for tracking draw results in geometry items. r=tn a=lmandel
authorSeth Fowler <seth@mozilla.com>
Wed, 04 Feb 2015 13:50:56 -0800
changeset 249871 09b37c4063346b0a0e0bc7bba42ecbf386ec08b6
parent 249870 c1ecd02b01291ae2d18e848cec37ccb00caf7e13
child 249872 46473c5ec5b2d99cf8d65aa076916968ea4e1077
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, lmandel
bugs1128225
milestone37.0a2
Bug 1128225 (Part 3) - Add infrastructure for tracking draw results in geometry items. r=tn a=lmandel
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsDisplayListInvalidation.h
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -4683,16 +4683,41 @@ FrameLayerBuilder::CheckDOMModified()
 }
 
 /* static */ void
 FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml)
 {
   aManager->Dump(aStream, "", aDumpHtml);
 }
 
+nsDisplayItemGeometry*
+FrameLayerBuilder::GetMostRecentGeometry(nsDisplayItem* aItem)
+{
+  typedef nsTArray<DisplayItemData*> DataArray;
+
+  // Retrieve the array of DisplayItemData associated with our frame.
+  FrameProperties properties = aItem->Frame()->Properties();
+  auto dataArray =
+    static_cast<DataArray*>(properties.Get(LayerManagerDataProperty()));
+  if (!dataArray) {
+    return nullptr;
+  }
+
+  // Find our display item data, if it exists, and return its geometry.
+  uint32_t itemPerFrameKey = aItem->GetPerFrameKey();
+  for (uint32_t i = 0; i < dataArray->Length(); i++) {
+    DisplayItemData* data = dataArray->ElementAt(i);
+    if (data->GetDisplayItemKey() == itemPerFrameKey) {
+      return data->GetGeometry();
+    }
+  }
+
+  return nullptr;
+}
+
 gfx::Rect
 CalculateBounds(const nsTArray<DisplayItemClip::RoundedRect>& aRects, int32_t A2D)
 {
   nsRect bounds = aRects[0].mRect;
   for (uint32_t i = 1; i < aRects.Length(); ++i) {
     bounds.UnionRect(bounds, aRects[i].mRect);
    }
 
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -269,16 +269,27 @@ public:
                               void* aCallbackData);
 
   /**
    * Dumps this FrameLayerBuilder's retained layer manager's retained
    * layer tree. Defaults to dumping to stdout in non-HTML format.
    */
   static void DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml = false);
 
+  /**
+   * Returns the most recently allocated geometry item for the given display
+   * item.
+   *
+   * XXX(seth): The current implementation must iterate through all display
+   * items allocated for this display item's frame. This may lead to O(n^2)
+   * behavior in some situations.
+   */
+  static nsDisplayItemGeometry* GetMostRecentGeometry(nsDisplayItem* aItem);
+
+
   /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
   /* These are only in the public section because they need
    * to be called by file-scope helper functions in FrameLayerBuilder.cpp.
    */
 
   /**
    * Record aItem as a display item that is rendered by aLayer.
    *
@@ -398,16 +409,17 @@ public:
    * Retained data for a display item.
    */
   class DisplayItemData MOZ_FINAL {
   public:
     friend class FrameLayerBuilder;
 
     uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
     Layer* GetLayer() { return mLayer; }
+    nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); }
     void Invalidate() { mIsInvalid = true; }
 
   private:
     DisplayItemData(LayerManagerData* aParent,
                     uint32_t aKey,
                     nsIFrame* aFrame = nullptr);
     DisplayItemData(DisplayItemData &toCopy);
 
--- a/layout/base/nsDisplayListInvalidation.h
+++ b/layout/base/nsDisplayListInvalidation.h
@@ -2,16 +2,18 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #ifndef NSDISPLAYLISTINVALIDATION_H_
 #define NSDISPLAYLISTINVALIDATION_H_
 
 #include "mozilla/Attributes.h"
+#include "FrameLayerBuilder.h"
+#include "imgIContainer.h"
 #include "nsRect.h"
 #include "nsColor.h"
 #include "gfxRect.h"
 
 class nsDisplayItem;
 class nsDisplayListBuilder;
 class nsDisplayBackgroundImage;
 class nsDisplayThemedBackground;
@@ -66,16 +68,73 @@ class nsDisplayItemGenericGeometry : pub
 public:
   nsDisplayItemGenericGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
 
   virtual void MoveBy(const nsPoint& aOffset) MOZ_OVERRIDE;
 
   nsRect mBorderRect;
 };
 
+/**
+ * nsImageGeometryMixin is a mixin for geometry items that draw images. Geometry
+ * items that include this mixin can track drawing results and use that
+ * information to inform invalidation decisions.
+ *
+ * This mixin uses CRTP; its template parameter should be the type of the class
+ * that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
+ * example.
+ */
+template <typename T>
+class nsImageGeometryMixin
+{
+public:
+  explicit nsImageGeometryMixin(nsDisplayItem* aItem)
+    : mLastDrawResult(mozilla::image::DrawResult::NOT_READY)
+  {
+    auto lastGeometry =
+      static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
+    if (lastGeometry) {
+      mLastDrawResult = lastGeometry->LastDrawResult();
+    }
+  }
+
+  static void UpdateDrawResult(nsDisplayItem* aItem,
+                               mozilla::image::DrawResult aResult)
+  {
+    auto lastGeometry =
+      static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
+    if (lastGeometry) {
+      lastGeometry->mLastDrawResult = aResult;
+    }
+  }
+
+  mozilla::image::DrawResult LastDrawResult() const { return mLastDrawResult; }
+
+private:
+  mozilla::image::DrawResult mLastDrawResult;
+};
+
+/**
+ * nsDisplayItemGenericImageGeometry is a generic geometry item class that
+ * includes nsImageGeometryMixin.
+ *
+ * This should be sufficient for most display items that draw images.
+ */
+class nsDisplayItemGenericImageGeometry
+  : public nsDisplayItemGenericGeometry
+  , public nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>
+{
+public:
+  nsDisplayItemGenericImageGeometry(nsDisplayItem* aItem,
+                                    nsDisplayListBuilder* aBuilder)
+    : nsDisplayItemGenericGeometry(aItem, aBuilder)
+    , nsImageGeometryMixin(aItem)
+  { }
+};
+
 class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry
 {
 public:
   nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
 
   bool mHasRoundedCorners;
 };