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
This commit is contained in:
caryclark@google.com 2012-11-06 21:26:13 +00:00
parent 9daf96afb3
commit a362237644
4 changed files with 222 additions and 10 deletions

View File

@ -32,7 +32,9 @@ public:
kBitmap_Type, kBitmap_Type,
kRect_Type, kRect_Type,
kPath_Type, kPath_Type,
kText_Type kText_Type,
kTypeCount
}; };
/** /**

View File

@ -16,6 +16,7 @@
#endif #endif
#include "SkGraphics.h" #include "SkGraphics.h"
#include "SkImageEncoder.h" #include "SkImageEncoder.h"
#include "SkMaskFilter.h"
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkPicture.h" #include "SkPicture.h"
#include "SkRTree.h" #include "SkRTree.h"
@ -51,25 +52,58 @@ void PictureRenderer::init(SkPicture* pict) {
fCanvas.reset(this->setupCanvas()); 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() { SkCanvas* PictureRenderer::setupCanvas() {
return this->setupCanvas(fPicture->width(), fPicture->height()); return this->setupCanvas(fPicture->width(), fPicture->height());
} }
SkCanvas* PictureRenderer::setupCanvas(int width, int height) { SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
SkCanvas* canvas;
switch(fDeviceType) { switch(fDeviceType) {
case kBitmap_DeviceType: { case kBitmap_DeviceType: {
SkBitmap bitmap; SkBitmap bitmap;
sk_tools::setup_bitmap(&bitmap, width, height); sk_tools::setup_bitmap(&bitmap, width, height);
return SkNEW_ARGS(SkCanvas, (bitmap)); canvas = SkNEW_ARGS(SkCanvas, (bitmap));
break; return setUpFilter(canvas, fDrawFilters);
} }
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
case kGPU_DeviceType: { case kGPU_DeviceType: {
SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
(fGrContext, SkBitmap::kARGB_8888_Config, (fGrContext, SkBitmap::kARGB_8888_Config,
width, height))); width, height)));
return SkNEW_ARGS(SkCanvas, (device.get())); canvas = SkNEW_ARGS(SkCanvas, (device.get()));
break; return setUpFilter(canvas, fDrawFilters);
} }
#endif #endif
default: default:

View File

@ -1,4 +1,4 @@
/* *
* Copyright 2012 Google Inc. * Copyright 2012 Google Inc.
* *
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
@ -9,6 +9,7 @@
#define PictureRenderer_DEFINED #define PictureRenderer_DEFINED
#include "SkCountdown.h" #include "SkCountdown.h"
#include "SkDrawFilter.h"
#include "SkMath.h" #include "SkMath.h"
#include "SkPicture.h" #include "SkPicture.h"
#include "SkRect.h" #include "SkRect.h"
@ -46,6 +47,20 @@ public:
kTileGrid_BBoxHierarchyType, 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. * Called with each new SkPicture to render.
*/ */
@ -80,6 +95,11 @@ public:
fDeviceType = deviceType; fDeviceType = deviceType;
} }
void setDrawFilters(DrawFilterFlags* filters, const SkString& configName) {
fDrawFilters = filters;
fDrawFiltersConfig = configName;
}
void setBBoxHierarchyType(BBoxHierarchyType bbhType) { void setBBoxHierarchyType(BBoxHierarchyType bbhType) {
fBBoxHierarchyType = bbhType; fBBoxHierarchyType = bbhType;
} }
@ -112,6 +132,7 @@ public:
config.append("_gpu"); config.append("_gpu");
} }
#endif #endif
config.append(fDrawFiltersConfig.c_str());
return config; return config;
} }
@ -137,6 +158,7 @@ public:
: fPicture(NULL) : fPicture(NULL)
, fDeviceType(kBitmap_DeviceType) , fDeviceType(kBitmap_DeviceType)
, fBBoxHierarchyType(kNone_BBoxHierarchyType) , fBBoxHierarchyType(kNone_BBoxHierarchyType)
, fDrawFilters(NULL)
, fGridWidth(0) , fGridWidth(0)
, fGridHeight(0) , fGridHeight(0)
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
@ -155,6 +177,8 @@ protected:
SkPicture* fPicture; SkPicture* fPicture;
SkDeviceTypes fDeviceType; SkDeviceTypes fDeviceType;
BBoxHierarchyType fBBoxHierarchyType; BBoxHierarchyType fBBoxHierarchyType;
DrawFilterFlags* fDrawFilters;
SkString fDrawFiltersConfig;
int fGridWidth, fGridHeight; // used when fBBoxHierarchyType is TileGrid int fGridWidth, fGridHeight; // used when fBBoxHierarchyType is TileGrid
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU

View File

@ -20,6 +20,97 @@
const int DEFAULT_REPEATS = 1; 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) { static void usage(const char* argv0) {
SkDebugf("SkPicture benchmarking tool\n"); SkDebugf("SkPicture benchmarking tool\n");
SkDebugf("\n" SkDebugf("\n"
@ -36,9 +127,10 @@ static void usage(const char* argv0) {
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
" | gpu" " | gpu"
#endif #endif
"]" "]\n"
, argv0); " [--filter [%s]:\n [%s]]\n"
SkDebugf("\n\n"); , argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
SkDebugf("\n");
SkDebugf( SkDebugf(
" inputDir: A list of directories and files to use as input. Files are\n" " inputDir: A list of directories and files to use as input. Files are\n"
" expected to have the .skp extension.\n\n" " expected to have the .skp extension.\n\n"
@ -49,7 +141,7 @@ static void usage(const char* argv0) {
SkDebugf(" --timers [wcgWC]* : " SkDebugf(" --timers [wcgWC]* : "
"Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n"); "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
SkDebugf( SkDebugf(
" --mode pow2tile minWidht height[] | record | simple\n" " --mode pow2tile minWidth height[] | record | simple\n"
" | tile width[] height[] | playbackCreation:\n" " | tile width[] height[] | playbackCreation:\n"
" Run in the corresponding mode.\n" " Run in the corresponding mode.\n"
" Default is simple.\n"); " Default is simple.\n");
@ -101,6 +193,11 @@ static void usage(const char* argv0) {
" --repeat: " " --repeat: "
"Set the number of times to repeat each test." "Set the number of times to repeat each test."
" Default is %i.\n", DEFAULT_REPEATS); " 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; SkBenchLogger gLogger;
@ -175,6 +272,8 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
bool gridSupported = false; bool gridSupported = false;
sk_tools::PictureRenderer::BBoxHierarchyType bbhType = sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
sk_tools::PictureRenderer::kNone_BBoxHierarchyType; sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
sk_bzero(drawFilters, sizeof(drawFilters));
for (++argv; argv < stop; ++argv) { for (++argv; argv < stop; ++argv) {
if (0 == strcmp(*argv, "--repeat")) { if (0 == strcmp(*argv, "--repeat")) {
++argv; ++argv;
@ -368,6 +467,58 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
gLogger.logError("Missing arg for --logPerIter\n"); gLogger.logError("Missing arg for --logPerIter\n");
PRINT_USAGE_AND_EXIT; 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")) { } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
PRINT_USAGE_AND_EXIT; PRINT_USAGE_AND_EXIT;
} else { } else {
@ -471,6 +622,7 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
} }
renderer->setBBoxHierarchyType(bbhType); renderer->setBBoxHierarchyType(bbhType);
renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
renderer->setGridSize(gridWidth, gridHeight); renderer->setGridSize(gridWidth, gridHeight);
benchmark->setRenderer(renderer); benchmark->setRenderer(renderer);
benchmark->setRepeats(repeats); benchmark->setRepeats(repeats);