1 // Main binary for DM. 2 // For a high-level overview, please see dm/README. 3 4 #include "CrashHandler.h" 5 #include "LazyDecodeBitmap.h" 6 #include "SkCommonFlags.h" 7 #include "SkForceLinking.h" 8 #include "SkGraphics.h" 9 #include "SkOSFile.h" 10 #include "SkPicture.h" 11 #include "SkString.h" 12 #include "SkTaskGroup.h" 13 #include "Test.h" 14 #include "gm.h" 15 #include "sk_tool_utils.h" 16 #include "sk_tool_utils_flags.h" 17 18 #include "DMCpuGMTask.h" 19 #include "DMGpuGMTask.h" 20 #include "DMGpuSupport.h" 21 #include "DMPDFTask.h" 22 #include "DMReporter.h" 23 #include "DMSKPTask.h" 24 #include "DMTask.h" 25 #include "DMTaskRunner.h" 26 #include "DMTestTask.h" 27 #include "DMWriteTask.h" 28 29 #ifdef SK_BUILD_POPPLER 30 # include "SkPDFRasterizer.h" 31 # define RASTERIZE_PDF_PROC SkPopplerRasterizePDF 32 #else 33 # define RASTERIZE_PDF_PROC NULL 34 #endif 35 36 #include <ctype.h> 37 38 using skiagm::GM; 39 using skiagm::GMRegistry; 40 using skiatest::Test; 41 using skiatest::TestRegistry; 42 43 static const char kGpuAPINameGL[] = "gl"; 44 static const char kGpuAPINameGLES[] = "gles"; 45 46 DEFINE_bool(gms, true, "Run GMs?"); 47 DEFINE_bool(tests, true, "Run tests?"); 48 DEFINE_bool(reportUsedChars, false, "Output test font construction data to be pasted into" 49 " create_test_font.cpp."); 50 51 __SK_FORCE_IMAGE_DECODER_LINKING; 52 53 // "FooBar" -> "foobar". Obviously, ASCII only. 54 static SkString lowercase(SkString s) { 55 for (size_t i = 0; i < s.size(); i++) { 56 s[i] = tolower(s[i]); 57 } 58 return s; 59 } 60 61 static const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType; 62 static const GrContextFactory::GLContextType nvpr = GrContextFactory::kNVPR_GLContextType; 63 static const GrContextFactory::GLContextType null = GrContextFactory::kNull_GLContextType; 64 static const GrContextFactory::GLContextType debug = GrContextFactory::kDebug_GLContextType; 65 #if SK_ANGLE 66 static const GrContextFactory::GLContextType angle = GrContextFactory::kANGLE_GLContextType; 67 #endif 68 #if SK_MESA 69 static const GrContextFactory::GLContextType mesa = GrContextFactory::kMESA_GLContextType; 70 #endif 71 72 static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms, 73 const SkTArray<SkString>& configs, 74 GrGLStandard gpuAPI, 75 DM::Reporter* reporter, 76 DM::TaskRunner* tasks) { 77 #define START(name, type, ...) \ 78 if (lowercase(configs[j]).equals(name)) { \ 79 tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, gms[i], ## __VA_ARGS__))); \ 80 } 81 for (int i = 0; i < gms.count(); i++) { 82 for (int j = 0; j < configs.count(); j++) { 83 84 START("565", CpuGMTask, kRGB_565_SkColorType); 85 START("8888", CpuGMTask, kN32_SkColorType); 86 START("gpu", GpuGMTask, native, gpuAPI, 0); 87 START("msaa4", GpuGMTask, native, gpuAPI, 4); 88 START("msaa16", GpuGMTask, native, gpuAPI, 16); 89 START("nvprmsaa4", GpuGMTask, nvpr, gpuAPI, 4); 90 START("nvprmsaa16", GpuGMTask, nvpr, gpuAPI, 16); 91 START("gpunull", GpuGMTask, null, gpuAPI, 0); 92 START("gpudebug", GpuGMTask, debug, gpuAPI, 0); 93 #if SK_ANGLE 94 START("angle", GpuGMTask, angle, gpuAPI, 0); 95 #endif 96 #if SK_MESA 97 START("mesa", GpuGMTask, mesa, gpuAPI, 0); 98 #endif 99 START("pdf", PDFTask, RASTERIZE_PDF_PROC); 100 } 101 } 102 #undef START 103 } 104 105 static void kick_off_tests(const SkTDArray<TestRegistry::Factory>& tests, 106 DM::Reporter* reporter, 107 DM::TaskRunner* tasks) { 108 for (int i = 0; i < tests.count(); i++) { 109 SkAutoTDelete<Test> test(tests[i](NULL)); 110 if (test->isGPUTest()) { 111 tasks->add(SkNEW_ARGS(DM::GpuTestTask, (reporter, tasks, tests[i]))); 112 } else { 113 tasks->add(SkNEW_ARGS(DM::CpuTestTask, (reporter, tasks, tests[i]))); 114 } 115 } 116 } 117 118 static void find_skps(SkTArray<SkString>* skps) { 119 if (FLAGS_skps.isEmpty()) { 120 return; 121 } 122 123 SkOSFile::Iter it(FLAGS_skps[0], ".skp"); 124 SkString filename; 125 while (it.next(&filename)) { 126 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) { 127 skps->push_back(SkOSPath::Join(FLAGS_skps[0], filename.c_str())); 128 } 129 } 130 } 131 132 static void kick_off_skps(const SkTArray<SkString>& skps, 133 DM::Reporter* reporter, 134 DM::TaskRunner* tasks) { 135 for (int i = 0; i < skps.count(); ++i) { 136 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(skps[i].c_str())); 137 if (stream.get() == NULL) { 138 SkDebugf("Could not read %s.\n", skps[i].c_str()); 139 exit(1); 140 } 141 SkAutoTUnref<SkPicture> pic( 142 SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeBitmap)); 143 if (pic.get() == NULL) { 144 SkDebugf("Could not read %s as an SkPicture.\n", skps[i].c_str()); 145 exit(1); 146 } 147 148 SkString filename = SkOSPath::Basename(skps[i].c_str()); 149 tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic, filename))); 150 tasks->add(SkNEW_ARGS(DM::PDFTask, (reporter, tasks, pic, filename, RASTERIZE_PDF_PROC))); 151 } 152 } 153 154 static void report_failures(const SkTArray<SkString>& failures) { 155 if (failures.count() == 0) { 156 return; 157 } 158 159 SkDebugf("Failures:\n"); 160 for (int i = 0; i < failures.count(); i++) { 161 SkDebugf(" %s\n", failures[i].c_str()); 162 } 163 SkDebugf("%d failures.\n", failures.count()); 164 } 165 166 static GrGLStandard get_gl_standard() { 167 if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { 168 return kGL_GrGLStandard; 169 } 170 if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { 171 return kGLES_GrGLStandard; 172 } 173 return kNone_GrGLStandard; 174 } 175 176 template <typename T, typename Registry> 177 static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) { 178 for (const Registry* reg = head; reg != NULL; reg = reg->next()) { 179 SkAutoTDelete<T> forName(reg->factory()(NULL)); 180 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, forName->getName())) { 181 *out->append() = reg->factory(); 182 } 183 } 184 } 185 186 int dm_main(); 187 int dm_main() { 188 SetupCrashHandler(); 189 SkAutoGraphics ag; 190 SkTaskGroup::Enabler enabled(FLAGS_threads); 191 192 if (FLAGS_dryRun) { 193 FLAGS_verbose = true; 194 } 195 #if SK_ENABLE_INST_COUNT 196 gPrintInstCount = FLAGS_leaks; 197 #endif 198 199 SkTArray<SkString> configs; 200 for (int i = 0; i < FLAGS_config.count(); i++) { 201 SkStrSplit(FLAGS_config[i], ", ", &configs); 202 } 203 204 GrGLStandard gpuAPI = get_gl_standard(); 205 206 SkTDArray<GMRegistry::Factory> gms; 207 if (FLAGS_gms) { 208 append_matching_factories<GM>(GMRegistry::Head(), &gms); 209 } 210 211 SkTDArray<TestRegistry::Factory> tests; 212 if (FLAGS_tests) { 213 append_matching_factories<Test>(TestRegistry::Head(), &tests); 214 } 215 216 SkTArray<SkString> skps; 217 find_skps(&skps); 218 219 SkDebugf("%d GMs x %d configs, %d tests, %d pictures\n", 220 gms.count(), configs.count(), tests.count(), skps.count()); 221 DM::Reporter reporter; 222 223 DM::TaskRunner tasks; 224 kick_off_tests(tests, &reporter, &tasks); 225 kick_off_gms(gms, configs, gpuAPI, &reporter, &tasks); 226 kick_off_skps(skps, &reporter, &tasks); 227 tasks.wait(); 228 229 DM::WriteTask::DumpJson(); 230 231 SkDebugf("\n"); 232 #ifdef SK_DEBUG 233 if (FLAGS_portableFonts && FLAGS_reportUsedChars) { 234 sk_tool_utils::report_used_chars(); 235 } 236 #endif 237 238 SkTArray<SkString> failures; 239 reporter.getFailures(&failures); 240 report_failures(failures); 241 return failures.count() > 0; 242 } 243 244 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 245 int main(int argc, char** argv) { 246 SkCommandLineFlags::Parse(argc, argv); 247 return dm_main(); 248 } 249 #endif 250