SkRasterPipeline.cpp revision c789b61167dd98efc3c3bfcf9673eef24c2e57f4
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkOpts.h"
9#include "SkRasterPipeline.h"
10
11SkRasterPipeline::SkRasterPipeline() {}
12
13void SkRasterPipeline::append(StockStage stage, void* ctx) {
14#ifdef SK_DEBUG
15    if (fNum == (int)SK_ARRAY_COUNT(fStages)) {
16        this->dump();
17    }
18#endif
19    SkASSERT(fNum < (int)SK_ARRAY_COUNT(fStages));
20    fStages[fNum++] = { stage, ctx };
21}
22
23void SkRasterPipeline::extend(const SkRasterPipeline& src) {
24    for (int i = 0; i < src.fNum; i++) {
25        const Stage& s = src.fStages[i];
26        this->append(s.stage, s.ctx);
27    }
28}
29
30void SkRasterPipeline::run(size_t x, size_t y, size_t n) const {
31    SkOpts::run_pipeline(x,y,n, fStages, fNum);
32}
33
34std::function<void(size_t, size_t, size_t)> SkRasterPipeline::compile() const {
35    return SkOpts::compile_pipeline(fStages, fNum);
36}
37
38static bool invariant_in_x(const SkRasterPipeline::Stage& st) {
39    if (st.ctx == nullptr) {
40        // If a stage doesn't have a context pointer, it can't really do anything with x.
41        return true;
42    }
43
44    // This would be a lot more compact as a blacklist (the loads, the stores, the gathers),
45    // but it's safer to write as a whitelist.  If we get it wrong this way, not a big deal.
46    switch (st.stage) {
47        default: return false;
48
49        case SkRasterPipeline::trace:
50        case SkRasterPipeline::set_rgb:
51        case SkRasterPipeline::constant_color:
52        case SkRasterPipeline::scale_constant_float:
53        case SkRasterPipeline::lerp_constant_float:
54        case SkRasterPipeline::matrix_2x3:
55        case SkRasterPipeline::matrix_3x4:
56        case SkRasterPipeline::matrix_4x5:
57        case SkRasterPipeline::matrix_perspective:
58        case SkRasterPipeline::parametric_r:
59        case SkRasterPipeline::parametric_g:
60        case SkRasterPipeline::parametric_b:
61        case SkRasterPipeline::table_r:
62        case SkRasterPipeline::table_g:
63        case SkRasterPipeline::table_b:
64        case SkRasterPipeline::color_lookup_table:
65        case SkRasterPipeline::lab_to_xyz:
66        case SkRasterPipeline::clamp_x:
67        case SkRasterPipeline::mirror_x:
68        case SkRasterPipeline::repeat_x:
69        case SkRasterPipeline::clamp_y:
70        case SkRasterPipeline::mirror_y:
71        case SkRasterPipeline::repeat_y:
72        case SkRasterPipeline::top_left:
73        case SkRasterPipeline::top_right:
74        case SkRasterPipeline::bottom_left:
75        case SkRasterPipeline::bottom_right:
76        case SkRasterPipeline::accumulate:
77            SkASSERT(st.ctx != nullptr);
78            return true;
79    }
80    return false;
81}
82
83void SkRasterPipeline::dump() const {
84    SkDebugf("SkRasterPipeline, %d stages\n", fNum);
85    bool in_constant_run = false;
86    for (int i = 0; i < fNum; i++) {
87        const char* name = "";
88        switch (fStages[i].stage) {
89        #define M(x) case x: name = #x; break;
90            SK_RASTER_PIPELINE_STAGES(M)
91        #undef M
92        }
93
94        char mark = ' ';
95        if (fStages[i].stage == SkRasterPipeline::constant_color) {
96            mark = '*';
97            in_constant_run = true;
98        } else if (in_constant_run && invariant_in_x(fStages[i])) {
99            mark = '|';
100        } else {
101            mark = ' ';
102            in_constant_run = false;
103        }
104        SkDebugf("\t%c %s\n", mark, name);
105    }
106    SkDebugf("\n");
107}
108