Bug 1258481 - Add a RegionBuilder for accumulating rects. r=jrmuizel
authorBenoit Girard <b56girard@gmail.com>
Wed, 23 Mar 2016 11:54:39 -0400
changeset 290104 89d767660c10c58d52066640ef0050f39bc79832
parent 290103 f379f47e538f513291318b14ab6f21d4142c3a55
child 290105 fea97c450559ae96f6736443dfcc1e83ebad6e8c
push id30114
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:15:54 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1258481
milestone48.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 1258481 - Add a RegionBuilder for accumulating rects. r=jrmuizel MozReview-Commit-ID: 6tI81iqj44V
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) {}
+  explicit 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();
+});
+