Chromium Code Reviews| Index: gm/gmmain.cpp |
| =================================================================== |
| --- gm/gmmain.cpp (revision 8262) |
| +++ gm/gmmain.cpp (working copy) |
| @@ -1140,6 +1140,257 @@ |
| } |
| } |
| +/** |
| + * 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, |
|
epoger
2013/03/20 17:26:42
All of this code just extracted from tools_main().
|
| + 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, |
|
epoger
2013/03/20 17:26:42
All of this code just extracted from tools_main().
|
| + 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); |
|
scroggo
2013/03/20 17:41:30
Over 100 lines.
epoger
2013/03/20 17:54:49
Fixed this and other line length / style stuff in
|
| + } |
| + |
| + 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); |
|
scroggo
2013/03/20 17:41:30
100 lines.
|
| + 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, |
|
scroggo
2013/03/20 17:41:30
100 lines.
|
| + 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 +1407,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 +1414,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 +1440,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 +1589,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 |