Bug 1059033 - Part 3: Avoid save/restoring for tiles that are entirely clipped out. r=Bas
☠☠ backed out by 6cddb4cf40e3 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 01 Sep 2014 15:22:49 +1200
changeset 224473 301fdfea8fbfe14e1179b96a47b2c9a69f3a2bae
parent 224472 1ef5a3a9bb0641803493ec57d7ebbb2b3c91a108
child 224474 e59430ea4256cd00c59a73b8a7992b62b9128113
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1059033
milestone34.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 1059033 - Part 3: Avoid save/restoring for tiles that are entirely clipped out. r=Bas
gfx/2d/DrawTargetTiled.cpp
gfx/2d/DrawTargetTiled.h
--- a/gfx/2d/DrawTargetTiled.cpp
+++ b/gfx/2d/DrawTargetTiled.cpp
@@ -43,17 +43,17 @@ DrawTargetTiled::Init(const TileSet& aTi
   }
   mFormat = mTiles[0].mDrawTarget->GetFormat();
   return true;
 }
 
 class SnapshotTiled : public SourceSurface
 {
 public:
-  SnapshotTiled(const vector<Tile>& aTiles, const IntRect& aRect)
+  SnapshotTiled(const vector<TileInternal>& aTiles, const IntRect& aRect)
     : mRect(aRect)
   {
     for (size_t i = 0; i < aTiles.size(); i++) {
       mSnapshots.push_back(aTiles[i].mDrawTarget->Snapshot());
       mOrigins.push_back(aTiles[i].mTileOrigin);
     }
   }
 
@@ -92,78 +92,134 @@ private:
 };
 
 TemporaryRef<SourceSurface>
 DrawTargetTiled::Snapshot()
 {
   return new SnapshotTiled(mTiles, mRect);
 }
 
+// Skip the mClippedOut check since this is only used for Flush() which
+// should happen even if we're clipped.
 #define TILED_COMMAND(command) \
   void \
   DrawTargetTiled::command() \
   { \
     for (size_t i = 0; i < mTiles.size(); i++) { \
-    \
-    \
-    mTiles[i].mDrawTarget->command(); \
+      mTiles[i].mDrawTarget->command(); \
     } \
   }
 #define TILED_COMMAND1(command, type1) \
   void \
   DrawTargetTiled::command(type1 arg1) \
   { \
     for (size_t i = 0; i < mTiles.size(); i++) { \
-    \
-    \
-    mTiles[i].mDrawTarget->command(arg1); \
+      if (!mTiles[i].mClippedOut) \
+        mTiles[i].mDrawTarget->command(arg1); \
     } \
   }
 #define TILED_COMMAND3(command, type1, type2, type3) \
   void \
   DrawTargetTiled::command(type1 arg1, type2 arg2, type3 arg3) \
   { \
     for (size_t i = 0; i < mTiles.size(); i++) { \
-    \
-    \
-    mTiles[i].mDrawTarget->command(arg1, arg2, arg3); \
+      if (!mTiles[i].mClippedOut) \
+        mTiles[i].mDrawTarget->command(arg1, arg2, arg3); \
     } \
   }
 #define TILED_COMMAND4(command, type1, type2, type3, type4) \
   void \
   DrawTargetTiled::command(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
   { \
     for (size_t i = 0; i < mTiles.size(); i++) { \
-    \
-    \
-    mTiles[i].mDrawTarget->command(arg1, arg2, arg3, arg4); \
+      if (!mTiles[i].mClippedOut) \
+        mTiles[i].mDrawTarget->command(arg1, arg2, arg3, arg4); \
     } \
   }
 #define TILED_COMMAND5(command, type1, type2, type3, type4, type5) \
   void \
   DrawTargetTiled::command(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
   { \
     for (size_t i = 0; i < mTiles.size(); i++) { \
-    \
-    \
-    mTiles[i].mDrawTarget->command(arg1, arg2, arg3, arg4, arg5); \
+      if (!mTiles[i].mClippedOut) \
+        mTiles[i].mDrawTarget->command(arg1, arg2, arg3, arg4, arg5); \
     } \
   }
 
 TILED_COMMAND(Flush)
 TILED_COMMAND4(DrawFilter, FilterNode*, const Rect&, const Point&, const DrawOptions&)
 TILED_COMMAND1(ClearRect, const Rect&)
 TILED_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point, const DrawOptions&)
 TILED_COMMAND4(StrokeRect, const Rect&, const Pattern&, const StrokeOptions&, const DrawOptions&)
 TILED_COMMAND5(StrokeLine, const Point&, const Point&, const Pattern&, const StrokeOptions&, const DrawOptions&)
 TILED_COMMAND5(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&, const DrawOptions&, const GlyphRenderingOptions*)
 TILED_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
-TILED_COMMAND1(PushClip, const Path*)
-TILED_COMMAND1(PushClipRect, const Rect&)
-TILED_COMMAND(PopClip)
+
+void
+DrawTargetTiled::PushClip(const Path* aPath)
+{
+  mClippedOutTilesStack.push_back(std::vector<uint32_t>());
+  std::vector<uint32_t>& clippedTiles = mClippedOutTilesStack.back();
+
+  Rect deviceRect = aPath->GetBounds(mTransform);
+
+  for (size_t i = 0; i < mTiles.size(); i++) {
+    if (!mTiles[i].mClippedOut) {
+      if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+                                   mTiles[i].mTileOrigin.y,
+                                   mTiles[i].mDrawTarget->GetSize().width,
+                                   mTiles[i].mDrawTarget->GetSize().height))) {
+        mTiles[i].mDrawTarget->PushClip(aPath);
+      } else {
+        mTiles[i].mClippedOut = true;
+        clippedTiles.push_back(i);
+      }
+    }
+  }
+}
+
+void
+DrawTargetTiled::PushClipRect(const Rect& aRect)
+{
+  mClippedOutTilesStack.push_back(std::vector<uint32_t>());
+  std::vector<uint32_t>& clippedTiles = mClippedOutTilesStack.back();
+
+  Rect deviceRect = mTransform.TransformBounds(aRect);
+
+  for (size_t i = 0; i < mTiles.size(); i++) {
+    if (!mTiles[i].mClippedOut) {
+      if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+                                   mTiles[i].mTileOrigin.y,
+                                   mTiles[i].mDrawTarget->GetSize().width,
+                                   mTiles[i].mDrawTarget->GetSize().height))) {
+        mTiles[i].mDrawTarget->PushClipRect(aRect);
+      } else {
+        mTiles[i].mClippedOut = true;
+        clippedTiles.push_back(i);
+      }
+    }
+  }
+}
+
+void
+DrawTargetTiled::PopClip()
+{
+  for (size_t i = 0; i < mTiles.size(); i++) {
+    if (!mTiles[i].mClippedOut) {
+      mTiles[i].mDrawTarget->PopClip();
+    }
+  }
+
+  std::vector<uint32_t>& clippedTiles = mClippedOutTilesStack.back();
+  for (size_t i = 0; i < clippedTiles.size(); i++) {
+    mTiles[clippedTiles[i]].mClippedOut = false;
+  }
+
+  mClippedOutTilesStack.pop_back();
+}
 
 void
 DrawTargetTiled::CopySurface(SourceSurface *aSurface,
                              const IntRect &aSourceRect,
                              const IntPoint &aDestination)
 {
   // CopySurface ignores the transform, account for that here.
   for (size_t i = 0; i < mTiles.size(); i++) {
@@ -192,31 +248,33 @@ DrawTargetTiled::SetTransform(const Matr
   DrawTarget::SetTransform(aTransform);
 }
 
 void
 DrawTargetTiled::DrawSurface(SourceSurface* aSurface, const Rect& aDest, const Rect& aSource, const DrawSurfaceOptions& aSurfaceOptions, const DrawOptions& aDrawOptions)
 {
   Rect deviceRect = mTransform.TransformBounds(aDest);
   for (size_t i = 0; i < mTiles.size(); i++) {
-    if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+    if (!mTiles[i].mClippedOut &&
+        deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
                                    mTiles[i].mTileOrigin.y,
                                    mTiles[i].mDrawTarget->GetSize().width,
                                    mTiles[i].mDrawTarget->GetSize().height))) {
       mTiles[i].mDrawTarget->DrawSurface(aSurface, aDest, aSource, aSurfaceOptions, aDrawOptions);
     }
   }
 }
 
 void
 DrawTargetTiled::FillRect(const Rect& aRect, const Pattern& aPattern, const DrawOptions& aDrawOptions)
 {
   Rect deviceRect = mTransform.TransformBounds(aRect);
   for (size_t i = 0; i < mTiles.size(); i++) {
-    if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+    if (!mTiles[i].mClippedOut &&
+        deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
                                    mTiles[i].mTileOrigin.y,
                                    mTiles[i].mDrawTarget->GetSize().width,
                                    mTiles[i].mDrawTarget->GetSize().height))) {
       mTiles[i].mDrawTarget->FillRect(aRect, aPattern, aDrawOptions);
     }
   }
 }
 
@@ -250,31 +308,33 @@ PathExtentsToMaxStrokeExtents(const Stro
 void
 DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aDrawOptions)
 {
   // Approximate the stroke extents, since Path::GetStrokeExtents can be slow
   Rect deviceRect = PathExtentsToMaxStrokeExtents(aStrokeOptions,
                                                  aPath->GetBounds(mTransform),
                                                  mTransform);
   for (size_t i = 0; i < mTiles.size(); i++) {
-    if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+    if (!mTiles[i].mClippedOut &&
+        deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
                                    mTiles[i].mTileOrigin.y,
                                    mTiles[i].mDrawTarget->GetSize().width,
                                    mTiles[i].mDrawTarget->GetSize().height))) {
       mTiles[i].mDrawTarget->Stroke(aPath, aPattern, aStrokeOptions, aDrawOptions);
     }
   }
 }
 
 void
 DrawTargetTiled::Fill(const Path* aPath, const Pattern& aPattern, const DrawOptions& aDrawOptions)
 {
   Rect deviceRect = aPath->GetBounds(mTransform);
   for (size_t i = 0; i < mTiles.size(); i++) {
-    if (deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
+    if (!mTiles[i].mClippedOut &&
+        deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
                                    mTiles[i].mTileOrigin.y,
                                    mTiles[i].mDrawTarget->GetSize().width,
                                    mTiles[i].mDrawTarget->GetSize().height))) {
       mTiles[i].mDrawTarget->Fill(aPath, aPattern, aDrawOptions);
     }
   }
 }
 
--- a/gfx/2d/DrawTargetTiled.h
+++ b/gfx/2d/DrawTargetTiled.h
@@ -9,16 +9,30 @@
 #include "2D.h"
 #include "Filters.h"
 
 #include <vector>
 
 namespace mozilla {
 namespace gfx {
 
+struct TileInternal : public Tile {
+  TileInternal()
+    : mClippedOut(false)
+  {}
+
+  TileInternal(const Tile& aOther)
+    : Tile(aOther)
+    , mClippedOut(false)
+  {}
+
+  bool mClippedOut;
+};
+
+
 class DrawTargetTiled : public DrawTarget
 {
 public:
   DrawTargetTiled();
 
   bool Init(const TileSet& mTiles);
 
   virtual bool IsTiledDrawTarget() const { return true; }
@@ -125,16 +139,17 @@ public:
     return mTiles[0].mDrawTarget->CreateGradientStops(aStops, aNumStops, aExtendMode);
   }
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType)
   {
     return mTiles[0].mDrawTarget->CreateFilter(aType);
   }
 
 private:
-  std::vector<Tile> mTiles;
+  std::vector<TileInternal> mTiles;
+  std::vector<std::vector<uint32_t> > mClippedOutTilesStack;
   IntRect mRect;
 };
 
 }
 }
 
 #endif