aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2016-09-29 13:40:01 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-09-29 18:11:29 +0000
commitfa9f241a85c55c32a3fe2ae0324811de998f7a2e (patch)
tree01308fe5602180eaaf0636fa635183ce9a93a7e7
parent69e7eba6aef583eb0561019539b164d8e0eed025 (diff)
Add an enum layer of indirection for stock raster pipeline stages.
This is handy now, and becomes necessary with fancier backends: - most code can't speak the type of AVX pipeline stages, so indirection's definitely needed there; - if the pipleine is entirely composed of stock stages, these enum values become an abstract recipe that can be JITted. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2782 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Change-Id: Iedd62e99ce39e94cf3e6ffc78c428f0ccc182342 Reviewed-on: https://skia-review.googlesource.com/2782 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r--bench/SkRasterPipelineBench.cpp10
-rw-r--r--src/core/SkOpts.cpp68
-rw-r--r--src/core/SkOpts.h20
-rw-r--r--src/core/SkRasterPipeline.cpp5
-rw-r--r--src/core/SkRasterPipeline.h27
-rw-r--r--src/core/SkRasterPipelineBlitter.cpp22
-rw-r--r--src/opts/SkOpts_sse41.cpp36
-rw-r--r--src/opts/SkRasterPipeline_opts.h20
8 files changed, 121 insertions, 87 deletions
diff --git a/bench/SkRasterPipelineBench.cpp b/bench/SkRasterPipelineBench.cpp
index 17a93da549..a5e53471cd 100644
--- a/bench/SkRasterPipelineBench.cpp
+++ b/bench/SkRasterPipelineBench.cpp
@@ -30,11 +30,11 @@ public:
void onDraw(int loops, SkCanvas*) override {
while (loops --> 0) {
SkRasterPipeline p;
- p.append(SkOpts::load_s_srgb_body, SkOpts::load_s_srgb_tail, src);
- p.append(SkOpts::scale_u8_body, SkOpts::scale_u8_tail, mask);
- p.append(SkOpts::load_d_srgb_body, SkOpts::load_d_srgb_tail, dst);
- p.append(SkOpts::srcover);
- p.append(SkOpts::store_srgb_body, SkOpts::store_srgb_tail, dst);
+ p.append(SkRasterPipeline::load_s_srgb, src);
+ p.append(SkRasterPipeline:: scale_u8, mask);
+ p.append(SkRasterPipeline::load_d_srgb, dst);
+ p.append(SkRasterPipeline:: srcover);
+ p.append(SkRasterPipeline:: store_srgb, dst);
p.run(N);
}
}
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
index 1f686ff56b..5cac8ec3ca 100644
--- a/src/core/SkOpts.cpp
+++ b/src/core/SkOpts.cpp
@@ -90,37 +90,57 @@ namespace SkOpts {
DEFINE_DEFAULT(hash_fn);
#undef DEFINE_DEFAULT
-// Stages that are not sensitive to the tail parameter can be represented by one function.
-#define DEFINE_DEFAULT(stage, kCallNext) \
- decltype(stage) stage = body<SK_OPTS_NS::stage, kCallNext>
+ // TODO: might be nice to only create one instance of tail-insensitive stages.
- DEFINE_DEFAULT(srcover, true);
- DEFINE_DEFAULT(constant_color, true);
- DEFINE_DEFAULT(lerp_constant_float, true);
-#undef DEFINE_DEFAULT
+ SkRasterPipeline::Fn stages_4[] = {
+ stage_4<SK_OPTS_NS::store_565 , false>,
+ stage_4<SK_OPTS_NS::store_srgb, false>,
+ stage_4<SK_OPTS_NS::store_f16 , false>,
-// Stages that are sensitive to the tail parameter need two versions, _body and _tail.
-#define DEFINE_DEFAULT(stage, kCallNext) \
- decltype(stage##_body) stage##_body = body<SK_OPTS_NS::stage, kCallNext>; \
- decltype(stage##_tail) stage##_tail = tail<SK_OPTS_NS::stage, kCallNext>
+ stage_4<SK_OPTS_NS::load_s_565 , true>,
+ stage_4<SK_OPTS_NS::load_s_srgb, true>,
+ stage_4<SK_OPTS_NS::load_s_f16 , true>,
- DEFINE_DEFAULT(load_d_srgb, true);
- DEFINE_DEFAULT(load_s_srgb, true);
- DEFINE_DEFAULT( store_srgb, false);
+ stage_4<SK_OPTS_NS::load_d_565 , true>,
+ stage_4<SK_OPTS_NS::load_d_srgb, true>,
+ stage_4<SK_OPTS_NS::load_d_f16 , true>,
- DEFINE_DEFAULT(load_d_f16, true);
- DEFINE_DEFAULT(load_s_f16, true);
- DEFINE_DEFAULT( store_f16, false);
+ stage_4<SK_OPTS_NS::scale_u8, true>,
- DEFINE_DEFAULT(load_d_565, true);
- DEFINE_DEFAULT(load_s_565, true);
- DEFINE_DEFAULT( store_565, false);
+ stage_4<SK_OPTS_NS::lerp_u8 , true>,
+ stage_4<SK_OPTS_NS::lerp_565 , true>,
+ stage_4<SK_OPTS_NS::lerp_constant_float, true>,
- DEFINE_DEFAULT(scale_u8, true);
+ stage_4<SK_OPTS_NS::constant_color, true>,
- DEFINE_DEFAULT(lerp_u8, true);
- DEFINE_DEFAULT(lerp_565, true);
-#undef DEFINE_DEFAULT
+ stage_4<SK_OPTS_NS::srcover, true>,
+ };
+ static_assert(SK_ARRAY_COUNT(stages_4) == SkRasterPipeline::kNumStockStages, "");
+
+ SkRasterPipeline::Fn stages_1_3[] = {
+ stage_1_3<SK_OPTS_NS::store_565 , false>,
+ stage_1_3<SK_OPTS_NS::store_srgb, false>,
+ stage_1_3<SK_OPTS_NS::store_f16 , false>,
+
+ stage_1_3<SK_OPTS_NS::load_s_565 , true>,
+ stage_1_3<SK_OPTS_NS::load_s_srgb, true>,
+ stage_1_3<SK_OPTS_NS::load_s_f16 , true>,
+
+ stage_1_3<SK_OPTS_NS::load_d_565 , true>,
+ stage_1_3<SK_OPTS_NS::load_d_srgb, true>,
+ stage_1_3<SK_OPTS_NS::load_d_f16 , true>,
+
+ stage_1_3<SK_OPTS_NS::scale_u8, true>,
+
+ stage_1_3<SK_OPTS_NS::lerp_u8 , true>,
+ stage_1_3<SK_OPTS_NS::lerp_565 , true>,
+ stage_1_3<SK_OPTS_NS::lerp_constant_float, true>,
+
+ stage_1_3<SK_OPTS_NS::constant_color, true>,
+
+ stage_1_3<SK_OPTS_NS::srcover, true>,
+ };
+ static_assert(SK_ARRAY_COUNT(stages_1_3) == SkRasterPipeline::kNumStockStages, "");
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
void Init_ssse3();
diff --git a/src/core/SkOpts.h b/src/core/SkOpts.h
index c310a79aa0..50de9c45e2 100644
--- a/src/core/SkOpts.h
+++ b/src/core/SkOpts.h
@@ -73,24 +73,8 @@ namespace SkOpts {
return hash_fn(data, bytes, seed);
}
- // Each of the SkRasterPipeline::Fn's lists its context pointer type in the comments.
-
- extern SkRasterPipeline::Fn srcover, // (none)
- constant_color, // const SkPM4f*
- lerp_constant_float; // const float*, in [0,1]
-
- extern SkRasterPipeline::Fn load_d_srgb_body, load_d_srgb_tail, // const uint32_t*
- load_s_srgb_body, load_s_srgb_tail, // const uint32_t*
- store_srgb_body, store_srgb_tail, // uint32_t*
- load_d_f16_body, load_d_f16_tail, // const uint64_t*
- load_s_f16_body, load_s_f16_tail, // const uint64_t*
- store_f16_body, store_f16_tail, // uint64_t*
- load_d_565_body, load_d_565_tail, // const uint16_t*
- load_s_565_body, load_s_565_tail, // const uint16_t*
- store_565_body, store_565_tail, // uint16_t*
- scale_u8_body, scale_u8_tail, // const uint8_t*
- lerp_u8_body, lerp_u8_tail, // const uint8_t*
- lerp_565_body, lerp_565_tail; // const uint16_t*
+ extern SkRasterPipeline::Fn stages_4 [SkRasterPipeline::kNumStockStages],
+ stages_1_3[SkRasterPipeline::kNumStockStages];
}
#endif//SkOpts_DEFINED
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index 71c993dfb8..fd909a1205 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkOpts.h"
#include "SkRasterPipeline.h"
SkRasterPipeline::SkRasterPipeline() {}
@@ -23,6 +24,10 @@ void SkRasterPipeline::append(SkRasterPipeline::Fn body,
fTail.push_back({ &JustReturn, const_cast<void*>(ctx) });
}
+void SkRasterPipeline::append(StockStage stage, const void* ctx) {
+ this->append(SkOpts::stages_4[stage], SkOpts::stages_1_3[stage], ctx);
+}
+
void SkRasterPipeline::extend(const SkRasterPipeline& src) {
SkASSERT(src.fBody.count() == src.fTail.count());
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 9f4dcb34da..789257e0e2 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -88,6 +88,33 @@ public:
void append(Fn body, Fn tail, const void* ctx = nullptr);
void append(Fn fn, const void* ctx = nullptr) { this->append(fn, fn, ctx); }
+ enum StockStage {
+ 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,
+
+ srcover,
+
+ kNumStockStages,
+ };
+ void append(StockStage, const void* ctx=nullptr);
+
// Append all stages to this pipeline.
void extend(const SkRasterPipeline&);
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 2ada336cd8..1e8dcf59e0 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -102,10 +102,10 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
color.premul());
if (!paint.getShader()) {
- blitter->fShader.append(SkOpts::constant_color, &blitter->fPaintColor);
+ blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor);
}
if (!paint.getXfermode()) {
- blitter->fXfermode.append(SkOpts::srcover);
+ blitter->fXfermode.append(SkRasterPipeline::srcover);
}
return blitter;
@@ -117,14 +117,14 @@ void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst
switch (fDst.info().colorType()) {
case kN32_SkColorType:
if (fDst.info().gammaCloseToSRGB()) {
- p->append(SkOpts::load_d_srgb_body, SkOpts::load_d_srgb_tail, dst);
+ p->append(SkRasterPipeline::load_d_srgb, dst);
}
break;
case kRGBA_F16_SkColorType:
- p->append(SkOpts::load_d_f16_body, SkOpts::load_d_f16_tail, dst);
+ p->append(SkRasterPipeline::load_d_f16, dst);
break;
case kRGB_565_SkColorType:
- p->append(SkOpts::load_d_565_body, SkOpts::load_d_565_tail, dst);
+ p->append(SkRasterPipeline::load_d_565, dst);
break;
default: break;
}
@@ -136,14 +136,14 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const
switch (fDst.info().colorType()) {
case kN32_SkColorType:
if (fDst.info().gammaCloseToSRGB()) {
- p->append(SkOpts::store_srgb_body, SkOpts::store_srgb_tail, dst);
+ p->append(SkRasterPipeline::store_srgb, dst);
}
break;
case kRGBA_F16_SkColorType:
- p->append(SkOpts::store_f16_body, SkOpts::store_f16_tail, dst);
+ p->append(SkRasterPipeline::store_f16, dst);
break;
case kRGB_565_SkColorType:
- p->append(SkOpts::store_565_body, SkOpts::store_565_tail, dst);
+ p->append(SkRasterPipeline::store_565, dst);
break;
default: break;
}
@@ -171,7 +171,7 @@ void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const
p.extend(fColorFilter);
this->append_load_d(&p, dst);
p.extend(fXfermode);
- p.append(SkOpts::lerp_constant_float, &coverage);
+ p.append(SkRasterPipeline::lerp_constant_float, &coverage);
this->append_store(&p, dst);
for (int16_t run = *runs; run > 0; run = *runs) {
@@ -201,10 +201,10 @@ void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip)
p.extend(fXfermode);
switch (mask.fFormat) {
case SkMask::kA8_Format:
- p.append(SkOpts::lerp_u8_body, SkOpts::lerp_u8_tail, mask.getAddr8(x,y)-x);
+ p.append(SkRasterPipeline::lerp_u8, mask.getAddr8(x,y)-x);
break;
case SkMask::kLCD16_Format:
- p.append(SkOpts::lerp_565_body, SkOpts::lerp_565_tail, mask.getAddrLCD16(x,y)-x);
+ p.append(SkRasterPipeline::lerp_565, mask.getAddrLCD16(x,y)-x);
break;
default: break;
}
diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp
index e4e3246780..0509b91fdf 100644
--- a/src/opts/SkOpts_sse41.cpp
+++ b/src/opts/SkOpts_sse41.cpp
@@ -22,33 +22,31 @@ namespace SkOpts {
blit_row_s32a_opaque = sse41::blit_row_s32a_opaque;
#define STAGE(stage, kCallNext) \
- stage = body<SK_OPTS_NS::stage, kCallNext>
+ stages_4 [SkRasterPipeline::stage] = stage_4 <SK_OPTS_NS::stage, kCallNext>; \
+ stages_1_3[SkRasterPipeline::stage] = stage_1_3<SK_OPTS_NS::stage, kCallNext>
- STAGE(srcover, true);
- STAGE(constant_color, true);
- STAGE(lerp_constant_float, true);
- #undef STAGE
+ STAGE(store_565 , false);
+ STAGE(store_srgb, false);
+ STAGE(store_f16 , false);
- #define STAGE(stage, kCallNext) \
- stage##_body = body<SK_OPTS_NS::stage, kCallNext>; \
- stage##_tail = tail<SK_OPTS_NS::stage, kCallNext>
+ STAGE(load_s_565 , true);
+ STAGE(load_s_srgb, true);
+ STAGE(load_s_f16 , true);
+ STAGE(load_d_565 , true);
STAGE(load_d_srgb, true);
- STAGE(load_s_srgb, true);
- STAGE( store_srgb, false);
+ STAGE(load_d_f16 , true);
- STAGE(load_d_f16, true);
- STAGE(load_s_f16, true);
- STAGE( store_f16, false);
+ STAGE(scale_u8, true);
- STAGE(load_d_565, true);
- STAGE(load_s_565, true);
- STAGE( store_565, false);
+ STAGE(lerp_u8 , true);
+ STAGE(lerp_565 , true);
+ STAGE(lerp_constant_float, true);
- STAGE(scale_u8, true);
+ STAGE(constant_color, true);
- STAGE(lerp_u8, true);
- STAGE(lerp_565, true);
+ STAGE(srcover, true);
#undef STAGE
+
}
}
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index 70c4d0c225..fe0fde8139 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -25,26 +25,26 @@ using Kernel_Sk4f = void(void*, size_t, size_t, Sk4f&, Sk4f&, Sk4f&, Sk4f&,
template <Kernel_Sk4f kernel, bool kCallNext>
-static inline void SK_VECTORCALL body(SkRasterPipeline::Stage* st, size_t x, size_t t,
- Sk4f r, Sk4f g, Sk4f b, Sk4f a,
- Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) {
+static inline void SK_VECTORCALL stage_4(SkRasterPipeline::Stage* st, size_t x, size_t tail,
+ Sk4f r, Sk4f g, Sk4f b, Sk4f a,
+ Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) {
// Passing 0 lets the optimizer completely drop any "if (tail) {...}" code in kernel.
kernel(st->ctx<void*>(), x,0, r,g,b,a, dr,dg,db,da);
if (kCallNext) {
- st->next(x,t, r,g,b,a, dr,dg,db,da); // It's faster to pass t here than 0.
+ st->next(x,tail, r,g,b,a, dr,dg,db,da); // It's faster to pass t here than 0.
}
}
template <Kernel_Sk4f kernel, bool kCallNext>
-static inline void SK_VECTORCALL tail(SkRasterPipeline::Stage* st, size_t x, size_t t,
- Sk4f r, Sk4f g, Sk4f b, Sk4f a,
- Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) {
+static inline void SK_VECTORCALL stage_1_3(SkRasterPipeline::Stage* st, size_t x, size_t tail,
+ Sk4f r, Sk4f g, Sk4f b, Sk4f a,
+ Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) {
#if defined(__clang__)
- __builtin_assume(t > 0); // This flourish lets Clang compile away any tail==0 code.
+ __builtin_assume(tail > 0); // This flourish lets Clang compile away any tail==0 code.
#endif
- kernel(st->ctx<void*>(), x,t, r,g,b,a, dr,dg,db,da);
+ kernel(st->ctx<void*>(), x,tail, r,g,b,a, dr,dg,db,da);
if (kCallNext) {
- st->next(x,t, r,g,b,a, dr,dg,db,da);
+ st->next(x,tail, r,g,b,a, dr,dg,db,da);
}
}