| Index: gm/gmmain.cpp
|
| ===================================================================
|
| --- gm/gmmain.cpp (revision 8262)
|
| +++ gm/gmmain.cpp (working copy)
|
| @@ -1140,6 +1140,245 @@
|
| }
|
| }
|
|
|
| +/**
|
| + * Run this test in a number of different configs (8888, 565, PDF,
|
| + * etc.), confirming that the resulting bitmaps match expectations
|
| + * (which may be different for each config).
|
| + *
|
| + * Returns all errors encountered while doing so.
|
| + */
|
| +ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs,
|
| + GrContextFactory *grFactory) {
|
| + ErrorBitfield errorsForAllConfigs = kEmptyErrorBitfield;
|
| + uint32_t gmFlags = gm->getFlags();
|
| +
|
| +#if SK_SUPPORT_GPU
|
| + struct {
|
| + int fBytes;
|
| + int fCount;
|
| + } gpuCacheSize = { -1, -1 }; // -1s mean use the default
|
| +
|
| + if (FLAGS_gpuCacheSize.count() > 0) {
|
| + if (FLAGS_gpuCacheSize.count() != 2) {
|
| + gm_fprintf(stderr, "--gpuCacheSize requires two arguments\n");
|
| + return -1;
|
| + }
|
| + gpuCacheSize.fBytes = atoi(FLAGS_gpuCacheSize[0]);
|
| + gpuCacheSize.fCount = atoi(FLAGS_gpuCacheSize[1]);
|
| + }
|
| +#endif
|
| +
|
| + for (int i = 0; i < configs.count(); i++) {
|
| + ConfigData config = gRec[configs[i]];
|
| +
|
| + // Skip any tests that we don't even need to try.
|
| + if ((kPDF_Backend == config.fBackend) &&
|
| + (!FLAGS_pdf|| (gmFlags & GM::kSkipPDF_Flag))) {
|
| + continue;
|
| + }
|
| + if ((gmFlags & GM::kSkip565_Flag) &&
|
| + (kRaster_Backend == config.fBackend) &&
|
| + (SkBitmap::kRGB_565_Config == config.fConfig)) {
|
| + continue;
|
| + }
|
| + if ((gmFlags & GM::kSkipGPU_Flag) &&
|
| + kGPU_Backend == config.fBackend) {
|
| + continue;
|
| + }
|
| +
|
| + // Now we know that we want to run this test and record its
|
| + // success or failure.
|
| + ErrorBitfield errorsForThisConfig = kEmptyErrorBitfield;
|
| + GrRenderTarget* renderTarget = NULL;
|
| +#if SK_SUPPORT_GPU
|
| + SkAutoTUnref<GrRenderTarget> rt;
|
| + AutoResetGr autogr;
|
| + if ((kEmptyErrorBitfield == errorsForThisConfig) && (kGPU_Backend == config.fBackend)) {
|
| + GrContext* gr = grFactory->get(config.fGLContextType);
|
| + bool grSuccess = false;
|
| + if (gr) {
|
| + // create a render target to back the device
|
| + GrTextureDesc desc;
|
| + desc.fConfig = kSkia8888_GrPixelConfig;
|
| + desc.fFlags = kRenderTarget_GrTextureFlagBit;
|
| + desc.fWidth = gm->getISize().width();
|
| + desc.fHeight = gm->getISize().height();
|
| + desc.fSampleCnt = config.fSampleCnt;
|
| + GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
|
| + if (tex) {
|
| + rt.reset(tex->asRenderTarget());
|
| + rt.get()->ref();
|
| + tex->unref();
|
| + autogr.set(gr);
|
| + renderTarget = rt.get();
|
| + grSuccess = NULL != renderTarget;
|
| + }
|
| + // Set the user specified cache limits if non-default.
|
| + size_t bytes;
|
| + int count;
|
| + gr->getTextureCacheLimits(&count, &bytes);
|
| + if (-1 != gpuCacheSize.fBytes) {
|
| + bytes = static_cast<size_t>(gpuCacheSize.fBytes);
|
| + }
|
| + if (-1 != gpuCacheSize.fCount) {
|
| + count = gpuCacheSize.fCount;
|
| + }
|
| + gr->setTextureCacheLimits(count, bytes);
|
| + }
|
| + if (!grSuccess) {
|
| + errorsForThisConfig |= kNoGpuContext_ErrorBitmask;
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + SkBitmap comparisonBitmap;
|
| +
|
| + const char* writePath;
|
| + if (FLAGS_writePath.count() == 1) {
|
| + writePath = FLAGS_writePath[0];
|
| + } else {
|
| + writePath = NULL;
|
| + }
|
| + if (kEmptyErrorBitfield == errorsForThisConfig) {
|
| + errorsForThisConfig |= gmmain.test_drawing(gm, config, writePath, GetGr(),
|
| + renderTarget, &comparisonBitmap);
|
| + }
|
| +
|
| + if (FLAGS_deferred && !errorsForThisConfig &&
|
| + (kGPU_Backend == config.fBackend ||
|
| + kRaster_Backend == config.fBackend)) {
|
| + errorsForThisConfig |= gmmain.test_deferred_drawing(gm, config, comparisonBitmap,
|
| + GetGr(), renderTarget);
|
| + }
|
| +
|
| + errorsForAllConfigs |= errorsForThisConfig;
|
| + }
|
| + return errorsForAllConfigs;
|
| +}
|
| +
|
| +/**
|
| + * Run this test in a number of different drawing modes (pipe,
|
| + * deferred, tiled, etc.), confirming that the resulting bitmaps all
|
| + * *exactly* match comparisonBitmap.
|
| + *
|
| + * Returns all errors encountered while doing so.
|
| + */
|
| +ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
|
| + const SkBitmap &comparisonBitmap) {
|
| + SkTDArray<SkScalar> tileGridReplayScales;
|
| + *tileGridReplayScales.append() = SK_Scalar1; // By default only test at scale 1.0
|
| + if (FLAGS_tileGridReplayScales.count() > 0) {
|
| + tileGridReplayScales.reset();
|
| + for (int i = 0; i < FLAGS_tileGridReplayScales.count(); i++) {
|
| + double val = atof(FLAGS_tileGridReplayScales[i]);
|
| + if (0 < val) {
|
| + *tileGridReplayScales.append() = SkDoubleToScalar(val);
|
| + }
|
| + }
|
| + if (0 == tileGridReplayScales.count()) {
|
| + // Should have at least one scale
|
| + gm_fprintf(stderr, "--tileGridReplayScales requires at least one scale.\n");
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| + ErrorBitfield errorsForAllModes = kEmptyErrorBitfield;
|
| + uint32_t gmFlags = gm->getFlags();
|
| +
|
| + // run the picture centric GM steps
|
| + if (!(gmFlags & GM::kSkipPicture_Flag)) {
|
| +
|
| + ErrorBitfield pictErrors = kEmptyErrorBitfield;
|
| +
|
| + //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));
|
| + SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0);
|
| + SkAutoUnref aur(pict);
|
| +
|
| + if (FLAGS_replay) {
|
| + SkBitmap bitmap;
|
| + gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
|
| + pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| + gm, compareConfig, "-replay", bitmap, &comparisonBitmap);
|
| + }
|
| +
|
| + if ((kEmptyErrorBitfield == pictErrors) && FLAGS_serialize) {
|
| + SkPicture* repict = gmmain.stream_to_new_picture(*pict);
|
| + SkAutoUnref aurr(repict);
|
| +
|
| + SkBitmap bitmap;
|
| + gmmain.generate_image_from_picture(gm, compareConfig, repict, &bitmap);
|
| + pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| + gm, compareConfig, "-serialize", bitmap, &comparisonBitmap);
|
| + }
|
| +
|
| + if (FLAGS_writePicturePath.count() == 1) {
|
| + const char* pictureSuffix = "skp";
|
| + SkString path = make_filename(FLAGS_writePicturePath[0], "",
|
| + gm->shortName(), pictureSuffix);
|
| + SkFILEWStream stream(path.c_str());
|
| + pict->serialize(&stream);
|
| + }
|
| +
|
| + errorsForAllModes |= pictErrors;
|
| + }
|
| +
|
| + // TODO: add a test in which the RTree rendering results in a
|
| + // different bitmap than the standard rendering. It should
|
| + // show up as failed in the JSON summary, and should be listed
|
| + // in the stdout also.
|
| + if (!(gmFlags & GM::kSkipPicture_Flag) && FLAGS_rtree) {
|
| + SkPicture* pict = gmmain.generate_new_picture(
|
| + gm, kRTree_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFlag);
|
| + SkAutoUnref aur(pict);
|
| + SkBitmap bitmap;
|
| + gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
|
| + errorsForAllModes |= gmmain.compare_test_results_to_reference_bitmap(
|
| + gm, compareConfig, "-rtree", bitmap, &comparisonBitmap);
|
| + }
|
| +
|
| + if (!(gmFlags & GM::kSkipPicture_Flag) && FLAGS_tileGrid) {
|
| + for(int scaleIndex = 0; scaleIndex < tileGridReplayScales.count(); ++scaleIndex) {
|
| + SkScalar replayScale = tileGridReplayScales[scaleIndex];
|
| + if ((gmFlags & GM::kSkipScaledReplay_Flag) && replayScale != 1) {
|
| + continue;
|
| + }
|
| + // We record with the reciprocal scale to obtain a replay
|
| + // result that can be validated against comparisonBitmap.
|
| + SkScalar recordScale = SkScalarInvert(replayScale);
|
| + SkPicture* pict = gmmain.generate_new_picture(
|
| + gm, kTileGrid_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFlag, recordScale);
|
| + SkAutoUnref aur(pict);
|
| + SkBitmap bitmap;
|
| + gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap, replayScale);
|
| + SkString suffix("-tilegrid");
|
| + if (SK_Scalar1 != replayScale) {
|
| + suffix += "-scale-";
|
| + suffix.appendScalar(replayScale);
|
| + }
|
| + errorsForAllModes |= gmmain.compare_test_results_to_reference_bitmap(
|
| + gm, compareConfig, suffix.c_str(), bitmap, &comparisonBitmap);
|
| + }
|
| + }
|
| +
|
| + // run the pipe centric GM steps
|
| + if (!(gmFlags & GM::kSkipPipe_Flag)) {
|
| +
|
| + ErrorBitfield pipeErrors = kEmptyErrorBitfield;
|
| +
|
| + if (FLAGS_pipe) {
|
| + pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, comparisonBitmap);
|
| + }
|
| +
|
| + if ((kEmptyErrorBitfield == pipeErrors) &&
|
| + FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) {
|
| + pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, comparisonBitmap);
|
| + }
|
| +
|
| + errorsForAllModes |= pipeErrors;
|
| + }
|
| + return errorsForAllModes;
|
| +}
|
| +
|
| int tool_main(int argc, char** argv);
|
| int tool_main(int argc, char** argv) {
|
|
|
| @@ -1156,8 +1395,6 @@
|
|
|
| SkTDArray<size_t> configs;
|
| SkTDArray<size_t> excludeConfigs;
|
| - SkTDArray<SkScalar> tileGridReplayScales;
|
| - *tileGridReplayScales.append() = SK_Scalar1; // By default only test at scale 1.0
|
| bool userConfig = false;
|
|
|
| SkString usage;
|
| @@ -1165,22 +1402,6 @@
|
| SkFlags::SetUsage(usage.c_str());
|
| SkFlags::ParseCommandLine(argc, argv);
|
|
|
| -#if SK_SUPPORT_GPU
|
| - struct {
|
| - int fBytes;
|
| - int fCount;
|
| - } gpuCacheSize = { -1, -1 }; // -1s mean use the default
|
| -
|
| - if (FLAGS_gpuCacheSize.count() > 0) {
|
| - if (FLAGS_gpuCacheSize.count() != 2) {
|
| - gm_fprintf(stderr, "--gpuCacheSize requires two arguments\n");
|
| - return -1;
|
| - }
|
| - gpuCacheSize.fBytes = atoi(FLAGS_gpuCacheSize[0]);
|
| - gpuCacheSize.fCount = atoi(FLAGS_gpuCacheSize[1]);
|
| - }
|
| -#endif
|
| -
|
| gmmain.fUseFileHierarchy = FLAGS_hierarchy;
|
| if (FLAGS_mismatchPath.count() == 1) {
|
| gmmain.fMismatchPath = FLAGS_mismatchPath[0];
|
| @@ -1207,21 +1428,6 @@
|
| }
|
| }
|
|
|
| - if (FLAGS_tileGridReplayScales.count() > 0) {
|
| - tileGridReplayScales.reset();
|
| - for (int i = 0; i < FLAGS_tileGridReplayScales.count(); i++) {
|
| - double val = atof(FLAGS_tileGridReplayScales[i]);
|
| - if (0 < val) {
|
| - *tileGridReplayScales.append() = SkDoubleToScalar(val);
|
| - }
|
| - }
|
| - if (0 == tileGridReplayScales.count()) {
|
| - // Should have at least one scale
|
| - gm_fprintf(stderr, "--tileGridReplayScales requires at least one scale.\n");
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| int moduloRemainder = -1;
|
| int moduloDivisor = -1;
|
|
|
| @@ -1371,208 +1577,17 @@
|
| size.width(), size.height());
|
|
|
| ErrorBitfield testErrors = kEmptyErrorBitfield;
|
| - uint32_t gmFlags = gm->getFlags();
|
| + testErrors |= run_multiple_configs(gmmain, gm, configs, grFactory);
|
|
|
| - for (int i = 0; i < configs.count(); i++) {
|
| - ConfigData config = gRec[configs[i]];
|
| -
|
| - // Skip any tests that we don't even need to try.
|
| - if ((kPDF_Backend == config.fBackend) &&
|
| - (!FLAGS_pdf|| (gmFlags & GM::kSkipPDF_Flag)))
|
| - {
|
| - continue;
|
| - }
|
| - if ((gmFlags & GM::kSkip565_Flag) &&
|
| - (kRaster_Backend == config.fBackend) &&
|
| - (SkBitmap::kRGB_565_Config == config.fConfig)) {
|
| - continue;
|
| - }
|
| - if ((gmFlags & GM::kSkipGPU_Flag) &&
|
| - kGPU_Backend == config.fBackend) {
|
| - continue;
|
| - }
|
| -
|
| - // Now we know that we want to run this test and record its
|
| - // success or failure.
|
| - ErrorBitfield renderErrors = kEmptyErrorBitfield;
|
| - GrRenderTarget* renderTarget = NULL;
|
| -#if SK_SUPPORT_GPU
|
| - SkAutoTUnref<GrRenderTarget> rt;
|
| - AutoResetGr autogr;
|
| - if ((kEmptyErrorBitfield == renderErrors) &&
|
| - kGPU_Backend == config.fBackend) {
|
| - GrContext* gr = grFactory->get(config.fGLContextType);
|
| - bool grSuccess = false;
|
| - if (gr) {
|
| - // create a render target to back the device
|
| - GrTextureDesc desc;
|
| - desc.fConfig = kSkia8888_GrPixelConfig;
|
| - desc.fFlags = kRenderTarget_GrTextureFlagBit;
|
| - desc.fWidth = gm->getISize().width();
|
| - desc.fHeight = gm->getISize().height();
|
| - desc.fSampleCnt = config.fSampleCnt;
|
| - GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
|
| - if (tex) {
|
| - rt.reset(tex->asRenderTarget());
|
| - rt.get()->ref();
|
| - tex->unref();
|
| - autogr.set(gr);
|
| - renderTarget = rt.get();
|
| - grSuccess = NULL != renderTarget;
|
| - }
|
| - // Set the user specified cache limits if non-default.
|
| - size_t bytes;
|
| - int count;
|
| - gr->getTextureCacheLimits(&count, &bytes);
|
| - if (-1 != gpuCacheSize.fBytes) {
|
| - bytes = static_cast<size_t>(gpuCacheSize.fBytes);
|
| - }
|
| - if (-1 != gpuCacheSize.fCount) {
|
| - count = gpuCacheSize.fCount;
|
| - }
|
| - gr->setTextureCacheLimits(count, bytes);
|
| - }
|
| - if (!grSuccess) {
|
| - renderErrors |= kNoGpuContext_ErrorBitmask;
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - SkBitmap comparisonBitmap;
|
| -
|
| - const char* writePath;
|
| - if (FLAGS_writePath.count() == 1) {
|
| - writePath = FLAGS_writePath[0];
|
| - } else {
|
| - writePath = NULL;
|
| - }
|
| - if (kEmptyErrorBitfield == renderErrors) {
|
| - renderErrors |= gmmain.test_drawing(gm, config, writePath,
|
| - GetGr(),
|
| - renderTarget,
|
| - &comparisonBitmap);
|
| - }
|
| -
|
| - if (FLAGS_deferred && !renderErrors &&
|
| - (kGPU_Backend == config.fBackend ||
|
| - kRaster_Backend == config.fBackend)) {
|
| - renderErrors |= gmmain.test_deferred_drawing(gm, config,
|
| - comparisonBitmap,
|
| - GetGr(),
|
| - renderTarget);
|
| - }
|
| -
|
| - testErrors |= renderErrors;
|
| - }
|
| -
|
| SkBitmap comparisonBitmap;
|
| const ConfigData compareConfig =
|
| { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "comparison", false };
|
| testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap, false);
|
|
|
| - // run the picture centric GM steps
|
| - if (!(gmFlags & GM::kSkipPicture_Flag)) {
|
| + // TODO(epoger): only run this if gmmain.generate_image() succeeded?
|
| + // Otherwise, what are we comparing against?
|
| + testErrors |= run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap);
|
|
|
| - ErrorBitfield pictErrors = kEmptyErrorBitfield;
|
| -
|
| - //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));
|
| - SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0);
|
| - SkAutoUnref aur(pict);
|
| -
|
| - if ((kEmptyErrorBitfield == testErrors) && FLAGS_replay) {
|
| - SkBitmap bitmap;
|
| - gmmain.generate_image_from_picture(gm, compareConfig, pict,
|
| - &bitmap);
|
| - pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| - gm, compareConfig, "-replay", bitmap, &comparisonBitmap);
|
| - }
|
| -
|
| - if ((kEmptyErrorBitfield == testErrors) &&
|
| - (kEmptyErrorBitfield == pictErrors) &&
|
| - FLAGS_serialize) {
|
| - SkPicture* repict = gmmain.stream_to_new_picture(*pict);
|
| - SkAutoUnref aurr(repict);
|
| -
|
| - SkBitmap bitmap;
|
| - gmmain.generate_image_from_picture(gm, compareConfig, repict,
|
| - &bitmap);
|
| - pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| - gm, compareConfig, "-serialize", bitmap, &comparisonBitmap);
|
| - }
|
| -
|
| - if (FLAGS_writePicturePath.count() == 1) {
|
| - const char* pictureSuffix = "skp";
|
| - SkString path = make_filename(FLAGS_writePicturePath[0], "",
|
| - gm->shortName(),
|
| - pictureSuffix);
|
| - SkFILEWStream stream(path.c_str());
|
| - pict->serialize(&stream);
|
| - }
|
| -
|
| - testErrors |= pictErrors;
|
| - }
|
| -
|
| - // TODO: add a test in which the RTree rendering results in a
|
| - // different bitmap than the standard rendering. It should
|
| - // show up as failed in the JSON summary, and should be listed
|
| - // in the stdout also.
|
| - if (!(gmFlags & GM::kSkipPicture_Flag) && FLAGS_rtree) {
|
| - SkPicture* pict = gmmain.generate_new_picture(
|
| - gm, kRTree_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFlag);
|
| - SkAutoUnref aur(pict);
|
| - SkBitmap bitmap;
|
| - gmmain.generate_image_from_picture(gm, compareConfig, pict,
|
| - &bitmap);
|
| - testErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| - gm, compareConfig, "-rtree", bitmap, &comparisonBitmap);
|
| - }
|
| -
|
| - if (!(gmFlags & GM::kSkipPicture_Flag) && FLAGS_tileGrid) {
|
| - for(int scaleIndex = 0; scaleIndex < tileGridReplayScales.count(); ++scaleIndex) {
|
| - SkScalar replayScale = tileGridReplayScales[scaleIndex];
|
| - if ((gmFlags & GM::kSkipScaledReplay_Flag) && replayScale != 1)
|
| - continue;
|
| - // We record with the reciprocal scale to obtain a replay
|
| - // result that can be validated against comparisonBitmap.
|
| - SkScalar recordScale = SkScalarInvert(replayScale);
|
| - SkPicture* pict = gmmain.generate_new_picture(
|
| - gm, kTileGrid_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFlag,
|
| - recordScale);
|
| - SkAutoUnref aur(pict);
|
| - SkBitmap bitmap;
|
| - gmmain.generate_image_from_picture(gm, compareConfig, pict,
|
| - &bitmap, replayScale);
|
| - SkString suffix("-tilegrid");
|
| - if (SK_Scalar1 != replayScale) {
|
| - suffix += "-scale-";
|
| - suffix.appendScalar(replayScale);
|
| - }
|
| - testErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
| - gm, compareConfig, suffix.c_str(), bitmap,
|
| - &comparisonBitmap);
|
| - }
|
| - }
|
| -
|
| - // run the pipe centric GM steps
|
| - if (!(gmFlags & GM::kSkipPipe_Flag)) {
|
| -
|
| - ErrorBitfield pipeErrors = kEmptyErrorBitfield;
|
| -
|
| - if ((kEmptyErrorBitfield == testErrors) && FLAGS_pipe) {
|
| - pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig,
|
| - comparisonBitmap);
|
| - }
|
| -
|
| - if ((kEmptyErrorBitfield == testErrors) &&
|
| - (kEmptyErrorBitfield == pipeErrors) &&
|
| - FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) {
|
| - pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig,
|
| - comparisonBitmap);
|
| - }
|
| -
|
| - testErrors |= pipeErrors;
|
| - }
|
| -
|
| // Update overall results.
|
| // We only tabulate the particular error types that we currently
|
| // care about (e.g., missing reference images). Later on, if we
|
|
|