From a36223764466c964ed1035bf6f152ba55168f61e Mon Sep 17 00:00:00 2001 From: "caryclark@google.com" Date: Tue, 6 Nov 2012 21:26:13 +0000 Subject: [PATCH] add draw filter option to picture_bench Option allows adding a draw filter option per type or for all types. All SkPaint flags may be filtered, plus disabling blur and setting the hint level. Review URL: https://codereview.appspot.com/6816092 git-svn-id: http://skia.googlecode.com/svn/trunk@6318 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkDrawFilter.h | 4 +- tools/PictureRenderer.cpp | 42 ++++++++- tools/PictureRenderer.h | 26 +++++- tools/bench_pictures_main.cpp | 160 +++++++++++++++++++++++++++++++++- 4 files changed, 222 insertions(+), 10 deletions(-) diff --git a/include/core/SkDrawFilter.h b/include/core/SkDrawFilter.h index 7471f9b2df..79decefb16 100644 --- a/include/core/SkDrawFilter.h +++ b/include/core/SkDrawFilter.h @@ -32,7 +32,9 @@ public: kBitmap_Type, kRect_Type, kPath_Type, - kText_Type + kText_Type, + + kTypeCount }; /** diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp index cb68f396a3..59ba680842 100644 --- a/tools/PictureRenderer.cpp +++ b/tools/PictureRenderer.cpp @@ -16,6 +16,7 @@ #endif #include "SkGraphics.h" #include "SkImageEncoder.h" +#include "SkMaskFilter.h" #include "SkMatrix.h" #include "SkPicture.h" #include "SkRTree.h" @@ -51,25 +52,58 @@ void PictureRenderer::init(SkPicture* pict) { fCanvas.reset(this->setupCanvas()); } +class FlagsDrawFilter : public SkDrawFilter { +public: + FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) : + fFlags(flags) {} + + virtual void filter(SkPaint* paint, Type t) { + paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags); + if (PictureRenderer::kBlur_DrawFilterFlag & fFlags[t]) { + SkMaskFilter* maskFilter = paint->getMaskFilter(); + SkMaskFilter::BlurInfo blurInfo; + if (maskFilter && maskFilter->asABlur(&blurInfo)) { + paint->setMaskFilter(NULL); + } + } + if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) { + paint->setHinting(SkPaint::kNo_Hinting); + } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) { + paint->setHinting(SkPaint::kSlight_Hinting); + } + } + +private: + PictureRenderer::DrawFilterFlags* fFlags; +}; + +static SkCanvas* setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) { + if (drawFilters && !canvas->getDrawFilter()) { + canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref(); + } + return canvas; +} + SkCanvas* PictureRenderer::setupCanvas() { return this->setupCanvas(fPicture->width(), fPicture->height()); } SkCanvas* PictureRenderer::setupCanvas(int width, int height) { + SkCanvas* canvas; switch(fDeviceType) { case kBitmap_DeviceType: { SkBitmap bitmap; sk_tools::setup_bitmap(&bitmap, width, height); - return SkNEW_ARGS(SkCanvas, (bitmap)); - break; + canvas = SkNEW_ARGS(SkCanvas, (bitmap)); + return setUpFilter(canvas, fDrawFilters); } #if SK_SUPPORT_GPU case kGPU_DeviceType: { SkAutoTUnref device(SkNEW_ARGS(SkGpuDevice, (fGrContext, SkBitmap::kARGB_8888_Config, width, height))); - return SkNEW_ARGS(SkCanvas, (device.get())); - break; + canvas = SkNEW_ARGS(SkCanvas, (device.get())); + return setUpFilter(canvas, fDrawFilters); } #endif default: diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index ec18428252..53aa114325 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -1,4 +1,4 @@ -/* +* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be @@ -9,6 +9,7 @@ #define PictureRenderer_DEFINED #include "SkCountdown.h" +#include "SkDrawFilter.h" #include "SkMath.h" #include "SkPicture.h" #include "SkRect.h" @@ -46,6 +47,20 @@ public: kTileGrid_BBoxHierarchyType, }; + // this uses SkPaint::Flags as a base and adds additional flags + enum DrawFilterFlags { + kNone_DrawFilterFlag = 0, + kBlur_DrawFilterFlag = 0x4000, + kHinting_DrawFilterFlag = 0x8000, // toggles between no hinting and normal hinting + kSlightHinting_DrawFilterFlag = 0x10000, // toggles between slight and normal hinting + }; + + SK_COMPILE_ASSERT(!(kBlur_DrawFilterFlag & SkPaint::kAllFlags), blur_flag_must_be_greater); + SK_COMPILE_ASSERT(!(kHinting_DrawFilterFlag & SkPaint::kAllFlags), + hinting_flag_must_be_greater); + SK_COMPILE_ASSERT(!(kSlightHinting_DrawFilterFlag & SkPaint::kAllFlags), + slight_hinting_flag_must_be_greater); + /** * Called with each new SkPicture to render. */ @@ -80,6 +95,11 @@ public: fDeviceType = deviceType; } + void setDrawFilters(DrawFilterFlags* filters, const SkString& configName) { + fDrawFilters = filters; + fDrawFiltersConfig = configName; + } + void setBBoxHierarchyType(BBoxHierarchyType bbhType) { fBBoxHierarchyType = bbhType; } @@ -112,6 +132,7 @@ public: config.append("_gpu"); } #endif + config.append(fDrawFiltersConfig.c_str()); return config; } @@ -137,6 +158,7 @@ public: : fPicture(NULL) , fDeviceType(kBitmap_DeviceType) , fBBoxHierarchyType(kNone_BBoxHierarchyType) + , fDrawFilters(NULL) , fGridWidth(0) , fGridHeight(0) #if SK_SUPPORT_GPU @@ -155,6 +177,8 @@ protected: SkPicture* fPicture; SkDeviceTypes fDeviceType; BBoxHierarchyType fBBoxHierarchyType; + DrawFilterFlags* fDrawFilters; + SkString fDrawFiltersConfig; int fGridWidth, fGridHeight; // used when fBBoxHierarchyType is TileGrid #if SK_SUPPORT_GPU diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp index f0f908dfd0..569a0a5006 100644 --- a/tools/bench_pictures_main.cpp +++ b/tools/bench_pictures_main.cpp @@ -20,6 +20,97 @@ const int DEFAULT_REPEATS = 1; +static char const * const gFilterTypes[] = { + "paint", + "point", + "line", + "bitmap", + "rect", + "path", + "text", + "all", +}; + +static const size_t kFilterTypesCount = sizeof(gFilterTypes) / sizeof(gFilterTypes[0]); + +static char const * const gFilterFlags[] = { + "antiAlias", + "filterBitmap", + "dither", + "underlineText", + "strikeThruText", + "fakeBoldText", + "linearText", + "subpixelText", + "devKernText", + "LCDRenderText", + "embeddedBitmapText", + "autoHinting", + "verticalText", + "genA8FromLCD", + "blur", + "hinting", + "slightHinting", +}; + +static const size_t kFilterFlagsCount = sizeof(gFilterFlags) / sizeof(gFilterFlags[0]); + +static SkString filtersName(sk_tools::PictureRenderer::DrawFilterFlags* drawFilters) { + int all = drawFilters[0]; + size_t tIndex; + for (tIndex = 1; tIndex < SkDrawFilter::kTypeCount; ++tIndex) { + all &= drawFilters[tIndex]; + } + SkString result; + for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) { + SkString types; + if (all & (1 << fIndex)) { + types = gFilterTypes[SkDrawFilter::kTypeCount]; + } else { + for (tIndex = 0; tIndex < SkDrawFilter::kTypeCount; ++tIndex) { + if (drawFilters[tIndex] & (1 << fIndex)) { + types += gFilterTypes[tIndex]; + } + } + } + if (!types.size()) { + continue; + } + result += "_"; + result += types; + result += "."; + result += gFilterFlags[fIndex]; + } + return result; +} + +static SkString filterTypesUsage() { + SkString result; + for (size_t index = 0; index < kFilterTypesCount; ++index) { + result += gFilterTypes[index]; + if (index < kFilterTypesCount - 1) { + result += " | "; + } + } + return result; +} + +static SkString filterFlagsUsage() { + SkString result; + size_t len = 0; + for (size_t index = 0; index < kFilterFlagsCount; ++index) { + result += gFilterFlags[index]; + if (result.size() - len >= 72) { + result += "\n "; + len = result.size(); + } + if (index < kFilterFlagsCount - 1) { + result += " | "; + } + } + return result; +} + static void usage(const char* argv0) { SkDebugf("SkPicture benchmarking tool\n"); SkDebugf("\n" @@ -36,9 +127,10 @@ static void usage(const char* argv0) { #if SK_SUPPORT_GPU " | gpu" #endif -"]" -, argv0); - SkDebugf("\n\n"); +"]\n" +" [--filter [%s]:\n [%s]]\n" +, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str()); + SkDebugf("\n"); SkDebugf( " inputDir: A list of directories and files to use as input. Files are\n" " expected to have the .skp extension.\n\n" @@ -49,7 +141,7 @@ static void usage(const char* argv0) { SkDebugf(" --timers [wcgWC]* : " "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n"); SkDebugf( -" --mode pow2tile minWidht height[] | record | simple\n" +" --mode pow2tile minWidth height[] | record | simple\n" " | tile width[] height[] | playbackCreation:\n" " Run in the corresponding mode.\n" " Default is simple.\n"); @@ -101,6 +193,11 @@ static void usage(const char* argv0) { " --repeat: " "Set the number of times to repeat each test." " Default is %i.\n", DEFAULT_REPEATS); + SkDebugf( +" --filter type:flag : "); + SkDebugf( +"Enable canvas filtering to disable a paint flag,\n" +" disable blur, or use less hinting.\n"); } SkBenchLogger gLogger; @@ -175,6 +272,8 @@ static void parse_commandline(int argc, char* const argv[], SkTArray* bool gridSupported = false; sk_tools::PictureRenderer::BBoxHierarchyType bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; + sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount]; + sk_bzero(drawFilters, sizeof(drawFilters)); for (++argv; argv < stop; ++argv) { if (0 == strcmp(*argv, "--repeat")) { ++argv; @@ -368,6 +467,58 @@ static void parse_commandline(int argc, char* const argv[], SkTArray* gLogger.logError("Missing arg for --logPerIter\n"); PRINT_USAGE_AND_EXIT; } + } else if (0 == strcmp(*argv, "--filter")) { + ++argv; + if (argv < stop) { + const char* colon = strchr(*argv, ':'); + if (colon) { + int type = -1; + size_t typeLen = colon - *argv; + for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) { + if (typeLen == strlen(gFilterTypes[tIndex]) + && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) { + type = tIndex; + break; + } + } + if (type < 0) { + SkString err; + err.printf("Unknown type for --filter %s\n", *argv); + gLogger.logError(err); + PRINT_USAGE_AND_EXIT; + } + int flag = -1; + size_t flagLen = strlen(*argv) - typeLen - 1; + for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) { + if (flagLen == strlen(gFilterFlags[fIndex]) + && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) { + flag = 1 << fIndex; + break; + } + } + if (flag < 0) { + SkString err; + err.printf("Unknown flag for --filter %s\n", *argv); + gLogger.logError(err); + PRINT_USAGE_AND_EXIT; + } + for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) { + if (type != SkDrawFilter::kTypeCount && index != type) { + continue; + } + drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags) + (drawFilters[index] | flag); + } + } else { + SkString err; + err.printf("Unknown arg for --filter %s : missing colon\n", *argv); + gLogger.logError(err); + PRINT_USAGE_AND_EXIT; + } + } else { + gLogger.logError("Missing arg for --filter\n"); + PRINT_USAGE_AND_EXIT; + } } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) { PRINT_USAGE_AND_EXIT; } else { @@ -471,6 +622,7 @@ static void parse_commandline(int argc, char* const argv[], SkTArray* } renderer->setBBoxHierarchyType(bbhType); + renderer->setDrawFilters(drawFilters, filtersName(drawFilters)); renderer->setGridSize(gridWidth, gridHeight); benchmark->setRenderer(renderer); benchmark->setRepeats(repeats);