aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkComposeShader.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-05-15 09:34:22 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-15 14:13:02 +0000
commit9959f723c33d609519c265abb5c4f48cba71fd6f (patch)
tree0cd154a470ca022967cf0a9f18331db093b5dc1b /src/core/SkComposeShader.cpp
parent787a16dd9e03f3971898131dd778206c8cb9a0df (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.cpp42
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)