Adding option to SkTileGrid for specifying border pixels.

The purpose of this patch is to make it possible for the chromium compositor to
generate a TileGrid structure that is better suited for scaled playback.
Review URL: https://codereview.appspot.com/7300072

git-svn-id: http://skia.googlecode.com/svn/trunk@7680 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkTileGridPicture.h b/include/core/SkTileGridPicture.h
index 6263ecb..77189bb 100644
--- a/include/core/SkTileGridPicture.h
+++ b/include/core/SkTileGridPicture.h
@@ -20,10 +20,21 @@
  */
 class SK_API SkTileGridPicture : public SkPicture {
 public:
-    SkTileGridPicture(int tileWidth, int tileHeight, int width, int height);
+    /**
+     * Constructor
+     * @param tileWidth horizontal stride between consecutive tiles
+     * @param tileHeight vertical stride between consecutive tiles
+     * @param width recording canvas width in device pixels
+     * @param height recording canvas height in device pixels
+     * @param borderPixels pixels of overlap between adjacent tiles. Set this
+     *  value to match the border overlap that is applied to tiles by user
+     *  code. Properly setting this value will help improve performance
+     *  when performing tile-aligned playbacks.
+     */
+    SkTileGridPicture(int tileWidth, int tileHeight, int width, int height, int borderPixels = 0);
     virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE;
 private:
-    int fTileWidth, fTileHeight, fXTileCount, fYTileCount;
+    int fTileWidth, fTileHeight, fXTileCount, fYTileCount, fBorderPixels;
 };
 
 #endif
diff --git a/src/core/SkTileGrid.cpp b/src/core/SkTileGrid.cpp
index 2b885c9..51c40cc 100644
--- a/src/core/SkTileGrid.cpp
+++ b/src/core/SkTileGrid.cpp
@@ -8,12 +8,16 @@
 
 #include "SkTileGrid.h"
 
-SkTileGrid::SkTileGrid(int tileWidth, int tileHeight, int xTileCount, int yTileCount, SkTileGridNextDatumFunctionPtr nextDatumFunction)
+SkTileGrid::SkTileGrid(int tileWidth, int tileHeight, int xTileCount, int yTileCount, 
+    int borderPixels, SkTileGridNextDatumFunctionPtr nextDatumFunction)
 {
     fTileWidth = tileWidth;
     fTileHeight = tileHeight;
     fXTileCount = xTileCount;
     fYTileCount = yTileCount;
+    // Border padding is offset by 1 as a provision for AA and
+    // to cancel-out the outset applied by getClipDeviceBounds.
+    fBorderPixels = borderPixels + 1; 
     fTileCount = fXTileCount * fYTileCount;
     fInsertionCount = 0;
     fGridBounds = SkIRect::MakeXYWH(0, 0, fTileWidth * fXTileCount, fTileHeight * fYTileCount);
@@ -32,7 +36,7 @@
 void SkTileGrid::insert(void* data, const SkIRect& bounds, bool) {
     SkASSERT(!bounds.isEmpty());
     SkIRect dilatedBounds = bounds;
-    dilatedBounds.outset(1,1); // Consideration for filtering and AA
+    dilatedBounds.outset(fBorderPixels, fBorderPixels);
 
     if (!SkIRect::Intersects(dilatedBounds, fGridBounds)) {
         return;
@@ -52,11 +56,10 @@
 }
 
 void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) {
-    // The +1/-1 is to compensate for the outset in applied SkCanvas::getClipBounds
-    int tileStartX = (query.left() + 1) / fTileWidth;
-    int tileEndX = (query.right() + fTileWidth - 1) / fTileWidth;
-    int tileStartY = (query.top() + 1) / fTileHeight;
-    int tileEndY = (query.bottom() + fTileHeight - 1) / fTileHeight;
+    int tileStartX = (query.left() + fBorderPixels) / fTileWidth;
+    int tileEndX = (query.right() + fTileWidth - fBorderPixels) / fTileWidth;
+    int tileStartY = (query.top() + fBorderPixels) / fTileHeight;
+    int tileEndY = (query.bottom() + fTileHeight - fBorderPixels) / fTileHeight;
     if (tileStartX >= fXTileCount || tileStartY >= fYTileCount || tileEndX <= 0 || tileEndY <= 0) {
         return; // query does not intersect the grid
     }
diff --git a/src/core/SkTileGrid.h b/src/core/SkTileGrid.h
index 8ae3f2c..3f69f07 100644
--- a/src/core/SkTileGrid.h
+++ b/src/core/SkTileGrid.h
@@ -26,7 +26,7 @@
 public:
     typedef void* (*SkTileGridNextDatumFunctionPtr)(SkTDArray<void*>** tileData, SkTDArray<int>& tileIndices);
 
-    SkTileGrid(int tileWidth, int tileHeight, int xTileCount, int yTileCount,
+    SkTileGrid(int tileWidth, int tileHeight, int xTileCount, int yTileCount, int borderPixels,
         SkTileGridNextDatumFunctionPtr nextDatumFunction);
 
     virtual ~SkTileGrid();
@@ -61,7 +61,7 @@
 private:
     SkTDArray<void*>& tile(int x, int y);
 
-    int fTileWidth, fTileHeight, fXTileCount, fYTileCount, fTileCount;
+    int fTileWidth, fTileHeight, fXTileCount, fYTileCount, fTileCount, fBorderPixels;
     SkTDArray<void*>* fTileData;
     int fInsertionCount;
     SkIRect fGridBounds;
diff --git a/src/core/SkTileGridPicture.cpp b/src/core/SkTileGridPicture.cpp
index 212e3b6..8a39d49 100644
--- a/src/core/SkTileGridPicture.cpp
+++ b/src/core/SkTileGridPicture.cpp
@@ -11,14 +11,17 @@
 #include "SkTileGrid.h"
 
 
-SkTileGridPicture::SkTileGridPicture(int tileWidth, int tileHeight, int width, int height) {
+SkTileGridPicture::SkTileGridPicture(int tileWidth, int tileHeight, int width, int height,
+                                     int borderPixels) {
+    SkASSERT(borderPixels >= 0);
     fTileWidth = tileWidth;
     fTileHeight = tileHeight;
     fXTileCount = (width + tileWidth - 1) / tileWidth;
     fYTileCount = (height + tileHeight - 1) / tileHeight;
+    fBorderPixels = borderPixels;
 }
 
 SkBBoxHierarchy* SkTileGridPicture::createBBoxHierarchy() const {
     return SkNEW_ARGS(SkTileGrid, (fTileWidth, fTileHeight, fXTileCount, fYTileCount,
-        SkTileGridNextDatum<SkPictureStateTree::Draw>));
+        fBorderPixels, SkTileGridNextDatum<SkPictureStateTree::Draw>));
 }
diff --git a/tests/TileGridTest.cpp b/tests/TileGridTest.cpp
index 1946b9f..afde41d 100644
--- a/tests/TileGridTest.cpp
+++ b/tests/TileGridTest.cpp
@@ -39,8 +39,9 @@
 
 class TileGridTest {
 public:
-    static void verifyTileHits(skiatest::Reporter* reporter, SkIRect rect, uint32_t tileMask) {
-        SkTileGrid grid(10, 10, 2, 2, NULL);
+    static void verifyTileHits(skiatest::Reporter* reporter, SkIRect rect, uint32_t tileMask, 
+                               int borderPixels = 0) {
+        SkTileGrid grid(10, 10, 2, 2, borderPixels, NULL);
         grid.insert(NULL, rect, false);
         REPORTER_ASSERT(reporter, grid.tile(0,0).count() ==
             ((tileMask & kTopLeft_Tile)? 1 : 0));
@@ -119,6 +120,12 @@
         verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1),  kAll_Tile);
         verifyTileHits(reporter, SkIRect::MakeXYWH(11, 11, 1, 1),  kBottomRight_Tile);
 
+        // BorderPixels
+        verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 7, 7),  kTopLeft_Tile, 1);
+        verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 8, 8),  kAll_Tile, 1);
+        verifyTileHits(reporter, SkIRect::MakeXYWH(11, 11, 1, 1),  kAll_Tile, 1);
+        verifyTileHits(reporter, SkIRect::MakeXYWH(12, 12, 1, 1),  kBottomRight_Tile, 1);
+
         // BBoxes that overlap tiles
         verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 1),  kTopLeft_Tile | kTopRight_Tile);
         verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 1, 10),  kTopLeft_Tile |