1#include "DMTask.h"
2#include "DMTaskRunner.h"
3#include "SkCommandLineFlags.h"
4
5DEFINE_bool(cpu, true, "Master switch for running CPU-bound work.");
6DEFINE_bool(gpu, true, "Master switch for running GPU-bound work.");
7
8DECLARE_bool(dryRun);
9
10namespace DM {
11
12Task::Task(Reporter* reporter, TaskRunner* taskRunner)
13    : fReporter(reporter)
14    , fTaskRunner(taskRunner)
15    , fDepth(0) {
16    fReporter->taskCreated();
17}
18
19Task::Task(const Task& parent)
20    : fReporter(parent.fReporter)
21    , fTaskRunner(parent.fTaskRunner)
22    , fDepth(parent.depth() + 1) {
23    fReporter->taskCreated();
24}
25
26Task::~Task() {
27    fReporter->taskDestroyed();
28}
29
30void Task::fail(const char* msg) {
31    SkString failure(this->name());
32    if (msg) {
33        failure.appendf(": %s", msg);
34    }
35    fReporter->fail(failure);
36}
37
38void Task::start() {
39    fStart = SkTime::GetMSecs();
40}
41
42void Task::finish() {
43    fReporter->printStatus(this->name(), SkTime::GetMSecs() - fStart);
44}
45
46void Task::spawnChildNext(CpuTask* task) {
47    fTaskRunner->addNext(task);
48}
49
50CpuTask::CpuTask(Reporter* reporter, TaskRunner* taskRunner) : Task(reporter, taskRunner) {}
51CpuTask::CpuTask(const Task& parent) : Task(parent) {}
52
53void CpuTask::run() {
54    if (FLAGS_cpu && !this->shouldSkip()) {
55        this->start();
56        if (!FLAGS_dryRun) this->draw();
57        this->finish();
58    }
59    SkDELETE(this);
60}
61
62void CpuTask::spawnChild(CpuTask* task) {
63    // Run children serially on this (CPU) thread.  This tends to save RAM and is usually no slower.
64    // Calling spawnChildNext() is nearly equivalent, but it'd pointlessly contend on the
65    // threadpool; spawnChildNext() is most useful when you want to change threadpools.
66    task->run();
67}
68
69GpuTask::GpuTask(Reporter* reporter, TaskRunner* taskRunner) : Task(reporter, taskRunner) {}
70
71void GpuTask::run(GrContextFactory& factory) {
72    if (FLAGS_gpu && !this->shouldSkip()) {
73        this->start();
74        if (!FLAGS_dryRun) this->draw(&factory);
75        this->finish();
76    }
77    SkDELETE(this);
78}
79
80void GpuTask::spawnChild(CpuTask* task) {
81    // Really spawn a new task so it runs on the CPU threadpool instead of the GPU one we're on now.
82    // It goes on the front of the queue to minimize the time we must hold reference bitmaps in RAM.
83    this->spawnChildNext(task);
84}
85
86}  // namespace DM
87