diff options
author | 2016-11-04 13:20:07 -0700 | |
---|---|---|
committer | 2016-11-04 13:20:07 -0700 | |
commit | a4a4488a4c3f16758f7e2b050168fe8d2f3b2a4d (patch) | |
tree | 207759030d7ac86a60c6cfba1d4a95de15cec5c0 | |
parent | d8db392be9dd1887df04b10b5670991d6b098c17 (diff) |
skrpb: evaluate color filters for constant shaders once.
The simplest thing to do here is just run shader+color filter pipeline at
construction time to create a new constant color shader (replacing the paint
color).
This reduces a pipeline like:
- constant_color (paint color)
- matrix_4x5
- clamp_a
- load_d_foo, xfermode, lerp, store_foo
to
- constant_color (paint color -> matrix_4x5 -> clamp_a)
- load_d_foo, xfermode, lerp, store_foo
To implement this all, we add a new store_f32 stage that writes SkPM4f, and
finally get around to implementing Sk8f::Store4() (store while reinterlacing).
Sk4f::Store4() already exists for both SSE and NEON.
Next step: reduce simple constant_color -> store pipelines (src mode, full
coverage) into non-pipeline memsets.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2480823002
Review-Url: https://codereview.chromium.org/2480823002
-rw-r--r-- | src/core/SkRasterPipeline.h | 2 | ||||
-rw-r--r-- | src/core/SkRasterPipelineBlitter.cpp | 85 | ||||
-rw-r--r-- | src/opts/SkNx_sse.h | 31 | ||||
-rw-r--r-- | src/opts/SkRasterPipeline_opts.h | 24 |
4 files changed, 102 insertions, 40 deletions
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h index 0a3cddbcb9..bf886cf43c 100644 --- a/src/core/SkRasterPipeline.h +++ b/src/core/SkRasterPipeline.h @@ -56,7 +56,7 @@ #define SK_RASTER_PIPELINE_STAGES(M) \ M(swap_src_dst) M(clamp_0) M(clamp_a) M(unpremul) M(premul) \ - M(constant_color) \ + M(constant_color) M(store_f32) \ 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) \ diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 31c188e4f9..8f9922d47e 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -20,12 +20,8 @@ class SkRasterPipelineBlitter : public SkBlitter { public: static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocator*); - SkRasterPipelineBlitter(SkPixmap dst, - SkRasterPipeline shader, - SkBlendMode blend, - SkPM4f paintColor) + SkRasterPipelineBlitter(SkPixmap dst, SkBlendMode blend, SkPM4f paintColor) : fDst(dst) - , fShader(shader) , fBlend(blend) , fPaintColor(paintColor) {} @@ -45,9 +41,9 @@ private: void maybe_clamp (SkRasterPipeline*) const; SkPixmap fDst; - SkRasterPipeline fShader; SkBlendMode fBlend; SkPM4f fPaintColor; + SkRasterPipeline fShader; // These functions are compiled lazily when first used. std::function<void(size_t, size_t)> fBlitH = nullptr, @@ -84,52 +80,69 @@ static bool append_effect_stages(const Effect* effect, SkRasterPipeline* pipelin return !effect || effect->appendStages(pipeline); } +static SkPM4f paint_color(const SkPixmap& dst, const SkPaint& paint) { + auto paintColor = paint.getColor(); + SkColor4f color; + if (dst.info().colorSpace()) { + color = SkColor4f::FromColor(paintColor); + // TODO: transform from sRGB to dst gamut. + } else { + swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store(&color); + } + return color.premul(); +} SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, const SkPaint& paint, SkTBlitterAllocator* alloc) { - if (!supported(dst.info())) { + auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst, + paint.getBlendMode(), + paint_color(dst, paint)); + SkBlendMode* blend = &blitter->fBlend; + SkPM4f* paintColor = &blitter->fPaintColor; + SkRasterPipeline* pipeline = &blitter->fShader; + + SkShader* shader = paint.getShader(); + SkColorFilter* colorFilter = paint.getColorFilter(); + + // TODO: all temporary + if (!supported(dst.info()) || shader || !SkBlendMode_AppendStages(*blend)) { + alloc->freeLast(); return nullptr; } - if (paint.getShader()) { - return nullptr; // TODO: need to work out how shaders and their contexts work - } - SkBlendMode blend = paint.getBlendMode(); - if (!SkBlendMode_AppendStages(blend)) { - return nullptr; // TODO - } - uint32_t paintColor = paint.getColor(); - bool shaderIsOpaque = (paintColor >> 24) == 0xff; - - SkRasterPipeline shader, colorFilter; - if (auto s = paint.getShader()) { - shaderIsOpaque = s->isOpaque(); + bool is_opaque, is_constant; + if (shader) { + is_opaque = shader->isOpaque(); + is_constant = false; // TODO: shader->isConstant() + // TODO: append shader stages, of course! + } else { + is_opaque = paintColor->a() == 1.0f; + is_constant = true; + pipeline->append(SkRasterPipeline::constant_color, paintColor); } - if (auto cf = paint.getColorFilter()) { - if (!cf->appendStages(&colorFilter, shaderIsOpaque)) { + + if (colorFilter) { + if (!colorFilter->appendStages(pipeline, is_opaque)) { + alloc->freeLast(); return nullptr; } - shaderIsOpaque = shaderIsOpaque && (cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); + is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); } - if (shaderIsOpaque && blend == SkBlendMode::kSrcOver) { - blend = SkBlendMode::kSrc; - } + if (is_constant) { + pipeline->append(SkRasterPipeline::store_f32, &paintColor); + pipeline->compile()(0,1); - SkColor4f color; - if (dst.info().colorSpace()) { - color = SkColor4f::FromColor(paintColor); - } else { - swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store(&color); - } + *pipeline = SkRasterPipeline(); + pipeline->append(SkRasterPipeline::constant_color, paintColor); - auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst, shader, blend, color.premul()); + is_opaque = paintColor->a() == 1.0f; + } - if (!paint.getShader()) { - blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor); + if (is_opaque && *blend == SkBlendMode::kSrcOver) { + *blend = SkBlendMode::kSrc; } - blitter->fShader.extend(colorFilter); return blitter; } diff --git a/src/opts/SkNx_sse.h b/src/opts/SkNx_sse.h index a4594115e0..a4783c6302 100644 --- a/src/opts/SkNx_sse.h +++ b/src/opts/SkNx_sse.h @@ -544,6 +544,14 @@ public: __m256i fVec; }; + // _mm256_unpack{lo,hi}_pd() auto-casting to and from __m256d. + AI static __m256 unpacklo_pd(__m256 x, __m256 y) { + return _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(x), _mm256_castps_pd(y))); + } + AI static __m256 unpackhi_pd(__m256 x, __m256 y) { + return _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(x), _mm256_castps_pd(y))); + } + template <> class SkNx<8, float> { public: @@ -560,6 +568,29 @@ public: AI static SkNx Load(const void* ptr) { return _mm256_loadu_ps((const float*)ptr); } AI void store(void* ptr) const { _mm256_storeu_ps((float*)ptr, fVec); } + AI static void Store4(void* ptr, + const SkNx& r, const SkNx& g, const SkNx& b, const SkNx& a) { + __m256 rg0145 = _mm256_unpacklo_ps(r.fVec, g.fVec), // r0 g0 r1 g1 | r4 g4 r5 g5 + rg2367 = _mm256_unpackhi_ps(r.fVec, g.fVec), // r2 ... | r6 ... + ba0145 = _mm256_unpacklo_ps(b.fVec, a.fVec), // b0 a0 b1 a1 | b4 a4 b5 a5 + ba2367 = _mm256_unpackhi_ps(b.fVec, a.fVec); // b2 ... | b6 ... + + __m256 _04 = unpacklo_pd(rg0145, ba0145), // r0 g0 b0 a0 | r4 g4 b4 a4 + _15 = unpackhi_pd(rg0145, ba0145), // r1 ... | r5 ... + _26 = unpacklo_pd(rg2367, ba2367), // r2 ... | r6 ... + _37 = unpackhi_pd(rg2367, ba2367); // r3 ... | r7 ... + + __m256 _01 = _mm256_permute2f128_ps(_04, _15, 16), // 16 == 010 000 == lo, lo + _23 = _mm256_permute2f128_ps(_26, _37, 16), + _45 = _mm256_permute2f128_ps(_04, _15, 25), // 25 == 011 001 == hi, hi + _67 = _mm256_permute2f128_ps(_26, _37, 25); + + _mm256_storeu_ps((float*)ptr + 0*8, _01); + _mm256_storeu_ps((float*)ptr + 1*8, _23); + _mm256_storeu_ps((float*)ptr + 2*8, _45); + _mm256_storeu_ps((float*)ptr + 3*8, _67); + } + AI SkNx operator+(const SkNx& o) const { return _mm256_add_ps(fVec, o.fVec); } AI SkNx operator-(const SkNx& o) const { return _mm256_sub_ps(fVec, o.fVec); } AI SkNx operator*(const SkNx& o) const { return _mm256_mul_ps(fVec, o.fVec); } diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h index bd42632b4b..155558e776 100644 --- a/src/opts/SkRasterPipeline_opts.h +++ b/src/opts/SkRasterPipeline_opts.h @@ -23,9 +23,9 @@ namespace { static constexpr int N = 4; #endif -using SkNf = SkNx<N, float>; -using SkNi = SkNx<N, int>; -using SkNh = SkNx<N, uint16_t>; + using SkNf = SkNx<N, float>; + using SkNi = SkNx<N, int>; + using SkNh = SkNx<N, uint16_t>; struct BodyStage; struct TailStage; @@ -379,6 +379,24 @@ STAGE(store_f16, false) { } } +STAGE(store_f32, false) { + auto ptr = *(SkPM4f**)ctx + x; + + SkPM4f buf[8]; + SkNf::Store4(kIsTail ? buf : ptr, r,g,b,a); + if (kIsTail) { + switch (tail & (N-1)) { + case 7: ptr[6] = buf[6]; + case 6: ptr[5] = buf[5]; + case 5: ptr[4] = buf[4]; + case 4: ptr[3] = buf[3]; + case 3: ptr[2] = buf[2]; + case 2: ptr[1] = buf[1]; + } + ptr[0] = buf[0]; + } +} + // Load 8-bit SkPMColor-order sRGB. STAGE(load_d_srgb, true) { |