Enable automatic rescaling in bench_pictures

bench_pictures with "--device gpu" is failing because we're trying to allocate
too much GPU memory.  Move the recently-added scaling code into picture_utils
and share it between render_pictures and bench_pictures.
Review URL: https://codereview.appspot.com/6495125

git-svn-id: http://skia.googlecode.com/svn/trunk@5543 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp
index 8edbb94..93b1cf9 100644
--- a/tools/bench_pictures_main.cpp
+++ b/tools/bench_pictures_main.cpp
@@ -109,17 +109,21 @@
         return;
     }
 
-    SkPicture picture(&inputStream);
+    SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream));
+    SkAutoTUnref<SkPicture> aur(picture);
 
     SkString filename;
     sk_tools::get_basename(&filename, inputPath);
 
     SkString result;
-    result.printf("running bench [%i %i] %s ", picture.width(), picture.height(),
-                  filename.c_str());
+    result.printf("running bench [%i %i] %s ", picture->width(),
+                  picture->height(), filename.c_str());
     gLogger.logProgress(result);
 
-    benchmark.run(&picture);
+    // rescale to avoid memory issues allocating a very large offscreen
+    sk_tools::resize_if_needed(&aur);
+
+    benchmark.run(aur);
 }
 
 static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp
index b9bedbb..2dd1f4e 100644
--- a/tools/picture_utils.cpp
+++ b/tools/picture_utils.cpp
@@ -6,9 +6,11 @@
  */
 
 #include "picture_utils.h"
+#include "SkCanvas.h"
 #include "SkColorPriv.h"
 #include "SkBitmap.h"
 #include "SkPicture.h"
+#include "SkRefCnt.h"
 #include "SkString.h"
 #include "SkStream.h"
 
@@ -90,4 +92,47 @@
         bitmap->allocPixels();
         bitmap->eraseColor(0);
     }
+
+    bool area_too_big(int w, int h, SkISize* newSize) {
+        // just a guess, based on what seems to fail on smaller android devices
+        static const int64_t kMaxAreaForMemory = 16 * 1024 * 1024;
+
+        if ((int64_t)w * h > kMaxAreaForMemory) {
+            do {
+                w >>= 1;
+                h >>= 1;
+            } while ((int64_t)w * h > kMaxAreaForMemory);
+            if (0 == w) {
+                w = 1;
+            }
+            if (0 == h) {
+                h = 1;
+            }
+            newSize->set(w, h);
+            return true;
+        }
+        return false;
+    }
+
+    void resize_if_needed(SkAutoTUnref<SkPicture>* aur) {
+        SkISize newSize;
+        SkPicture* picture = aur->get();
+        if (area_too_big(picture->width(), picture->height(), &newSize)) {
+            SkPicture* pic = SkNEW(SkPicture);
+            picture->ref();
+            aur->reset(pic);
+
+            SkCanvas* canvas = pic->beginRecording(newSize.width(),
+                                                   newSize.height());
+            SkScalar scale = SkIntToScalar(newSize.width()) / picture->width();
+            canvas->scale(scale, scale);
+            canvas->drawPicture(*picture);
+            pic->endRecording();
+
+            SkDebugf(
+                "... rescaling to [%d %d] to avoid overly large allocations\n",
+                newSize.width(), newSize.height());
+            picture->unref();
+        }
+    }
 }
diff --git a/tools/picture_utils.h b/tools/picture_utils.h
index cca9431..db996ca 100644
--- a/tools/picture_utils.h
+++ b/tools/picture_utils.h
@@ -7,12 +7,15 @@
 
 #ifndef picture_utils_DEFINED
 #define picture_utils_DEFINED
-#include "SkTypes.h"
 
+#include "SkTypes.h"
+#include "SkSize.h"
+
+template <typename T> class SkAutoTUnref;
 class SkBitmap;
 class SkFILEStream;
-class SkString;
 class SkPicture;
+class SkString;
 
 namespace sk_tools {
     // since PNG insists on unpremultiplying our alpha, we take no precision
@@ -41,6 +44,14 @@
     // Specifically, it configures the bitmap, allocates pixels and then
     // erases the pixels to transparent black.
     void setup_bitmap(SkBitmap* bitmap, int width, int height);
+
+    // Determines whether the given dimensions are too large and suggests a new
+    // size.
+    bool area_too_big(int w, int h, SkISize* newSize);
+
+    // Determines whether the given SkPicture is too large and, if so, replaces
+    // it with a new, scaled-down SkPicture.
+    void resize_if_needed(SkAutoTUnref<SkPicture>* aur);
 }
 
 #endif  // picture_utils_DEFINED
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index 87d5d4b..7d54516 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -89,27 +89,6 @@
     }
 }
 
-static bool area_too_big(int w, int h, SkISize* newSize) {
-    // just a guess, based on what seems to fail on smaller android devices
-    static const int64_t kMaxAreaForMemory = 16 * 1024 * 1024;
-
-    if ((int64_t)w * h > kMaxAreaForMemory) {
-        do {
-            w >>= 1;
-            h >>= 1;
-        } while ((int64_t)w * h > kMaxAreaForMemory);
-        if (0 == w) {
-            w = 1;
-        }
-        if (0 == h) {
-            h = 1;
-        }
-        newSize->set(w, h);
-        return true;
-    }
-    return false;
-}
-
 static void render_picture(const SkString& inputPath, const SkString& outputDir,
                            sk_tools::PictureRenderer& renderer) {
     SkString inputFilename;
@@ -122,32 +101,16 @@
         return;
     }
 
-    SkPicture picture(&inputStream);
+    SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream));
+    SkAutoTUnref<SkPicture> aur(picture);
 
-    SkDebugf("drawing... [%i %i] %s\n", picture.width(), picture.height(),
+    SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
              inputPath.c_str());
 
+    // rescale to avoid memory issues allocating a very large offscreen
+    sk_tools::resize_if_needed(&aur);
 
-    // rescale to avoid memory issues allcoating a very large offscreen
-    SkPicture* pic = &picture;
-    SkISize newSize;
-    SkAutoUnref aur(NULL);
-
-    if (area_too_big(picture.width(), picture.height(), &newSize)) {
-        pic = new SkPicture;
-        aur.reset(pic);
-
-        SkCanvas* canvas = pic->beginRecording(newSize.width(), newSize.height());
-        SkScalar scale = SkIntToScalar(newSize.width()) / picture.width();
-        canvas->scale(scale, scale);
-        canvas->drawPicture(picture);
-        pic->endRecording();
-
-        SkDebugf("... rescaling to [%d %d] to avoid overly large allocations\n",
-                 newSize.width(), newSize.height());
-    }
-
-    renderer.init(pic);
+    renderer.init(aur);
 
     renderer.render(true);