From e21795e277aa7942a152c4f9921b7d4bd9076406 Mon Sep 17 00:00:00 2001 From: "borenet@google.com" Date: Fri, 14 Sep 2012 14:34:28 +0000 Subject: [PATCH] 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 --- gyp/tools.gyp | 1 + tools/bench_pictures_main.cpp | 12 ++++++--- tools/picture_utils.cpp | 45 +++++++++++++++++++++++++++++++ tools/picture_utils.h | 15 +++++++++-- tools/render_pictures_main.cpp | 49 +++++----------------------------- 5 files changed, 73 insertions(+), 49 deletions(-) diff --git a/gyp/tools.gyp b/gyp/tools.gyp index 28456a26f..371ecd2ad 100644 --- a/gyp/tools.gyp +++ b/gyp/tools.gyp @@ -143,6 +143,7 @@ 'type': 'static_library', 'sources': [ '../tools/picture_utils.cpp', + '../tools/picture_utils.h', ], 'dependencies': [ 'core.gyp:core', diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp index 8edbb9423..93b1cf964 100644 --- a/tools/bench_pictures_main.cpp +++ b/tools/bench_pictures_main.cpp @@ -109,17 +109,21 @@ static void run_single_benchmark(const SkString& inputPath, return; } - SkPicture picture(&inputStream); + SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream)); + SkAutoTUnref 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* inputs, diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp index b9bedbb50..2dd1f4ec4 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 @@ namespace sk_tools { 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* 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 cca943123..db996caf5 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 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 @@ namespace sk_tools { // 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* aur); } #endif // picture_utils_DEFINED diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp index 87d5d4b79..7d54516d8 100644 --- a/tools/render_pictures_main.cpp +++ b/tools/render_pictures_main.cpp @@ -89,27 +89,6 @@ static void write_output(const SkString& outputDir, const SkString& inputFilenam } } -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 @@ static void render_picture(const SkString& inputPath, const SkString& outputDir, return; } - SkPicture picture(&inputStream); + SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream)); + SkAutoTUnref 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);