Implemented power of two tiling.
Review URL: https://codereview.appspot.com/6485056
git-svn-id: http://skia.googlecode.com/svn/trunk@5274 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index ab7f7b9..b162abc 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -175,7 +175,11 @@
fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
}
- this->setupTiles();
+ if (fTileMinPowerOf2Width > 0) {
+ this->setupPowerOf2Tiles();
+ } else {
+ this->setupTiles();
+ }
}
void TiledPictureRenderer::render() {
@@ -205,8 +209,8 @@
tile->clipRect(clip);
}
-void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
- SkCanvas* tile = this->setupCanvas(fTileWidth, fTileHeight);
+void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start, int width, int height) {
+ SkCanvas* tile = this->setupCanvas(width, height);
tile->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
this->clipTile(tile);
@@ -219,7 +223,43 @@
tile_y_start += fTileHeight) {
for (int tile_x_start = 0; tile_x_start < fPicture->width();
tile_x_start += fTileWidth) {
- this->addTile(tile_x_start, tile_y_start);
+ this->addTile(tile_x_start, tile_y_start, fTileWidth, fTileHeight);
+ }
+ }
+}
+
+// The goal of the powers of two tiles is to minimize the amount of wasted tile
+// space in the width-wise direction and then minimize the number of tiles. The
+// constraints are that every tile must have a pixel width that is a power of
+// two and also be of some minimal width (that is also a power of two).
+//
+// This is sovled by first taking our picture size and rounding it up to the
+// multiple of the minimal width. The binary representation of this rounded
+// value gives us the tiles we need: a bit of value one means we need a tile of
+// that size.
+void TiledPictureRenderer::setupPowerOf2Tiles() {
+ int rounded_value = fPicture->width();
+ if (fPicture->width() % fTileMinPowerOf2Width != 0) {
+ rounded_value = fPicture->width() - (fPicture->width() % fTileMinPowerOf2Width)
+ + fTileMinPowerOf2Width;
+ }
+
+ int num_bits = SkScalarCeilToInt(SkScalarLog2(fPicture->width()));
+ int largest_possible_tile_size = 1 << num_bits;
+
+ // The tile height is constant for a particular picture.
+ for (int tile_y_start = 0; tile_y_start < fPicture->height(); tile_y_start += fTileHeight) {
+ int tile_x_start = 0;
+ int current_width = largest_possible_tile_size;
+
+ while (current_width >= fTileMinPowerOf2Width) {
+ // It is very important this is a bitwise AND.
+ if (current_width & rounded_value) {
+ this->addTile(tile_x_start, tile_y_start, current_width, fTileHeight);
+ tile_x_start += current_width;
+ }
+
+ current_width >>= 1;
}
}
}