static void setup_benchmark(sk_tools::PictureBenchmark* benchmark) { sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount]; sk_bzero(drawFilters, sizeof(drawFilters)); if (FLAGS_filter.count() > 0) { const char* filters = FLAGS_filter[0]; const char* colon = strchr(filters, ':'); if (colon) { int32_t type = -1; size_t typeLen = colon - filters; for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) { if (typeLen == strlen(gFilterTypes[tIndex]) && !strncmp(filters, gFilterTypes[tIndex], typeLen)) { type = SkToS32(tIndex); break; } } if (type < 0) { SkString err; err.printf("Unknown type for --filter %s\n", filters); gLogger.logError(err); exit(-1); } int flag = -1; size_t flagLen = strlen(filters) - 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", filters); gLogger.logError(err); exit(-1); } 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", filters); gLogger.logError(err); exit(-1); } } if (FLAGS_timers.count() > 0) { size_t index = 0; bool timerWall = false; bool truncatedTimerWall = false; bool timerCpu = false; bool truncatedTimerCpu = false; bool timerGpu = false; while (index < strlen(FLAGS_timers[0])) { switch (FLAGS_timers[0][index]) { case 'w': timerWall = true; break; case 'c': timerCpu = true; break; case 'W': truncatedTimerWall = true; break; case 'C': truncatedTimerCpu = true; break; case 'g': timerGpu = true; break; default: SkDebugf("mystery character\n"); break; } index++; } benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu, truncatedTimerCpu, timerGpu); } SkString errorString; SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString, kBench_PictureTool)); if (errorString.size() > 0) { gLogger.logError(errorString); } if (NULL == renderer.get()) { exit(-1); } if (FLAGS_timeIndividualTiles) { if (FLAGS_multi > 1) { gLogger.logError("Cannot time individual tiles with more than one thread.\n"); exit(-1); } sk_tools::TiledPictureRenderer* tiledRenderer = renderer->getTiledRenderer(); if (NULL == tiledRenderer) { gLogger.logError("--timeIndividualTiles requires tiled rendering.\n"); exit(-1); } if (!tiledRenderer->supportsTimingIndividualTiles()) { gLogger.logError("This renderer does not support --timeIndividualTiles.\n"); exit(-1); } benchmark->setTimeIndividualTiles(true); } benchmark->setPurgeDecodedTex(FLAGS_purgeDecodedTex); benchmark->setPreprocess(FLAGS_preprocess); if (FLAGS_readPath.count() < 1) { gLogger.logError(".skp files or directories are required.\n"); exit(-1); } renderer->setDrawFilters(drawFilters, filtersName(drawFilters)); if (FLAGS_logPerIter) { benchmark->setTimerResultType(TimerData::kPerIter_Result); } else if (FLAGS_min) { benchmark->setTimerResultType(TimerData::kMin_Result); } else { benchmark->setTimerResultType(TimerData::kAvg_Result); } benchmark->setRenderer(renderer); benchmark->setRepeats(FLAGS_repeat); benchmark->setWriter(&gWriter); }
void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) { const GrTextureDomain& domain = args.fFp.cast<GrMatrixConvolutionEffect>().domain(); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fImageIncrementUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); fKernelUni = uniformHandler->addUniformArray(GrGLSLUniformHandler::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Kernel", fKernelSize.width() * fKernelSize.height()); fKernelOffsetUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "KernelOffset"); fGainUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Gain"); fBiasUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Bias"); const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* kernel = uniformHandler->getUniformCStr(fKernelUni); const char* gain = uniformHandler->getUniformCStr(fGainUni); const char* bias = uniformHandler->getUniformCStr(fBiasUni); int kWidth = fKernelSize.width(); int kHeight = fKernelSize.height(); GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); fragBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);"); fragBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc); fragBuilder->codeAppend("vec4 c;"); for (int y = 0; y < kHeight; y++) { for (int x = 0; x < kWidth; x++) { GrGLSLShaderBuilder::ShaderBlock block(fragBuilder); fragBuilder->codeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x); SkString coord; coord.printf("coord + vec2(%d, %d) * %s", x, y, imgInc); fDomain.sampleTexture(fragBuilder, uniformHandler, args.fGLSLCaps, domain, "c", coord, args.fSamplers[0]); if (!fConvolveAlpha) { fragBuilder->codeAppend("c.rgb /= c.a;"); fragBuilder->codeAppend("c.rgb = clamp(c.rgb, 0.0, 1.0);"); } fragBuilder->codeAppend("sum += c * k;"); } } if (fConvolveAlpha) { fragBuilder->codeAppendf("%s = sum * %s + %s;", args.fOutputColor, gain, bias); fragBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);", args.fOutputColor, args.fOutputColor, args.fOutputColor); } else { fDomain.sampleTexture(fragBuilder, uniformHandler, args.fGLSLCaps, domain, "c", coords2D, args.fSamplers[0]); fragBuilder->codeAppendf("%s.a = c.a;", args.fOutputColor); fragBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", args.fOutputColor, gain, bias); fragBuilder->codeAppendf("%s.rgb *= %s.a;", args.fOutputColor, args.fOutputColor); } SkString modulate; GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); fragBuilder->codeAppend(modulate.c_str()); }
static bool run_single_benchmark(const SkString& inputPath, sk_tools::PictureBenchmark& benchmark) { SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkString err; err.printf("Could not open file %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool(); // Since the old picture has been deleted, all pixels should be cleared. SkASSERT(pool->getRAMUsed() == 0); if (FLAGS_countRAM) { pool->setRAMBudget(SK_MaxU32); // Set the limit to max, so all pixels will be kept } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else { proc = &SkImageDecoder::DecodeMemory; } SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); if (NULL == picture.get()) { SkString err; err.printf("Could not read an SkPicture from %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkString filename = SkOSPath::SkBasename(inputPath.c_str()); gWriter.bench(filename.c_str(), picture->width(), picture->height()); benchmark.run(picture); #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { int cacheHits = pool->getCacheHits(); int cacheMisses = pool->getCacheMisses(); pool->resetCacheHitsAndMisses(); SkString hitString; hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses)); gLogger.logProgress(hitString); gTotalCacheHits += cacheHits; gTotalCacheMisses += cacheMisses; } #endif if (FLAGS_countRAM) { SkString ramCount("RAM used for bitmaps: "); size_t bytes = pool->getRAMUsed(); if (bytes > 1024) { size_t kb = bytes / 1024; if (kb > 1024) { size_t mb = kb / 1024; ramCount.appendf("%zi MB\n", mb); } else { ramCount.appendf("%zi KB\n", kb); } } else { ramCount.appendf("%zi bytes\n", bytes); } gLogger.logProgress(ramCount); } return true; }
virtual const char* onGetName() { fName.printf("shadermask", SkScalarToFloat(fPaint.getTextSize())); fName.appendf("_%s", fontQualityName(fPaint)); fName.appendf("_%02X", fPaint.getAlpha()); return fName.c_str(); }
static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs, sk_tools::PictureBenchmark* benchmark) { const char* argv0 = argv[0]; char* const* stop = argv + argc; int repeats = DEFAULT_REPEATS; sk_tools::PictureRenderer::SkDeviceTypes deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL); // Create a string to show our current settings. // TODO: Make it prettier. Currently it just repeats the command line. SkString commandLine("bench_pictures:"); for (int i = 1; i < argc; i++) { commandLine.appendf(" %s", *(argv+i)); } commandLine.append("\n"); bool usePipe = false; int numThreads = 1; bool useTiles = false; const char* widthString = NULL; const char* heightString = NULL; int gridWidth = 0; int gridHeight = 0; bool isPowerOf2Mode = false; bool isCopyMode = false; const char* xTilesString = NULL; const char* yTilesString = NULL; const char* mode = NULL; 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)); SkISize viewport; viewport.setEmpty(); for (++argv; argv < stop; ++argv) { if (0 == strcmp(*argv, "--repeat")) { ++argv; if (argv < stop) { repeats = atoi(*argv); if (repeats < 1) { gLogger.logError("--repeat must be given a value > 0\n"); PRINT_USAGE_AND_EXIT; } } else { gLogger.logError("Missing arg for --repeat\n"); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--pipe")) { usePipe = true; } else if (0 == strcmp(*argv, "--logFile")) { argv++; if (argv < stop) { if (!gLogger.SetLogFile(*argv)) { SkString str; str.printf("Could not open %s for writing.", *argv); gLogger.logError(str); usage(argv0); // TODO(borenet): We're disabling this for now, due to // write-protected Android devices. The very short-term // solution is to ignore the fact that we have no log file. //exit(-1); } } else { gLogger.logError("Missing arg for --logFile\n"); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--multi")) { ++argv; if (argv >= stop) { gLogger.logError("Missing arg for --multi\n"); PRINT_USAGE_AND_EXIT; } numThreads = atoi(*argv); if (numThreads < 2) { gLogger.logError("Number of threads must be at least 2.\n"); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--bbh")) { ++argv; if (argv >= stop) { gLogger.logError("Missing value for --bbh\n"); PRINT_USAGE_AND_EXIT; } if (0 == strcmp(*argv, "none")) { bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; } else if (0 == strcmp(*argv, "rtree")) { bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType; } else if (0 == strcmp(*argv, "grid")) { bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType; ++argv; if (argv >= stop) { gLogger.logError("Missing width for --bbh grid\n"); PRINT_USAGE_AND_EXIT; } gridWidth = atoi(*argv); ++argv; if (argv >= stop) { gLogger.logError("Missing height for --bbh grid\n"); PRINT_USAGE_AND_EXIT; } gridHeight = atoi(*argv); } else { SkString err; err.printf("%s is not a valid value for --bbhType\n", *argv); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--mode")) { if (renderer.get() != NULL) { SkDebugf("Cannot combine modes.\n"); PRINT_USAGE_AND_EXIT; } ++argv; if (argv >= stop) { gLogger.logError("Missing mode for --mode\n"); PRINT_USAGE_AND_EXIT; } if (0 == strcmp(*argv, "record")) { renderer.reset(SkNEW(sk_tools::RecordPictureRenderer)); gridSupported = true; } else if (0 == strcmp(*argv, "clone")) { renderer.reset(sk_tools::CreatePictureCloneRenderer()); } else if (0 == strcmp(*argv, "simple")) { renderer.reset(SkNEW(sk_tools::SimplePictureRenderer)); } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile")) || 0 == strcmp(*argv, "copyTile")) { useTiles = true; mode = *argv; if (0 == strcmp(*argv, "pow2tile")) { isPowerOf2Mode = true; } else if (0 == strcmp(*argv, "copyTile")) { isCopyMode = true; } else { gridSupported = true; } ++argv; if (argv >= stop) { SkString err; err.printf("Missing width for --mode %s\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } widthString = *argv; ++argv; if (argv >= stop) { SkString err; err.appendf("Missing height for --mode %s\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } heightString = *argv; } else if (0 == strcmp(*argv, "playbackCreation")) { renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer)); gridSupported = true; } else if (0 == strcmp(*argv, "gatherPixelRefs")) { renderer.reset(sk_tools::CreateGatherPixelRefsRenderer()); } else { SkString err; err.printf("%s is not a valid mode for --mode\n", *argv); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--viewport")) { ++argv; if (argv >= stop) { gLogger.logError("Missing width for --viewport\n"); PRINT_USAGE_AND_EXIT; } viewport.fWidth = atoi(*argv); ++argv; if (argv >= stop) { gLogger.logError("Missing height for --viewport\n"); PRINT_USAGE_AND_EXIT; } viewport.fHeight = atoi(*argv); } else if (0 == strcmp(*argv, "--tiles")) { ++argv; if (argv >= stop) { gLogger.logError("Missing x for --tiles\n"); PRINT_USAGE_AND_EXIT; } xTilesString = *argv; ++argv; if (argv >= stop) { gLogger.logError("Missing y for --tiles\n"); PRINT_USAGE_AND_EXIT; } yTilesString = *argv; } else if (0 == strcmp(*argv, "--device")) { ++argv; if (argv >= stop) { gLogger.logError("Missing mode for --device\n"); PRINT_USAGE_AND_EXIT; } if (0 == strcmp(*argv, "bitmap")) { deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; } #if SK_SUPPORT_GPU else if (0 == strcmp(*argv, "gpu")) { deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; } #endif else { SkString err; err.printf("%s is not a valid mode for --device\n", *argv); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--timers")) { ++argv; if (argv < stop) { bool timerWall = false; bool truncatedTimerWall = false; bool timerCpu = false; bool truncatedTimerCpu = false; bool timerGpu = false; for (char* t = *argv; *t; ++t) { switch (*t) { case 'w': timerWall = true; break; case 'c': timerCpu = true; break; case 'W': truncatedTimerWall = true; break; case 'C': truncatedTimerCpu = true; break; case 'g': timerGpu = true; break; default: { break; } } } benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu, truncatedTimerCpu, timerGpu); } else { gLogger.logError("Missing arg for --timers\n"); PRINT_USAGE_AND_EXIT; } } else if (0 == strcmp(*argv, "--timeIndividualTiles")) { benchmark->setTimeIndividualTiles(true); } else if (0 == strcmp(*argv, "--min")) { benchmark->setPrintMin(true); } else if (0 == strcmp(*argv, "--logPerIter")) { ++argv; if (argv < stop) { bool log = atoi(*argv) != 0; benchmark->setLogPerIter(log); } else { 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 { inputs->push_back(SkString(*argv)); } } if (numThreads > 1 && !useTiles) { gLogger.logError("Multithreaded drawing requires tiled rendering.\n"); PRINT_USAGE_AND_EXIT; } if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) { gLogger.logError("--pipe and --bbh cannot be used together\n"); PRINT_USAGE_AND_EXIT; } if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType && !gridSupported) { gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n"); PRINT_USAGE_AND_EXIT; } if (useTiles) { SkASSERT(NULL == renderer); sk_tools::TiledPictureRenderer* tiledRenderer; if (isCopyMode) { int x, y; if (xTilesString != NULL) { SkASSERT(yTilesString != NULL); x = atoi(xTilesString); y = atoi(yTilesString); if (x <= 0 || y <= 0) { gLogger.logError("--tiles must be given values > 0\n"); PRINT_USAGE_AND_EXIT; } } else { x = y = 4; } tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)); if (benchmark->timeIndividualTiles()) { gLogger.logError("timeIndividualTiles is not compatible with copyTile\n"); PRINT_USAGE_AND_EXIT; } } else if (numThreads > 1) { tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads)); } else { tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer); } if (isPowerOf2Mode) { int minWidth = atoi(widthString); if (!SkIsPow2(minWidth) || minWidth < 0) { tiledRenderer->unref(); SkString err; err.printf("-mode %s must be given a width" " value that is a power of two\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } tiledRenderer->setTileMinPowerOf2Width(minWidth); } else if (sk_tools::is_percentage(widthString)) { if (isCopyMode) { tiledRenderer->unref(); SkString err; err.printf("--mode %s does not support percentages.\n", mode); gLogger.logError(err.c_str()); PRINT_USAGE_AND_EXIT; } tiledRenderer->setTileWidthPercentage(atof(widthString)); if (!(tiledRenderer->getTileWidthPercentage() > 0)) { tiledRenderer->unref(); SkString err; err.appendf("--mode %s must be given a width percentage > 0\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } else { tiledRenderer->setTileWidth(atoi(widthString)); if (!(tiledRenderer->getTileWidth() > 0)) { tiledRenderer->unref(); SkString err; err.appendf("--mode %s must be given a width > 0\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } if (sk_tools::is_percentage(heightString)) { if (isCopyMode) { tiledRenderer->unref(); SkString err; err.printf("--mode %s does not support percentages.\n", mode); gLogger.logError(err.c_str()); PRINT_USAGE_AND_EXIT; } tiledRenderer->setTileHeightPercentage(atof(heightString)); if (!(tiledRenderer->getTileHeightPercentage() > 0)) { tiledRenderer->unref(); SkString err; err.appendf("--mode %s must be given a height percentage > 0\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } else { tiledRenderer->setTileHeight(atoi(heightString)); if (!(tiledRenderer->getTileHeight() > 0)) { tiledRenderer->unref(); SkString err; err.appendf("--mode %s must be given a height > 0\n", mode); gLogger.logError(err); PRINT_USAGE_AND_EXIT; } } if (numThreads > 1) { #if SK_SUPPORT_GPU if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) { tiledRenderer->unref(); gLogger.logError("GPU not compatible with multithreaded tiling.\n"); PRINT_USAGE_AND_EXIT; } #endif } renderer.reset(tiledRenderer); if (usePipe) { gLogger.logError("Pipe rendering is currently not compatible with tiling.\n" "Turning off pipe.\n"); } } else { if (benchmark->timeIndividualTiles()) { gLogger.logError("timeIndividualTiles requires tiled rendering.\n"); PRINT_USAGE_AND_EXIT; } if (usePipe) { if (renderer.get() != NULL) { gLogger.logError("Pipe is incompatible with other modes.\n"); PRINT_USAGE_AND_EXIT; } renderer.reset(SkNEW(sk_tools::PipePictureRenderer)); } } if (inputs->count() < 1) { PRINT_USAGE_AND_EXIT; } if (NULL == renderer) { renderer.reset(SkNEW(sk_tools::SimplePictureRenderer)); } renderer->setBBoxHierarchyType(bbhType); renderer->setDrawFilters(drawFilters, filtersName(drawFilters)); renderer->setGridSize(gridWidth, gridHeight); renderer->setViewport(viewport); benchmark->setRenderer(renderer); benchmark->setRepeats(repeats); benchmark->setDeviceType(deviceType); benchmark->setLogger(&gLogger); // Report current settings: gLogger.logProgress(commandLine); }
static void output_font(SkTypeface* face, const char* name, SkTypeface::Style style, const char* used, FILE* out) { int emSize = face->getUnitsPerEm() * 2; SkPaint paint; paint.setAntiAlias(true); paint.setTextAlign(SkPaint::kLeft_Align); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); paint.setTextSize(emSize); SkSafeUnref(paint.setTypeface(face)); SkTDArray<SkPath::Verb> verbs; SkTDArray<unsigned> charCodes; SkTDArray<SkScalar> widths; SkString ptsOut; output_path_data(paint, used, emSize, &ptsOut, &verbs, &charCodes, &widths); SkString fontnameStr(name); SkString strippedStr = strip_spaces(fontnameStr); strippedStr.appendf("%s", gStyleName[style]); const char* fontname = strippedStr.c_str(); fprintf(out, "const SkScalar %sPoints[] = {\n", fontname); ptsOut = strip_final(ptsOut); fprintf(out, "%s", ptsOut.c_str()); fprintf(out, "\n};\n\n"); fprintf(out, "const unsigned char %sVerbs[] = {\n", fontname); int verbCount = verbs.count(); int outChCount = 0; for (int index = 0; index < verbCount;) { SkPath::Verb verb = verbs[index]; SkASSERT(verb >= SkPath::kMove_Verb && verb <= SkPath::kDone_Verb); SkASSERT((unsigned) verb == (unsigned char) verb); fprintf(out, "%u", verb); if (++index < verbCount) { outChCount += 3; fprintf(out, "%c", ','); if (outChCount >= kMaxLineLength) { outChCount = 0; fprintf(out, "%c", '\n'); } else { fprintf(out, "%c", ' '); } } } fprintf(out, "\n};\n\n"); fprintf(out, "const unsigned %sCharCodes[] = {\n", fontname); int offsetCount = charCodes.count(); for (int index = 0; index < offsetCount;) { unsigned offset = charCodes[index]; fprintf(out, "%u", offset); if (++index < offsetCount) { outChCount += offset_str_len(offset) + 2; fprintf(out, "%c", ','); if (outChCount >= kMaxLineLength) { outChCount = 0; fprintf(out, "%c", '\n'); } else { fprintf(out, "%c", ' '); } } } fprintf(out, "\n};\n\n"); SkString widthsStr; fprintf(out, "const SkFixed %sWidths[] = {\n", fontname); for (int index = 0; index < offsetCount; ++index) { output_fixed(widths[index], emSize, &widthsStr); } widthsStr = strip_final(widthsStr); fprintf(out, "%s\n};\n\n", widthsStr.c_str()); fprintf(out, "const int %sCharCodesCount = (int) SK_ARRAY_COUNT(%sCharCodes);\n\n", fontname, fontname); SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); fprintf(out, "const SkPaint::FontMetrics %sMetrics = {\n", fontname); SkString metricsStr; metricsStr.printf("0x%08x, ", metrics.fFlags); output_scalar(metrics.fTop, emSize, &metricsStr); output_scalar(metrics.fAscent, emSize, &metricsStr); output_scalar(metrics.fDescent, emSize, &metricsStr); output_scalar(metrics.fBottom, emSize, &metricsStr); output_scalar(metrics.fLeading, emSize, &metricsStr); output_scalar(metrics.fAvgCharWidth, emSize, &metricsStr); output_scalar(metrics.fMaxCharWidth, emSize, &metricsStr); output_scalar(metrics.fXMin, emSize, &metricsStr); output_scalar(metrics.fXMax, emSize, &metricsStr); output_scalar(metrics.fXHeight, emSize, &metricsStr); output_scalar(metrics.fCapHeight, emSize, &metricsStr); output_scalar(metrics.fUnderlineThickness, emSize, &metricsStr); output_scalar(metrics.fUnderlinePosition, emSize, &metricsStr); metricsStr = strip_final(metricsStr); fprintf(out, "%s\n};\n\n", metricsStr.c_str()); }
InterpBench(void* param, const char name[]) : INHERITED(param) { fName.printf("interp_%s", name); fFx = 3.3f; fDx = 0.1257f; }
void TestResult::testOne() { SkPicture* pic = NULL; { SkString d; d.printf(" {%d, \"%s\"},", fDirNo, fFilename); SkString path = make_filepath(fDirNo, IN_DIR, fFilename); SkFILEStream stream(path.c_str()); if (!stream.isValid()) { SkDebugf("invalid stream %s\n", path.c_str()); goto finish; } if (fTestStep == kEncodeFiles) { size_t length = stream.getLength(); SkTArray<char, true> bytes; bytes.push_back_n(length); stream.read(&bytes[0], length); stream.rewind(); SkString wPath = make_filepath(0, outSkpDir, fFilename); SkFILEWStream wStream(wPath.c_str()); wStream.write(&bytes[0], length); wStream.flush(); } pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory); if (!pic) { SkDebugf("unable to decode %s\n", fFilename); goto finish; } int pWidth = pic->width(); int pHeight = pic->height(); int pLargerWH = SkTMax(pWidth, pHeight); GrContextFactory contextFactory; #ifdef SK_BUILD_FOR_WIN GrContext* context = contextFactory.get(kAngle); #else GrContext* context = contextFactory.get(kNative); #endif if (NULL == context) { SkDebugf("unable to allocate context for %s\n", fFilename); goto finish; } int maxWH = context->getMaxRenderTargetSize(); int scale = 1; while (pLargerWH / scale > maxWH) { scale *= 2; } SkBitmap bitmap; SkIPoint dim; do { dim.fX = (pWidth + scale - 1) / scale; dim.fY = (pHeight + scale - 1) / scale; bool success = bitmap.allocN32Pixels(dim.fX, dim.fY); if (success) { break; } SkDebugf("-%d-", scale); } while ((scale *= 2) < 256); if (scale >= 256) { SkDebugf("unable to allocate bitmap for %s (w=%d h=%d) (sw=%d sh=%d)\n", fFilename, pWidth, pHeight, dim.fX, dim.fY); goto finish; } SkCanvas skCanvas(bitmap); drawPict(pic, &skCanvas, fScaleOversized ? scale : 1); GrTextureDesc desc; desc.fConfig = kSkia8888_GrPixelConfig; desc.fFlags = kRenderTarget_GrTextureFlagBit; desc.fWidth = dim.fX; desc.fHeight = dim.fY; desc.fSampleCnt = 0; SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0)); if (!texture) { SkDebugf("unable to allocate texture for %s (w=%d h=%d)\n", fFilename, dim.fX, dim.fY); goto finish; } SkGpuDevice grDevice(context, texture.get()); SkCanvas grCanvas(&grDevice); drawPict(pic, &grCanvas, fScaleOversized ? scale : 1); SkBitmap grBitmap; grBitmap.allocPixels(grCanvas.imageInfo()); grCanvas.readPixels(&grBitmap, 0, 0); if (fTestStep == kCompareBits) { fPixelError = similarBits(grBitmap, bitmap); int skTime = timePict(pic, &skCanvas); int grTime = timePict(pic, &grCanvas); fTime = skTime - grTime; } else if (fTestStep == kEncodeFiles) { SkString pngStr = make_png_name(fFilename); const char* pngName = pngStr.c_str(); writePict(grBitmap, outGrDir, pngName); writePict(bitmap, outSkDir, pngName); } } finish: delete pic; }
static SkString makeStatusString(int dirNo) { SkString statName; statName.printf("stats%d.txt", dirNo); SkString statusFile = make_filepath(0, outStatusDir, statName.c_str()); return statusFile; }
virtual void onDrawContent(SkCanvas* canvas) { SkRect r = { 0, 0, SkIntToScalar(gWidth*2), SkIntToScalar(gHeight*2) }; static const char* gConfigNames[] = { "8888", "565", "4444" }; static const bool gFilters[] = { false, true }; static const char* gFilterNames[] = { "point", "bilinear" }; static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode }; static const char* gModeNames[] = { "C", "R", "M" }; SkScalar y = SkIntToScalar(24); SkScalar x = SkIntToScalar(10); SkCanvas* textCanvas = NULL; if (fTextPicture->width() == 0) { textCanvas = fTextPicture->beginRecording(1000, 1000); } if (textCanvas) { for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) { for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) { SkPaint p; SkString str; p.setAntiAlias(true); p.setDither(true); p.setLooper(&fLooper); str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]); p.setTextAlign(SkPaint::kCenter_Align); textCanvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p); x += r.width() * 4 / 3; } } } y += SkIntToScalar(16); for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) { for (size_t j = 0; j < SK_ARRAY_COUNT(gFilters); j++) { x = SkIntToScalar(10); for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) { for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) { SkPaint paint; setup(&paint, fTexture[i], gFilters[j], gModes[kx], gModes[ky]); paint.setDither(true); canvas->save(); canvas->translate(x, y); canvas->drawRect(r, paint); canvas->restore(); x += r.width() * 4 / 3; } } if (textCanvas) { SkPaint p; SkString str; p.setAntiAlias(true); p.setLooper(&fLooper); str.printf("%s, %s", gConfigNames[i], gFilterNames[j]); textCanvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p); } y += r.height() * 4 / 3; } } canvas->drawPicture(*fTextPicture); }
void ParseConfigs(const SkCommandLineFlags::StringArray& configs, SkCommandLineConfigArray* outResult) { outResult->reset(); for (int i = 0; i < configs.count(); ++i) { SkString extendedBackend; SkString extendedOptions; SkString simpleBackend; SkTArray<SkString> vias; SkString tag(configs[i]); SkTArray<SkString> parts; SkStrSplit(tag.c_str(), "(", kStrict_SkStrSplitMode, &parts); if (parts.count() == 2) { SkTArray<SkString> parts2; SkStrSplit(parts[1].c_str(), ")", kStrict_SkStrSplitMode, &parts2); if (parts2.count() == 2 && parts2[1].isEmpty()) { SkStrSplit(parts[0].c_str(), "-", kStrict_SkStrSplitMode, &vias); if (vias.count()) { extendedBackend = vias[vias.count() - 1]; vias.pop_back(); } else { extendedBackend = parts[0]; } extendedOptions = parts2[0]; simpleBackend.printf("%s(%s)", extendedBackend.c_str(), extendedOptions.c_str()); } } if (extendedBackend.isEmpty()) { simpleBackend = tag; SkStrSplit(tag.c_str(), "-", kStrict_SkStrSplitMode, &vias); if (vias.count()) { simpleBackend = vias[vias.count() - 1]; vias.pop_back(); } // Note: no #if SK_ANGLE: this is a special rule in the via-tag grammar. if (vias.count() && simpleBackend.equals("gl") && vias[vias.count() - 1].equals("angle")) { simpleBackend = "angle-gl"; vias.pop_back(); } for (auto& predefinedConfig : gPredefinedConfigs) { if (simpleBackend.equals(predefinedConfig.predefinedConfig)) { extendedBackend = predefinedConfig.backend; extendedOptions = predefinedConfig.options; break; } } } SkCommandLineConfig* parsedConfig = nullptr; #if SK_SUPPORT_GPU if (extendedBackend.equals("gpu")) { parsedConfig = parse_command_line_config_gpu(tag, vias, extendedOptions); } #endif if (!parsedConfig) { parsedConfig = new SkCommandLineConfig(tag, simpleBackend, vias); } outResult->emplace_back(parsedConfig); } }
ScalarBench(void* param, const char name[]) : INHERITED(param) { fName.printf("scalar_%s", name); }
FontScalerBench(void* param, bool doLCD) : INHERITED(param) { fName.printf("fontscaler_%s", doLCD ? "lcd" : "aa"); fText.set("abcdefghijklmnopqrstuvwxyz01234567890"); fDoLCD = doLCD; }
static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs, sk_tools::PictureRenderer*& renderer, SkString*& outputDir, bool* validate, int* maxComponentDiff, bool* writeWholeImage, int* clones){ const char* argv0 = argv[0]; char* const* stop = argv + argc; sk_tools::PictureRenderer::SkDeviceTypes deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; bool usePipe = false; int numThreads = 1; bool useTiles = false; const char* widthString = NULL; const char* heightString = NULL; int gridWidth = 0; int gridHeight = 0; bool isPowerOf2Mode = false; bool isCopyMode = false; const char* xTilesString = NULL; const char* yTilesString = NULL; const char* mode = NULL; bool gridSupported = false; sk_tools::PictureRenderer::BBoxHierarchyType bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; *validate = false; *maxComponentDiff = 256; *writeWholeImage = false; *clones = 0; SkISize viewport; viewport.setEmpty(); SkScalar scaleFactor = SK_Scalar1; for (++argv; argv < stop; ++argv) { if (0 == strcmp(*argv, "--mode")) { if (renderer != NULL) { renderer->unref(); SkDebugf("Cannot combine modes.\n"); usage(argv0); exit(-1); } ++argv; if (argv >= stop) { SkDebugf("Missing mode for --mode\n"); usage(argv0); exit(-1); } if (0 == strcmp(*argv, "simple")) { renderer = SkNEW(sk_tools::SimplePictureRenderer); } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile")) || 0 == strcmp(*argv, "copyTile")) { useTiles = true; mode = *argv; if (0 == strcmp(*argv, "pow2tile")) { isPowerOf2Mode = true; } else if (0 == strcmp(*argv, "copyTile")) { isCopyMode = true; } else { gridSupported = true; } ++argv; if (argv >= stop) { SkDebugf("Missing width for --mode %s\n", mode); usage(argv0); exit(-1); } widthString = *argv; ++argv; if (argv >= stop) { SkDebugf("Missing height for --mode %s\n", mode); usage(argv0); exit(-1); } heightString = *argv; } else if (0 == strcmp(*argv, "rerecord")) { renderer = SkNEW(sk_tools::RecordPictureRenderer); } else { SkDebugf("%s is not a valid mode for --mode\n", *argv); usage(argv0); exit(-1); } } else if (0 == strcmp(*argv, "--bbh")) { ++argv; if (argv >= stop) { SkDebugf("Missing value for --bbh\n"); usage(argv0); exit(-1); } if (0 == strcmp(*argv, "none")) { bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; } else if (0 == strcmp(*argv, "rtree")) { bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType; } else if (0 == strcmp(*argv, "grid")) { bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType; ++argv; if (argv >= stop) { SkDebugf("Missing width for --bbh grid\n"); usage(argv0); exit(-1); } gridWidth = atoi(*argv); ++argv; if (argv >= stop) { SkDebugf("Missing height for --bbh grid\n"); usage(argv0); exit(-1); } gridHeight = atoi(*argv); } else { SkDebugf("%s is not a valid value for --bbhType\n", *argv); usage(argv0); exit(-1);; } } else if (0 == strcmp(*argv, "--viewport")) { ++argv; if (argv >= stop) { SkDebugf("Missing width for --viewport\n"); usage(argv0); exit(-1); } viewport.fWidth = atoi(*argv); ++argv; if (argv >= stop) { SkDebugf("Missing height for --viewport\n"); usage(argv0); exit(-1); } viewport.fHeight = atoi(*argv); } else if (0 == strcmp(*argv, "--scale")) { ++argv; if (argv >= stop) { SkDebugf("Missing scaleFactor for --scale\n"); usage(argv0); exit(-1); } scaleFactor = SkDoubleToScalar(atof(*argv)); } else if (0 == strcmp(*argv, "--tiles")) { ++argv; if (argv >= stop) { SkDebugf("Missing x for --tiles\n"); usage(argv0); exit(-1); } xTilesString = *argv; ++argv; if (argv >= stop) { SkDebugf("Missing y for --tiles\n"); usage(argv0); exit(-1); } yTilesString = *argv; } else if (0 == strcmp(*argv, "--pipe")) { usePipe = true; } else if (0 == strcmp(*argv, "--multi")) { ++argv; if (argv >= stop) { SkSafeUnref(renderer); SkDebugf("Missing arg for --multi\n"); usage(argv0); exit(-1); } numThreads = atoi(*argv); if (numThreads < 2) { SkSafeUnref(renderer); SkDebugf("Number of threads must be at least 2.\n"); usage(argv0); exit(-1); } } else if (0 == strcmp(*argv, "--clone")) { ++argv; if (argv >= stop) { SkSafeUnref(renderer); SkDebugf("Missing arg for --clone\n"); usage(argv0); exit(-1); } *clones = atoi(*argv); if (*clones < 0) { SkSafeUnref(renderer); SkDebugf("Number of clones must be at least 0.\n"); usage(argv0); exit(-1); } } else if (0 == strcmp(*argv, "--device")) { ++argv; if (argv >= stop) { SkSafeUnref(renderer); SkDebugf("Missing mode for --device\n"); usage(argv0); exit(-1); } if (0 == strcmp(*argv, "bitmap")) { deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; } #if SK_SUPPORT_GPU else if (0 == strcmp(*argv, "gpu")) { deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; } #endif else { SkSafeUnref(renderer); SkDebugf("%s is not a valid mode for --device\n", *argv); usage(argv0); exit(-1); } } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) { SkSafeUnref(renderer); usage(argv0); exit(-1); } else if (0 == strcmp(*argv, "-w")) { ++argv; if (argv >= stop) { SkDebugf("Missing output directory for -w\n"); usage(argv0); exit(-1); } outputDir = SkNEW_ARGS(SkString, (*argv)); } else if (0 == strcmp(*argv, "--validate")) { *validate = true; } else if (0 == strcmp(*argv, "--maxComponentDiff")) { if (!*validate) { SkDebugf("--maxComponentDiff must be used only with --validate\n"); usage(argv0); exit(-1); } ++argv; if (argv >= stop) { SkDebugf("Missing arg for --maxComponentDiff\n"); usage(argv0); exit(-1); } *maxComponentDiff = atoi(*argv); if (*maxComponentDiff < 0 || *maxComponentDiff > 256) { SkSafeUnref(renderer); SkDebugf("maxComponentDiff: 0 - 256.\n"); usage(argv0); exit(-1); } } else if (0 == strcmp(*argv, "--writeWholeImage")) { *writeWholeImage = true; } else { inputs->push_back(SkString(*argv)); } } if (numThreads > 1 && !useTiles) { SkSafeUnref(renderer); SkDebugf("Multithreaded drawing requires tiled rendering.\n"); usage(argv0); exit(-1); } if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) { SkDebugf("--pipe and --bbh cannot be used together\n"); usage(argv0); exit(-1); } if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType && !gridSupported) { SkDebugf("'--bbh grid' is not compatible with specified --mode.\n"); usage(argv0); exit(-1); } if (useTiles) { SkASSERT(NULL == renderer); sk_tools::TiledPictureRenderer* tiledRenderer; if (isCopyMode) { int x, y; if (xTilesString != NULL) { SkASSERT(yTilesString != NULL); x = atoi(xTilesString); y = atoi(yTilesString); if (x <= 0 || y <= 0) { SkDebugf("--tiles must be given values > 0\n"); usage(argv0); exit(-1); } } else { x = y = 4; } tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)); } else if (numThreads > 1) { tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads)); } else { tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer); } if (isPowerOf2Mode) { int minWidth = atoi(widthString); if (!SkIsPow2(minWidth) || minWidth < 0) { tiledRenderer->unref(); SkString err; err.printf("-mode %s must be given a width" " value that is a power of two\n", mode); SkDebugf(err.c_str()); usage(argv0); exit(-1); } tiledRenderer->setTileMinPowerOf2Width(minWidth); } else if (sk_tools::is_percentage(widthString)) { if (isCopyMode) { tiledRenderer->unref(); SkString err; err.printf("--mode %s does not support percentages.\n", mode); SkDebugf(err.c_str()); usage(argv0); exit(-1); } tiledRenderer->setTileWidthPercentage(atof(widthString)); if (!(tiledRenderer->getTileWidthPercentage() > 0)) { tiledRenderer->unref(); SkDebugf("--mode %s must be given a width percentage > 0\n", mode); usage(argv0); exit(-1); } } else { tiledRenderer->setTileWidth(atoi(widthString)); if (!(tiledRenderer->getTileWidth() > 0)) { tiledRenderer->unref(); SkDebugf("--mode %s must be given a width > 0\n", mode); usage(argv0); exit(-1); } } if (sk_tools::is_percentage(heightString)) { if (isCopyMode) { tiledRenderer->unref(); SkString err; err.printf("--mode %s does not support percentages.\n", mode); SkDebugf(err.c_str()); usage(argv0); exit(-1); } tiledRenderer->setTileHeightPercentage(atof(heightString)); if (!(tiledRenderer->getTileHeightPercentage() > 0)) { tiledRenderer->unref(); SkDebugf("--mode %s must be given a height percentage > 0\n", mode); usage(argv0); exit(-1); } } else { tiledRenderer->setTileHeight(atoi(heightString)); if (!(tiledRenderer->getTileHeight() > 0)) { tiledRenderer->unref(); SkDebugf("--mode %s must be given a height > 0\n", mode); usage(argv0); exit(-1); } } if (numThreads > 1) { #if SK_SUPPORT_GPU if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) { tiledRenderer->unref(); SkDebugf("GPU not compatible with multithreaded tiling.\n"); usage(argv0); exit(-1); } #endif } renderer = tiledRenderer; if (usePipe) { SkDebugf("Pipe rendering is currently not compatible with tiling.\n" "Turning off pipe.\n"); } } else if (usePipe) { if (renderer != NULL) { renderer->unref(); SkDebugf("Pipe is incompatible with other modes.\n"); usage(argv0); exit(-1); } renderer = SkNEW(sk_tools::PipePictureRenderer); } if (inputs->empty()) { SkSafeUnref(renderer); if (NULL != outputDir) { SkDELETE(outputDir); } usage(argv0); exit(-1); } if (NULL == renderer) { renderer = SkNEW(sk_tools::SimplePictureRenderer); } renderer->setBBoxHierarchyType(bbhType); renderer->setGridSize(gridWidth, gridHeight); renderer->setViewport(viewport); renderer->setScaleFactor(scaleFactor); renderer->setDeviceType(deviceType); }
int tool_main(int argc, char** argv) { SkString usage; usage.printf("Time drawing .skp files.\n" "\tPossible arguments for --filter: [%s]\n\t\t[%s]", filterTypesUsage().c_str(), filterFlagsUsage().c_str()); SkCommandLineFlags::SetUsage(usage.c_str()); SkCommandLineFlags::Parse(argc, argv); if (FLAGS_repeat < 1) { SkString error; error.printf("--repeats must be >= 1. Was %i\n", FLAGS_repeat); gLogger.logError(error); exit(-1); } if (FLAGS_logFile.count() == 1) { if (!gLogger.SetLogFile(FLAGS_logFile[0])) { SkString str; str.printf("Could not open %s for writing.\n", FLAGS_logFile[0]); gLogger.logError(str); // TODO(borenet): We're disabling this for now, due to // write-protected Android devices. The very short-term // solution is to ignore the fact that we have no log file. //exit(-1); } } #ifdef SK_BUILD_JSON_WRITER SkAutoTDelete<PictureJSONResultsWriter> jsonWriter; if (FLAGS_jsonLog.count() == 1) { jsonWriter.reset(SkNEW(PictureJSONResultsWriter(FLAGS_jsonLog[0]))); gWriter.add(jsonWriter.get()); } #endif gWriter.add(&gLogWriter); #if SK_ENABLE_INST_COUNT gPrintInstCount = true; #endif SkAutoGraphics ag; sk_tools::PictureBenchmark benchmark; setup_benchmark(&benchmark); int failures = 0; for (int i = 0; i < FLAGS_readPath.count(); ++i) { failures += process_input(FLAGS_readPath[i], benchmark); } if (failures != 0) { SkString err; err.printf("Failed to run %i benchmarks.\n", failures); gLogger.logError(err); return 1; } #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { SkDebugf("Total cache hit rate: %f\n", (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses)); } #endif gWriter.end(); return 0; }
SkString status() { SkString outStr; outStr.printf("%s %d %d%s", fFilename, fPixelError, fTime, LINE_FEED); return outStr; }
GrMipMapBench(int w, int h) : fW(w), fH(h) { fName.printf("gr_mipmap_build_%dx%d", w, h); }
MatrixBench(const char name[]) { fName.printf("matrix_%s", name); }
virtual void onDraw(SkCanvas* canvas) { static const int kBmpSize = 2048; if (fLargeBitmap.isNull()) { makebm(&fLargeBitmap, kBmpSize, kBmpSize); } SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; static const int kMaxSrcRectSize = 1 << (SkNextLog2(kBmpSize) + 2); static const int kPadX = 30; static const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawBitmapRect(fLargeBitmap, NULL, SkRect::MakeWH(gSize * SK_Scalar1, gSize * SK_Scalar1), &paint); canvas->translate(SK_Scalar1 * kPadX / 2, SK_Scalar1 * kPadY / 2); SkPaint blackPaint; SkScalar titleHeight = SK_Scalar1 * 24; blackPaint.setColor(SK_ColorBLACK); blackPaint.setTextSize(titleHeight); blackPaint.setAntiAlias(true); SkString title; title.printf("Bitmap size: %d x %d", kBmpSize, kBmpSize); canvas->drawText(title.c_str(), title.size(), 0, titleHeight, blackPaint); canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight); int rowCount = 0; canvas->save(); for (int w = 1; w <= kMaxSrcRectSize; w *= 4) { for (int h = 1; h <= kMaxSrcRectSize; h *= 4) { SkIRect srcRect = SkIRect::MakeXYWH((kBmpSize - w) / 2, (kBmpSize - h) / 2, w, h); canvas->drawBitmapRect(fLargeBitmap, &srcRect, dstRect); SkString label; label.appendf("%d x %d", w, h); blackPaint.setAntiAlias(true); blackPaint.setStyle(SkPaint::kFill_Style); blackPaint.setTextSize(SK_Scalar1 * 10); SkScalar baseline = dstRect.height() + blackPaint.getTextSize() + SK_Scalar1 * 3; canvas->drawText(label.c_str(), label.size(), 0, baseline, blackPaint); blackPaint.setStyle(SkPaint::kStroke_Style); blackPaint.setStrokeWidth(SK_Scalar1); blackPaint.setAntiAlias(false); canvas->drawRect(dstRect, blackPaint); canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); ++rowCount; if ((dstRect.width() + kPadX) * rowCount > gSize) { canvas->restore(); canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); canvas->save(); rowCount = 0; } } } { // test the following code path: // SkGpuDevice::drawPath() -> SkGpuDevice::drawWithMaskFilter() SkIRect srcRect; SkPaint paint; SkBitmap bm; bm = make_chessbm(5, 5); paint.setFilterLevel(SkPaint::kLow_FilterLevel); srcRect.setXYWH(1, 1, 3, 3); SkMaskFilter* mf = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)), SkBlurMaskFilter::kHighQuality_BlurFlag | SkBlurMaskFilter::kIgnoreTransform_BlurFlag); paint.setMaskFilter(mf)->unref(); canvas->drawBitmapRect(bm, &srcRect, dstRect, &paint); } }
void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) { const GrMatrixConvolutionEffect& mce = args.fFp.cast<GrMatrixConvolutionEffect>(); const GrTextureDomain& domain = mce.domain(); int kWidth = mce.kernelSize().width(); int kHeight = mce.kernelSize().height(); int arrayCount = (kWidth * kHeight + 3) / 4; SkASSERT(4 * arrayCount >= kWidth * kHeight); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "ImageIncrement"); fKernelUni = uniformHandler->addUniformArray(kFragment_GrShaderFlag, kHalf4_GrSLType, "Kernel", arrayCount); fKernelOffsetUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "KernelOffset"); fGainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Gain"); fBiasUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "Bias"); const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* kernel = uniformHandler->getUniformCStr(fKernelUni); const char* gain = uniformHandler->getUniformCStr(fGainUni); const char* bias = uniformHandler->getUniformCStr(fBiasUni); GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);"); fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc); fragBuilder->codeAppend("half4 c;"); const char* kVecSuffix[4] = { ".x", ".y", ".z", ".w" }; for (int y = 0; y < kHeight; y++) { for (int x = 0; x < kWidth; x++) { GrGLSLShaderBuilder::ShaderBlock block(fragBuilder); int offset = y*kWidth + x; fragBuilder->codeAppendf("half k = %s[%d]%s;", kernel, offset / 4, kVecSuffix[offset & 0x3]); SkString coord; coord.printf("coord + half2(%d, %d) * %s", x, y, imgInc); fDomain.sampleTexture(fragBuilder, uniformHandler, args.fShaderCaps, domain, "c", coord, args.fTexSamplers[0]); if (!mce.convolveAlpha()) { fragBuilder->codeAppend("c.rgb /= c.a;"); fragBuilder->codeAppend("c.rgb = clamp(c.rgb, 0.0, 1.0);"); } fragBuilder->codeAppend("sum += c * k;"); } } if (mce.convolveAlpha()) { fragBuilder->codeAppendf("%s = sum * %s + %s;", args.fOutputColor, gain, bias); fragBuilder->codeAppendf("%s.a = clamp(%s.a, 0, 1);", args.fOutputColor, args.fOutputColor); fragBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);", args.fOutputColor, args.fOutputColor, args.fOutputColor); } else { fDomain.sampleTexture(fragBuilder, uniformHandler, args.fShaderCaps, domain, "c", coords2D, args.fTexSamplers[0]); fragBuilder->codeAppendf("%s.a = c.a;", args.fOutputColor); fragBuilder->codeAppendf("%s.rgb = clamp(sum.rgb * %s + %s, 0, 1);", args.fOutputColor, gain, bias); fragBuilder->codeAppendf("%s.rgb *= %s.a;", args.fOutputColor, args.fOutputColor); } fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor); }
void GrGLBicubicEffect::emitCode(EmitArgs& args) { const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>(); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fCoefficientsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType, kDefault_GrSLPrecision, "Coefficients"); fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* coeff = uniformHandler->getUniformCStr(fCoefficientsUni); GrGLSLColorSpaceXformHelper colorSpaceHelper(uniformHandler, bicubicEffect.colorSpaceXform(), &fColorSpaceXformUni); SkString cubicBlendName; static const GrGLSLShaderVar gCubicBlendArgs[] = { GrGLSLShaderVar("coefficients", kMat44f_GrSLType), GrGLSLShaderVar("t", kFloat_GrSLType), GrGLSLShaderVar("c0", kVec4f_GrSLType), GrGLSLShaderVar("c1", kVec4f_GrSLType), GrGLSLShaderVar("c2", kVec4f_GrSLType), GrGLSLShaderVar("c3", kVec4f_GrSLType), }; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); fragBuilder->emitFunction(kVec4f_GrSLType, "cubicBlend", SK_ARRAY_COUNT(gCubicBlendArgs), gCubicBlendArgs, "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n" "\tvec4 c = coefficients * ts;\n" "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n", &cubicBlendName); fragBuilder->codeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc); // We unnormalize the coord in order to determine our fractional offset (f) within the texel // We then snap coord to a texel center and renormalize. The snap prevents cases where the // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/ // double hit a texel. fragBuilder->codeAppendf("\tcoord /= %s;\n", imgInc); fragBuilder->codeAppend("\tvec2 f = fract(coord);\n"); fragBuilder->codeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc); fragBuilder->codeAppend("\tvec4 rowColors[4];\n"); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { SkString coord; coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1); SkString sampleVar; sampleVar.printf("rowColors[%d]", x); fDomain.sampleTexture(fragBuilder, args.fUniformHandler, args.fGLSLCaps, bicubicEffect.domain(), sampleVar.c_str(), coord, args.fTexSamplers[0]); } fragBuilder->codeAppendf( "\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff); } SkString bicubicColor; bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff); if (colorSpaceHelper.getXformMatrix()) { SkString xformedColor; fragBuilder->appendColorGamutXform(&xformedColor, bicubicColor.c_str(), &colorSpaceHelper); bicubicColor.swap(xformedColor); } fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(args.fInputColor)).c_str()); }
// Make sure our blits are invariant with the width of the blit (i.e. that // special case for 8 at a time have the same results as narrower blits) static void test_diagonal(skiatest::Reporter* reporter) { static const int W = 64; static const int H = W; static const SkBitmap::Config gDstConfig[] = { SkBitmap::kARGB_8888_Config, SkBitmap::kRGB_565_Config, // SkBitmap::kARGB_4444_Config, // SkBitmap::kA8_Config, }; static const SkColor gDstBG[] = { 0, 0xFFFFFFFF }; SkPaint paint; SkBitmap srcBM; srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, H); srcBM.allocPixels(); SkRect srcR = { 0, 0, SkIntToScalar(srcBM.width()), SkIntToScalar(srcBM.height()) }; // cons up a mesh to draw the bitmap with Mesh mesh(srcBM, &paint); for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) { SkBitmap dstBM0, dstBM1; dstBM0.setConfig(gDstConfig[i], W, H); dstBM1.setConfig(gDstConfig[i], W, H); dstBM0.allocPixels(); dstBM1.allocPixels(); SkCanvas canvas0(dstBM0); SkCanvas canvas1(dstBM1); SkColor bgColor; for (size_t j = 0; j < SK_ARRAY_COUNT(gDstBG); j++) { bgColor = gDstBG[j]; for (int c = 0; c <= 0xFF; c++) { srcBM.eraseARGB(0xFF, c, c, c); for (int k = 0; k < 4; k++) { bool dither = (k & 1) != 0; uint8_t alpha = (k & 2) ? 0x80 : 0xFF; paint.setDither(dither); paint.setAlpha(alpha); dstBM0.eraseColor(bgColor); dstBM1.eraseColor(bgColor); canvas0.drawRect(srcR, paint); mesh.draw(&canvas1, &paint); if (!gOnce && false) { save_bm(dstBM0, "drawBitmap.png"); save_bm(dstBM1, "drawMesh.png"); gOnce = true; } if (memcmp(dstBM0.getPixels(), dstBM1.getPixels(), dstBM0.getSize())) { SkString str; str.printf("Diagonal config=%s bg=0x%x dither=%d alpha=0x%x src=0x%x", gConfigName[gDstConfig[i]], bgColor, dither, alpha, c); reporter->reportFailed(str); } } } } } }
SkString status() { SkString outStr; outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime); return outStr; }
static bool run_single_benchmark(const SkString& inputPath, sk_tools::PictureBenchmark& benchmark) { SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkString err; err.printf("Could not open file %s\n", inputPath.c_str()); gLogger.logError(err); return false; } // Since the old picture has been deleted, all pixels should be cleared. SkASSERT(gLruImageCache.getImageCacheUsed() == 0); if (FLAGS_countRAM) { // Set the limit to zero, so all pixels will be kept gLruImageCache.setImageCacheLimit(0); } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else { proc = &SkImageDecoder::DecodeMemory; } SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); if (NULL == picture.get()) { SkString err; err.printf("Could not read an SkPicture from %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkString filename; sk_tools::get_basename(&filename, inputPath); SkString result; result.printf("running bench [%i %i] %s ", picture->width(), picture->height(), filename.c_str()); gLogger.logProgress(result); benchmark.run(picture); #if LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { int32_t cacheHits = SkLazyPixelRef::GetCacheHits(); int32_t cacheMisses = SkLazyPixelRef::GetCacheMisses(); SkLazyPixelRef::ResetCacheStats(); SkString hitString; hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses)); gLogger.logProgress(hitString); gTotalCacheHits += cacheHits; gTotalCacheMisses += cacheMisses; } #endif if (FLAGS_countRAM) { SkString ramCount("RAM used for bitmaps: "); size_t bytes = gLruImageCache.getImageCacheUsed(); if (bytes > 1024) { size_t kb = bytes / 1024; if (kb > 1024) { size_t mb = kb / 1024; ramCount.appendf("%zi MB\n", mb); } else { ramCount.appendf("%zi KB\n", kb); } } else { ramCount.appendf("%zi bytes\n", bytes); } gLogger.logProgress(ramCount); } return true; }
PathUtilsBench(Proc proc, const char name[]) { fProc = proc; fName.printf("pathUtils_%s", name); }
void onDraw(SkCanvas* canvas) override { if (!fImage) { this->setupImage(canvas); } SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; const int kMaxSrcRectSize = 1 << (SkNextLog2(gBmpSize) + 2); const int kPadX = 30; const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawImageRect(fImage, SkRect::MakeIWH(gSize, gSize), &paint); canvas->translate(SK_Scalar1 * kPadX / 2, SK_Scalar1 * kPadY / 2); SkPaint blackPaint; SkScalar titleHeight = SK_Scalar1 * 24; blackPaint.setColor(SK_ColorBLACK); blackPaint.setTextSize(titleHeight); blackPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&blackPaint); SkString title; title.printf("Bitmap size: %d x %d", gBmpSize, gBmpSize); canvas->drawString(title, 0, titleHeight, blackPaint); canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight); int rowCount = 0; canvas->save(); for (int w = 1; w <= kMaxSrcRectSize; w *= 4) { for (int h = 1; h <= kMaxSrcRectSize; h *= 4) { SkIRect srcRect = SkIRect::MakeXYWH((gBmpSize - w) / 2, (gBmpSize - h) / 2, w, h); fProc(canvas, fImage.get(), fLargeBitmap, srcRect, dstRect, nullptr); SkString label; label.appendf("%d x %d", w, h); blackPaint.setAntiAlias(true); blackPaint.setStyle(SkPaint::kFill_Style); blackPaint.setTextSize(SK_Scalar1 * 10); SkScalar baseline = dstRect.height() + blackPaint.getTextSize() + SK_Scalar1 * 3; canvas->drawString(label, 0, baseline, blackPaint); blackPaint.setStyle(SkPaint::kStroke_Style); blackPaint.setStrokeWidth(SK_Scalar1); blackPaint.setAntiAlias(false); canvas->drawRect(dstRect, blackPaint); canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); ++rowCount; if ((dstRect.width() + kPadX) * rowCount > gSize) { canvas->restore(); canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); canvas->save(); rowCount = 0; } } } { // test the following code path: // SkGpuDevice::drawPath() -> SkGpuDevice::drawWithMaskFilter() SkIRect srcRect; SkPaint paint; SkBitmap bm; bm = make_chessbm(5, 5); paint.setFilterQuality(kLow_SkFilterQuality); srcRect.setXYWH(1, 1, 3, 3); paint.setMaskFilter(SkMaskFilter::MakeBlur( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)))); sk_sp<SkImage> image(SkImage::MakeFromBitmap(bm)); fProc(canvas, image.get(), bm, srcRect, dstRect, &paint); } }