Bug 1258481 - Add a RegionBuilder for accumulating rects. r=jrmuizel
☠☠ backed out by 52195522dbac ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Mon, 21 Mar 2016 16:22:37 -0400
changeset 290129 5e60a574fcec34b325090b82917e98c5bc5b623b
parent 290128 4b36423739fa9ccbd2e04b6e934109bc05d8db30
child 290130 8e7a8791854f07b4134f88cf97079f353d9b2fb5
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1258481
milestone48.0a1
Bug 1258481 - Add a RegionBuilder for accumulating rects. r=jrmuizel MozReview-Commit-ID: 6AO9q6Ru833
gfx/src/RegionBuilder.h
gfx/src/moz.build
gfx/src/nsRegion.h
gfx/tests/gtest/TestRegion.cpp
new file mode 100644
--- /dev/null
+++ b/gfx/src/RegionBuilder.h
@@ -0,0 +1,32 @@
+/* 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 RegionBuilder_h__
+#define RegionBuilder_h__
+
+#include <nsTArray.h>
+
+template <typename RegionType>
+class RegionBuilder
+{
+public:
+  typedef typename RegionType::RectType RectType;
+
+  RegionBuilder()
+  {}
+
+  void Or(const RectType& aRect) {
+    pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
+    mRects.AppendElement(box);
+  }
+
+  RegionType ToRegion() const {
+    return RegionType(mRects);
+  }
+
+private:
+  nsTArray<pixman_box32_t> mRects;
+};
+
+#endif // RegionBuilder_h__
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -32,16 +32,17 @@ EXPORTS += [
     'nsPoint.h',
     'nsRect.h',
     'nsRegion.h',
     'nsRegionFwd.h',
     'nsRenderingContext.h',
     'nsSize.h',
     'nsThemeConstants.h',
     'nsTransform2D.h',
+    'RegionBuilder.h',
 ]
 
 EXPORTS.mozilla += [
     'AppUnits.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS.mozilla += ['X11Util.h']
--- a/gfx/src/nsRegion.h
+++ b/gfx/src/nsRegion.h
@@ -14,16 +14,17 @@
 #include <ostream>                      // for std::ostream
 #include "nsCoord.h"                    // for nscoord
 #include "nsError.h"                    // for nsresult
 #include "nsPoint.h"                    // for nsIntPoint, nsPoint
 #include "nsRect.h"                     // for mozilla::gfx::IntRect, nsRect
 #include "nsMargin.h"                   // for nsIntMargin
 #include "nsRegionFwd.h"                // for nsIntRegion
 #include "nsStringGlue.h"               // for nsCString
+#include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "xpcom-config.h"               // for CPP_THROW_NEW
 #include "mozilla/Move.h"               // for mozilla::Move
 #include "mozilla/gfx/MatrixFwd.h"      // for mozilla::gfx::Matrix4x4
 
 #include "pixman.h"
 
 /* For information on the internal representation look at pixman-region.c
  *
@@ -44,22 +45,30 @@ enum class VisitSide {
 	BOTTOM,
 	LEFT,
 	RIGHT
 };
 
 class nsRegion
 {
 public:
+  typedef nsRect RectType;
+  typedef nsPoint PointType;
+  typedef nsMargin MarginType;
+
   nsRegion () { pixman_region32_init(&mImpl); }
   MOZ_IMPLICIT nsRegion (const nsRect& aRect) { pixman_region32_init_rect(&mImpl,
                                                                           aRect.x,
                                                                           aRect.y,
                                                                           aRect.width,
                                                                           aRect.height); }
+  explicit nsRegion (const nsTArray<pixman_box32_t>& aRects)
+  {
+    pixman_region32_init_rects(&mImpl, aRects.Elements(), aRects.Length());
+  }
   nsRegion (const nsRegion& aRegion) { pixman_region32_init(&mImpl); pixman_region32_copy(&mImpl,aRegion.Impl()); }
   nsRegion (nsRegion&& aRegion) { mImpl = aRegion.mImpl; pixman_region32_init(&aRegion.mImpl); }
   nsRegion& operator = (nsRegion&& aRegion) {
       pixman_region32_fini(&mImpl);
       mImpl = aRegion.mImpl;
       pixman_region32_init(&aRegion.mImpl);
       return *this;
   }
@@ -466,16 +475,17 @@ class BaseIntRegion
 
 public:
   typedef Rect RectType;
   typedef Point PointType;
   typedef Margin MarginType;
 
   BaseIntRegion () {}
   MOZ_IMPLICIT BaseIntRegion (const Rect& aRect) : mImpl (ToRect(aRect)) {}
+  explicit BaseIntRegion (const nsTArray<pixman_box32_t>& aRects) : mImpl (aRects) {}
   BaseIntRegion (const BaseIntRegion& aRegion) : mImpl (aRegion.mImpl) {}
   BaseIntRegion (BaseIntRegion&& aRegion) : mImpl (mozilla::Move(aRegion.mImpl)) {}
   Derived& operator = (const Rect& aRect) { mImpl = ToRect (aRect); return This(); }
   Derived& operator = (const Derived& aRegion) { mImpl = aRegion.mImpl; return This(); }
   Derived& operator = (Derived&& aRegion) { mImpl = mozilla::Move(aRegion.mImpl); return This(); }
 
   bool operator==(const Derived& aRgn) const
   {
@@ -809,20 +819,25 @@ class IntRegionTyped :
 
   // Make other specializations of IntRegionTyped friends.
   template <typename OtherUnits>
   friend class IntRegionTyped;
 
   static_assert(IsPixel<units>::value, "'units' must be a coordinate system tag");
 
 public:
+  typedef IntRectTyped<units> RectType;
+  typedef IntPointTyped<units> PointType;
+  typedef IntMarginTyped<units> MarginType;
+
   // Forward constructors.
   IntRegionTyped() {}
   MOZ_IMPLICIT IntRegionTyped(const IntRectTyped<units>& aRect) : Super(aRect) {}
   IntRegionTyped(const IntRegionTyped& aRegion) : Super(aRegion) {}
+  IntRegionTyped(const nsTArray<pixman_box32_t>& aRects) : Super(aRects) {}
   IntRegionTyped(IntRegionTyped&& aRegion) : Super(mozilla::Move(aRegion)) {}
 
   // Assignment operators need to be forwarded as well, otherwise the compiler
   // will declare deleted ones.
   IntRegionTyped& operator=(const IntRegionTyped& aRegion)
   {
     return Super::operator=(aRegion);
   }
--- a/gfx/tests/gtest/TestRegion.cpp
+++ b/gfx/tests/gtest/TestRegion.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <algorithm>
 
 #include "gtest/gtest.h"
 #include "gtest/MozGTestBench.h"
 #include "nsRect.h"
 #include "nsRegion.h"
+#include "RegionBuilder.h"
 
 using namespace std;
 
 class TestLargestRegion {
 public:
   static void TestSingleRect(nsRect r) {
     nsRegion region(r);
     EXPECT_TRUE(region.GetLargestRectangle().IsEqualInterior(r));
@@ -578,8 +579,28 @@ MOZ_GTEST_BENCH(GfxBench, RegionAnd, []{
   nsRegion r(nsRect(0, 0, size, size));
   for (int i = 0; i < size; i++) {
     nsRegion rMissingPixel(nsRect(0, 0, size, size));
     rMissingPixel = rMissingPixel.Sub(rMissingPixel, nsRect(i, i, 1, 1));
     r = r.And(r, rMissingPixel);
   }
 });
 
+void TestExec() {
+  const int size = 5000;
+
+  RegionBuilder<nsRegion> r;
+  for (int i = 0; i < size; i++) {
+    r.Or(nsRect(i, i, i + 10, i + 10));
+  }
+  r.ToRegion();
+
+  RegionBuilder<nsIntRegion> rInt;
+  for (int i = 0; i < size; i++) {
+    rInt.Or(nsIntRect(i, i, i + 10, i + 10));
+  }
+  rInt.ToRegion();
+}
+
+MOZ_GTEST_BENCH(GfxBench, RegionBuilderOr, []{
+  TestExec();
+});
+