Exemplo n.º 1
0
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;
    }

    bool success = false;
    SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
    if (!success) {
        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);
    return true;
}
Exemplo n.º 2
0
static void 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;
    }

    SkPicture picture(&inputStream);

    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);
}
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);
    }

    bool success = false;
    SkPicture* picture;
    if (FLAGS_deferImageDecoding) {
        picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &lazy_decode_bitmap));
    } else {
        picture = SkNEW_ARGS(SkPicture, (&inputStream, &success, &SkImageDecoder::DecodeMemory));
    }
    SkAutoTDelete<SkPicture> ad(picture);

    if (!success) {
        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;
}
Exemplo n.º 4
0
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;

    // 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;
    bool multiThreaded = false;
    bool useTiles = false;
    const char* widthString = NULL;
    const char* heightString = NULL;
    bool isPowerOf2Mode = false;
    const char* mode = NULL;
    for (++argv; argv < stop; ++argv) {
        if (0 == strcmp(*argv, "--repeat")) {
            ++argv;
            if (argv < stop) {
                repeats = atoi(*argv);
                if (repeats < 1) {
                    SkDELETE(benchmark);
                    gLogger.logError("--repeat must be given a value > 0\n");
                    exit(-1);
                }
            } else {
                SkDELETE(benchmark);
                gLogger.logError("Missing arg for --repeat\n");
                usage(argv0);
                exit(-1);
            }
        } 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);
                    exit(-1);
                }
            } else {
                gLogger.logError("Missing arg for --logFile\n");
                usage(argv0);
                exit(-1);
            }
        } else if (0 == strcmp(*argv, "--mode")) {
            SkDELETE(benchmark);

            ++argv;
            if (argv >= stop) {
                gLogger.logError("Missing mode for --mode\n");
                usage(argv0);
                exit(-1);
            }

            if (0 == strcmp(*argv, "record")) {
                benchmark = SkNEW(sk_tools::RecordPictureBenchmark);
            } else if (0 == strcmp(*argv, "simple")) {
                benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
            } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
                useTiles = true;
                mode = *argv;

                if (0 == strcmp(*argv, "pow2tile")) {
                    isPowerOf2Mode = true;
                }

                ++argv;
                if (argv >= stop) {
                    SkString err;
                    err.printf("Missing width for --mode %s\n", mode);
                    gLogger.logError(err);
                    usage(argv0);
                    exit(-1);
                }

                widthString = *argv;
                ++argv;
                if (argv >= stop) {
                    gLogger.logError("Missing height for --mode tile\n");
                    usage(argv0);
                    exit(-1);
                }
                heightString = *argv;

                ++argv;
                if (argv < stop && 0 == strcmp(*argv, "multi")) {
                    multiThreaded = true;
                } else {
                    --argv;
                }
            } else if (0 == strcmp(*argv, "playbackCreation")) {
                benchmark = SkNEW(sk_tools::PlaybackCreationBenchmark);
            } else {
                SkString err;
                err.printf("%s is not a valid mode for --mode\n", *argv);
                gLogger.logError(err);
                usage(argv0);
                exit(-1);
            }
        }  else if (0 == strcmp(*argv, "--device")) {
            ++argv;
            if (argv >= stop) {
                gLogger.logError("Missing mode for --deivce\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 {
                SkString err;
                err.printf("%s is not a valid mode for --device\n", *argv);
                gLogger.logError(err);
                usage(argv0);
                exit(-1);
            }

        } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
            SkDELETE(benchmark);
            usage(argv0);
            exit(0);
        } else {
            inputs->push_back(SkString(*argv));
        }
    }

    if (useTiles) {
        sk_tools::TiledPictureBenchmark* tileBenchmark = SkNEW(sk_tools::TiledPictureBenchmark);
        if (isPowerOf2Mode) {
            int minWidth = atoi(widthString);
            if (!SkIsPow2(minWidth) || minWidth < 0) {
                SkDELETE(tileBenchmark);
                SkString err;
                err.printf("--mode %s must be given a width"
                         " value that is a power of two\n", mode);
                gLogger.logError(err);
                exit(-1);
            }
            tileBenchmark->setTileMinPowerOf2Width(minWidth);
        } else if (sk_tools::is_percentage(widthString)) {
            tileBenchmark->setTileWidthPercentage(atof(widthString));
            if (!(tileBenchmark->getTileWidthPercentage() > 0)) {
                SkDELETE(tileBenchmark);
                gLogger.logError("--mode tile must be given a width percentage > 0\n");
                exit(-1);
            }
        } else {
            tileBenchmark->setTileWidth(atoi(widthString));
            if (!(tileBenchmark->getTileWidth() > 0)) {
                SkDELETE(tileBenchmark);
                gLogger.logError("--mode tile must be given a width > 0\n");
                exit(-1);
            }
        }

        if (sk_tools::is_percentage(heightString)) {
            tileBenchmark->setTileHeightPercentage(atof(heightString));
            if (!(tileBenchmark->getTileHeightPercentage() > 0)) {
                SkDELETE(tileBenchmark);
                gLogger.logError("--mode tile must be given a height percentage > 0\n");
                exit(-1);
            }
        } else {
            tileBenchmark->setTileHeight(atoi(heightString));
            if (!(tileBenchmark->getTileHeight() > 0)) {
                SkDELETE(tileBenchmark);
                gLogger.logError("--mode tile must be given a height > 0\n");
                exit(-1);
            }
        }
        tileBenchmark->setThreading(multiThreaded);
        tileBenchmark->setUsePipe(usePipe);
        benchmark = tileBenchmark;
    } else if (usePipe) {
        SkDELETE(benchmark);
        benchmark = SkNEW(sk_tools::PipePictureBenchmark);
    }
    if (inputs->count() < 1) {
        SkDELETE(benchmark);
        usage(argv0);
        exit(-1);
    }

    if (NULL == benchmark) {
        benchmark = SkNEW(sk_tools::SimplePictureBenchmark);
    }

    benchmark->setRepeats(repeats);
    benchmark->setDeviceType(deviceType);
    benchmark->setLogger(&gLogger);
    // Report current settings:
    gLogger.logProgress(commandLine);
}
Exemplo n.º 5
0
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;
    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 = pool->fCacheHits;
        int32_t cacheMisses = pool->fCacheMisses;
        pool->fCacheHits = pool->fCacheMisses = 0;
        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;
}
Exemplo n.º 6
0
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);
}