Bug 946475 - Avoid using AutoSaveRestoreClippedOut for ClearRect when the cumulative clip can be represented as a single axis aligned rectangle. r=Bas, a=lsblakk
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 12 Dec 2013 10:11:37 +1300
changeset 174370 320a46ff06741bde536d392fbd12cfb2027a4753
parent 174369 cc5c82e3f1093d466ebf498e190c9589a296deb6
child 174371 2217681c1b685132593b3418d6d2208abc9249e1
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas, lsblakk
bugs946475
milestone28.0a2
Bug 946475 - Avoid using AutoSaveRestoreClippedOut for ClearRect when the cumulative clip can be represented as a single axis aligned rectangle. r=Bas, a=lsblakk
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -761,24 +761,44 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
 }
 
 void
 DrawTargetD2D::ClearRect(const Rect &aRect)
 {
   MarkChanged();
   PushClipRect(aRect);
 
-  FlushTransformToRT();
   PopAllClips();
 
   AutoSaveRestoreClippedOut restoreClippedOut(this);
 
-  restoreClippedOut.Save();
+  D2D1_RECT_F clipRect;
+  bool isPixelAligned;
+  bool pushedClip = false;
+  if (mTransform.IsRectilinear() &&
+      GetDeviceSpaceClipRect(clipRect, isPixelAligned)) {
+    if (mTransformDirty ||
+        !mTransform.IsIdentity()) {
+      mRT->SetTransform(D2D1::IdentityMatrix());
+      mTransformDirty = true;
+    }
+
+    mRT->PushAxisAlignedClip(clipRect, isPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
+    pushedClip = true;
+  } else {
+    FlushTransformToRT();
+    restoreClippedOut.Save();
+  }
 
   mRT->Clear(D2D1::ColorF(0, 0.0f));
+
+  if (pushedClip) {
+    mRT->PopAxisAlignedClip();
+  }
+
   PopClip();
   return;
 }
 
 void
 DrawTargetD2D::CopySurface(SourceSurface *aSurface,
                            const IntRect &aSourceRect,
                            const IntPoint &aDestination)
@@ -1758,19 +1778,50 @@ DrawTargetD2D::FinalizeRTForOperation(Co
 static D2D1_RECT_F
 IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2)
 {
   D2D1_RECT_F result;
   result.left = max(aRect1.left, aRect2.left);
   result.top = max(aRect1.top, aRect2.top);
   result.right = min(aRect1.right, aRect2.right);
   result.bottom = min(aRect1.bottom, aRect2.bottom);
+
+  result.right = max(result.right, result.left);
+  result.bottom = max(result.bottom, result.top);
+
   return result;
 }
 
+bool
+DrawTargetD2D::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned)
+{
+  if (!mPushedClips.size()) {
+    return false;
+  }
+
+  std::vector<DrawTargetD2D::PushedClip>::iterator iter = mPushedClips.begin();
+  if (iter->mPath) {
+    return false;
+  }
+  aClipRect = iter->mBounds;
+  aIsPixelAligned = iter->mIsPixelAligned;
+
+  iter++;
+  for (;iter != mPushedClips.end(); iter++) {
+    if (iter->mPath) {
+      return false;
+    }
+    aClipRect = IntersectRect(aClipRect, iter->mBounds);
+    if (!iter->mIsPixelAligned) {
+      aIsPixelAligned = false;
+    }
+  }
+  return true;
+}
+
 TemporaryRef<ID2D1Geometry>
 DrawTargetD2D::GetClippedGeometry(IntRect *aClipBounds)
 {
   if (mCurrentClippedGeometry) {
     *aClipBounds = mCurrentClipBounds;
     return mCurrentClippedGeometry;
   }
 
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -200,16 +200,18 @@ private:
   TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
 
   // This returns the clipped geometry, in addition it returns aClipBounds which
   // represents the intersection of all pixel-aligned rectangular clips that
   // are currently set. The returned clipped geometry must be clipped by these
   // bounds to correctly reflect the total clip. This is in device space.
   TemporaryRef<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
 
+  bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
+
   TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
 
   TemporaryRef<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops);
   TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
 
   void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
   void SetupStateForRendering();