diff options
author | 2017-05-15 09:34:22 -0400 | |
---|---|---|
committer | 2017-05-15 14:13:02 +0000 | |
commit | 9959f723c33d609519c265abb5c4f48cba71fd6f (patch) | |
tree | 0cd154a470ca022967cf0a9f18331db093b5dc1b /src/core/SkComposeShader.cpp | |
parent | 787a16dd9e03f3971898131dd778206c8cb9a0df (diff) |
composeshader stages
needed to add two helper stages for composeshader
load_rgba, store_rgba
These just read/write the r,g,b,a registers to context memory, making no promise as to how the
memory is formatted (e.g. interleaved -vs- planar).
Note that we have similar existing stages, but they did not seem to suit:
constant_color
This guy loads 4 floats from memory, and splats them into registers. I need to load 4 entire
registers.
load_f32, store_f32
These offset where they read/write based on the 'x' register, plus they guarantee that the memory
will be interleaved ala SkPM4f.
Bug: skia:
Change-Id: Iaa81f950660b837bdb34416ab3e342d56a92239b
Reviewed-on: https://skia-review.googlesource.com/16716
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkComposeShader.cpp')
-rw-r--r-- | src/core/SkComposeShader.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp index ee0fe10c77..e3282357a2 100644 --- a/src/core/SkComposeShader.cpp +++ b/src/core/SkComposeShader.cpp @@ -6,13 +6,16 @@ */ #include "SkArenaAlloc.h" +#include "SkBlendModePriv.h" #include "SkComposeShader.h" #include "SkColorFilter.h" #include "SkColorPriv.h" #include "SkColorShader.h" +#include "SkRasterPipeline.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" #include "SkString.h" +#include "../jumper/SkJumper.h" sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode) { @@ -117,6 +120,45 @@ bool SkComposeShader::asACompose(ComposeRec* rec) const { return true; } +bool SkComposeShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, + SkArenaAlloc* alloc, const SkMatrix& ctm, + const SkPaint& paint, const SkMatrix* localM) const { + struct Storage { + float fXY[4 * SkJumper_kMaxStride]; + float fRGBA[4 * SkJumper_kMaxStride]; + float fAlpha; + }; + auto storage = alloc->make<Storage>(); + + // We need to save off device x,y (inputs to shader), since after calling fShaderA they + // will be smashed, and I'll need them again for fShaderB. store_rgba saves off 4 registers + // even though we only need to save r,g. + pipeline->append(SkRasterPipeline::store_rgba, storage->fXY); + if (!fShaderB->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) { // SRC + return false; + } + // This outputs r,g,b,a, which we'll need later when we apply the mode, but we save it off now + // since fShaderB will overwrite them. + pipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA); + // Now we restore the device x,y for the next shader + pipeline->append(SkRasterPipeline::load_rgba, storage->fXY); + if (!fShaderA->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) { // DST + return false; + } + // We now have our logical 'dst' in r,g,b,a, but we need it in dr,dg,db,da for the mode + // so we have to shuttle them. If we had a stage the would load_into_dst, then we could + // reverse the two shader invocations, and avoid this move... + pipeline->append(SkRasterPipeline::move_src_dst); + pipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA); + + // Idea: should time this, and see if it helps to have custom versions of the overflow modes + // that do their own clamping, avoiding the overhead of an extra stage. + SkBlendMode_AppendStages(fMode, pipeline); + if (SkBlendMode_CanOverflow(fMode)) { + pipeline->append(SkRasterPipeline::clamp_a); + } + return true; +} // larger is better (fewer times we have to loop), but we shouldn't // take up too much stack-space (each element is 4 bytes) |