Home | History | Annotate | Download | only in dm
      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