aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2016-10-25 10:27:33 -0400
committerGravatar Mike Klein <mtklein@chromium.org>2016-10-25 17:30:38 +0000
commitaebfb45104eeb6dab5dbbedda13c2eaa7b7f7868 (patch)
tree7dcbf9bf86bd1b9fad0048dccbabb11e47a1d3fb /src/core
parentcc813ae9a0afe4259f12b655d9336662a6e2c100 (diff)
Move SkRasterPipeline further into SkOpts.
The portable code now becomes entirely focused on enum+ptr descriptions, leaving the concrete implementation of the pipeline to SkOpts::run_pipeline(). As implemented, the concrete implementation is basically the same, with a little more type safety. Speed is essentially unchanged on my laptop, and that's having run_pipeline() rebuild its concrete state every call. There's room for improvement there if we split this into a compile_pipeline() / run_pipeline() sort of thing, which is my next planned CL. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3920 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Change-Id: Ie4c554f51040426de7c5c144afa5d9d9d8938012 Reviewed-on: https://skia-review.googlesource.com/3920 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkOpts.cpp102
-rw-r--r--src/core/SkOpts.h8
-rw-r--r--src/core/SkRasterPipeline.cpp36
-rw-r--r--src/core/SkRasterPipeline.h98
4 files changed, 40 insertions, 204 deletions
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
index 16389484b4..c082b160ee 100644
--- a/src/core/SkOpts.cpp
+++ b/src/core/SkOpts.cpp
@@ -92,108 +92,6 @@ namespace SkOpts {
DEFINE_DEFAULT(run_pipeline);
#undef DEFINE_DEFAULT
- SkOpts::VoidFn body[] = {
- (SkOpts::VoidFn)SK_OPTS_NS::just_return,
- (SkOpts::VoidFn)SK_OPTS_NS::swap_src_dst,
-
- (SkOpts::VoidFn)SK_OPTS_NS::store_565,
- (SkOpts::VoidFn)SK_OPTS_NS::store_srgb,
- (SkOpts::VoidFn)SK_OPTS_NS::store_f16,
-
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_565,
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_srgb,
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_f16,
-
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_565,
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_srgb,
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_f16,
-
- (SkOpts::VoidFn)SK_OPTS_NS::scale_u8,
-
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_u8,
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_565,
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_constant_float,
-
- (SkOpts::VoidFn)SK_OPTS_NS::constant_color,
-
- (SkOpts::VoidFn)SK_OPTS_NS::dst,
- (SkOpts::VoidFn)SK_OPTS_NS::dstatop,
- (SkOpts::VoidFn)SK_OPTS_NS::dstin,
- (SkOpts::VoidFn)SK_OPTS_NS::dstout,
- (SkOpts::VoidFn)SK_OPTS_NS::dstover,
- (SkOpts::VoidFn)SK_OPTS_NS::srcatop,
- (SkOpts::VoidFn)SK_OPTS_NS::srcin,
- (SkOpts::VoidFn)SK_OPTS_NS::srcout,
- (SkOpts::VoidFn)SK_OPTS_NS::srcover,
- (SkOpts::VoidFn)SK_OPTS_NS::clear,
- (SkOpts::VoidFn)SK_OPTS_NS::modulate,
- (SkOpts::VoidFn)SK_OPTS_NS::multiply,
- (SkOpts::VoidFn)SK_OPTS_NS::plus_,
- (SkOpts::VoidFn)SK_OPTS_NS::screen,
- (SkOpts::VoidFn)SK_OPTS_NS::xor_,
- (SkOpts::VoidFn)SK_OPTS_NS::colorburn,
- (SkOpts::VoidFn)SK_OPTS_NS::colordodge,
- (SkOpts::VoidFn)SK_OPTS_NS::darken,
- (SkOpts::VoidFn)SK_OPTS_NS::difference,
- (SkOpts::VoidFn)SK_OPTS_NS::exclusion,
- (SkOpts::VoidFn)SK_OPTS_NS::hardlight,
- (SkOpts::VoidFn)SK_OPTS_NS::lighten,
- (SkOpts::VoidFn)SK_OPTS_NS::overlay,
- (SkOpts::VoidFn)SK_OPTS_NS::softlight,
- };
- static_assert(SK_ARRAY_COUNT(body) == SkRasterPipeline::kNumStockStages, "");
-
- SkOpts::VoidFn tail[] = {
- (SkOpts::VoidFn)SK_OPTS_NS::just_return_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::swap_src_dst_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::store_565_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::store_srgb_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::store_f16_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_565_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_srgb_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::load_s_f16_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_565_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_srgb_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::load_d_f16_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::scale_u8_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_u8_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_565_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::lerp_constant_float_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::constant_color_tail,
-
- (SkOpts::VoidFn)SK_OPTS_NS::dst_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::dstatop_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::dstin_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::dstout_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::dstover_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::srcatop_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::srcin_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::srcout_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::srcover_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::clear_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::modulate_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::multiply_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::plus__tail,
- (SkOpts::VoidFn)SK_OPTS_NS::screen_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::xor__tail,
- (SkOpts::VoidFn)SK_OPTS_NS::colorburn_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::colordodge_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::darken_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::difference_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::exclusion_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::hardlight_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::lighten_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::overlay_tail,
- (SkOpts::VoidFn)SK_OPTS_NS::softlight_tail,
- };
- static_assert(SK_ARRAY_COUNT(tail) == SkRasterPipeline::kNumStockStages, "");
-
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
void Init_ssse3();
void Init_sse41();
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index 4685d86691..7283030068 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -73,13 +73,7 @@ namespace SkOpts {
return hash_fn(data, bytes, seed);
}
- // SkRasterPipeline::Fn has different types in different files (notably, in SkOpts_hsw.cpp
- // they're all in terms of Sk8f.) We store them with a type everyone can agree on, void(*)().
- using VoidFn = void(*)();
- extern VoidFn body[SkRasterPipeline::kNumStockStages],
- tail[SkRasterPipeline::kNumStockStages];
- extern void (*run_pipeline)(size_t, size_t, void(*)(), SkRasterPipeline::Stage*,
- void(*)(), SkRasterPipeline::Stage*);
+ extern void (*run_pipeline)(size_t, size_t, const SkRasterPipeline::Stage*, int);
}
#endif//SkOpts_DEFINED
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index bc7feaccc7..707a33ae6f 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -8,40 +8,20 @@
#include "SkOpts.h"
#include "SkRasterPipeline.h"
-SkRasterPipeline::SkRasterPipeline() {
- fBodyStart = SkOpts::body[just_return];
- fTailStart = SkOpts::tail[just_return];
-}
-
-void SkRasterPipeline::append(void (*body)(), void (*tail)(), void* ctx) {
- // Each stage holds its own context and the next function to call.
- // So the pipeline itself has to hold onto the first function that starts the pipeline.
- (fBody.empty() ? fBodyStart : fBody.back().fNext) = body;
- (fTail.empty() ? fTailStart : fTail.back().fNext) = tail;
-
- // Each last stage starts with its next function set to JustReturn as a safety net.
- // It'll be overwritten by the next call to append().
- fBody.push_back({ SkOpts::body[just_return], ctx });
- fTail.push_back({ SkOpts::tail[just_return], ctx });
-}
+SkRasterPipeline::SkRasterPipeline() {}
void SkRasterPipeline::append(StockStage stage, void* ctx) {
- this->append(SkOpts::body[stage], SkOpts::tail[stage], ctx);
+ SkASSERT(fNum < (int)SK_ARRAY_COUNT(fStages));
+ fStages[fNum++] = { stage, ctx };
}
void SkRasterPipeline::extend(const SkRasterPipeline& src) {
- SkASSERT(src.fBody.count() == src.fTail.count());
-
- auto body = src.fBodyStart,
- tail = src.fTailStart;
- for (int i = 0; i < src.fBody.count(); i++) {
- SkASSERT(src.fBody[i].fCtx == src.fTail[i].fCtx);
- this->append(body, tail, src.fBody[i].fCtx);
- body = src.fBody[i].fNext;
- tail = src.fTail[i].fNext;
+ for (int i = 0; i < src.fNum; i++) {
+ const Stage& s = src.fStages[i];
+ this->append(s.stage, s.ctx);
}
}
-void SkRasterPipeline::run(size_t x, size_t n) {
- SkOpts::run_pipeline(x,n, fBodyStart,fBody.begin(), fTailStart,fTail.begin());
+void SkRasterPipeline::run(size_t x, size_t n) const {
+ SkOpts::run_pipeline(x,n, fStages, fNum);
}
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 525a8dbe72..60279dd168 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -53,72 +53,31 @@
// TODO: There may be a better place to stuff tail, e.g. in the bottom alignment bits of
// the Stage*. This mostly matters on 64-bit Windows where every register is precious.
+#define SK_RASTER_PIPELINE_STAGES(M) \
+ M(swap_src_dst) M(constant_color) \
+ M(load_s_565) M(load_d_565) M(store_565) \
+ M(load_s_srgb) M(load_d_srgb) M(store_srgb) \
+ M(load_s_f16) M(load_d_f16) M(store_f16) \
+ M(scale_u8) \
+ M(lerp_u8) M(lerp_565) M(lerp_constant_float) \
+ M(dst) \
+ M(dstatop) M(dstin) M(dstout) M(dstover) \
+ M(srcatop) M(srcin) M(srcout) M(srcover) \
+ M(clear) M(modulate) M(multiply) M(plus_) M(screen) M(xor_) \
+ M(colorburn) M(colordodge) M(darken) M(difference) \
+ M(exclusion) M(hardlight) M(lighten) M(overlay) M(softlight)
+
class SkRasterPipeline {
public:
- struct Stage {
- // It makes next() a good bit cheaper if we hold the next function to call here,
- // rather than logically simpler choice of the function implementing this stage.
- void (*fNext)();
- void* fCtx;
- };
+ // No pipeline may be more than kMaxStages long.
+ static const int kMaxStages = 32;
SkRasterPipeline();
- // Run the pipeline constructed with append(), walking x through [x,x+n),
- // generally in 4-pixel steps, with perhaps one jagged tail step.
- void run(size_t x, size_t n);
- void run(size_t n) { this->run(0, n); }
-
enum StockStage {
- just_return,
- swap_src_dst,
-
- store_565,
- store_srgb,
- store_f16,
-
- load_s_565,
- load_s_srgb,
- load_s_f16,
-
- load_d_565,
- load_d_srgb,
- load_d_f16,
-
- scale_u8,
-
- lerp_u8,
- lerp_565,
- lerp_constant_float,
-
- constant_color,
-
- dst,
- dstatop,
- dstin,
- dstout,
- dstover,
- srcatop,
- srcin,
- srcout,
- srcover,
- clear,
- modulate,
- multiply,
- plus_,
- screen,
- xor_,
- colorburn,
- colordodge,
- darken,
- difference,
- exclusion,
- hardlight,
- lighten,
- overlay,
- softlight,
-
- kNumStockStages,
+ #define M(stage) stage,
+ SK_RASTER_PIPELINE_STAGES(M)
+ #undef M
};
void append(StockStage, void* = nullptr);
void append(StockStage stage, const void* ctx) { this->append(stage, const_cast<void*>(ctx)); }
@@ -126,15 +85,20 @@ public:
// Append all stages to this pipeline.
void extend(const SkRasterPipeline&);
-private:
- using Stages = SkSTArray<10, Stage, /*MEM_COPY=*/true>;
+ // Run the pipeline constructed with append(), walking x through [x,x+n),
+ // generally in 4-pixel steps, with perhaps one jagged tail step.
+ void run(size_t x, size_t n) const;
+ void run(size_t n) const { this->run(0, n); }
- void append(void (*body)(), void (*tail)(), void*);
- Stages fBody,
- fTail;
- void (*fBodyStart)() = nullptr;
- void (*fTailStart)() = nullptr;
+ struct Stage {
+ StockStage stage;
+ void* ctx;
+ };
+
+private:
+ int fNum = 0;
+ Stage fStages[kMaxStages];
};
#endif//SkRasterPipeline_DEFINED