diff options
author | Mike Klein <mtklein@chromium.org> | 2017-09-16 09:44:27 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-18 18:45:54 +0000 |
commit | 5f8774268ce4a0674a80e8cb5b0aeb4ea9b92a48 (patch) | |
tree | 4ab1c7d673455f1e602d3507d419c00d8db0c204 /src/core/SkBlendMode.cpp | |
parent | e9034493cd0ee21271f26943da8e6cdad794a580 (diff) |
Post-lerp -> pre-scale if blend mode supports it.
We've been doing this for Plus and SrcOver, and now expand it to the
couple other blend modes like SrcATop and DstOver that also support this
trick.
We need to take some special care with rgb coverage, and continue
to lerp for any mode that contains an explicit source-alpha term.
This is explained in the comments.
Change-Id: Ie44edf1504f305aec0c69fc92504431e0efeb627
Reviewed-on: https://skia-review.googlesource.com/47401
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/core/SkBlendMode.cpp')
-rw-r--r-- | src/core/SkBlendMode.cpp | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/src/core/SkBlendMode.cpp b/src/core/SkBlendMode.cpp index ef96cc0376..548106f1c4 100644 --- a/src/core/SkBlendMode.cpp +++ b/src/core/SkBlendMode.cpp @@ -9,22 +9,42 @@ #include "SkRasterPipeline.h" #include "../jumper/SkJumper.h" -bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) { +bool SkBlendMode_ShouldPreScaleCoverage(SkBlendMode mode, bool rgb_coverage) { + // The most important things we do here are: + // 1) never pre-scale with rgb coverage if the blend mode involves a source-alpha term; + // 2) always pre-scale Plus. + // + // When we pre-scale with rgb coverage, we scale each of source r,g,b, with a distinct value, + // and source alpha with one of those three values. This process destructively updates the + // source-alpha term, so we can't evaluate blend modes that need its original value. + // + // Plus always requires pre-scaling as a specific quirk of its implementation in + // SkRasterPipeline. This lets us put the clamp inside the blend mode itself rather + // than as a separate stage that'd come after the lerp. + // + // This function is a finer-grained breakdown of SkBlendMode_SupportsCoverageAsAlpha(). switch (mode) { - case SkBlendMode::kDst: - case SkBlendMode::kSrcOver: - case SkBlendMode::kDstOver: - case SkBlendMode::kDstOut: - case SkBlendMode::kSrcATop: - case SkBlendMode::kXor: - case SkBlendMode::kPlus: + case SkBlendMode::kDst: // d --> no sa term, ok! + case SkBlendMode::kDstOver: // d + s*inv(da) --> no sa term, ok! + case SkBlendMode::kPlus: // clamp(s+d) --> no sa term, ok! return true; - default: - break; + + case SkBlendMode::kDstOut: // d * inv(sa) + case SkBlendMode::kSrcATop: // s*da + d*inv(sa) + case SkBlendMode::kSrcOver: // s + d*inv(sa) + case SkBlendMode::kXor: // s*inv(da) + d*inv(sa) + return !rgb_coverage; + + default: break; } return false; } +// Users of this function may want to switch to the rgb-coverage aware version above. +bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) { + return SkBlendMode_ShouldPreScaleCoverage(mode, false); +} + struct CoeffRec { SkBlendModeCoeff fSrc; SkBlendModeCoeff fDst; @@ -62,14 +82,6 @@ bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoe return true; } -bool SkBlendMode_ShouldPreScaleCoverage(SkBlendMode mode, bool rgb_coverage) { - // The most important things we do here are: - // - always use pre-scaling for plus mode; - // - never use pre-scaling for srcover with 565 coverage. - return mode == SkBlendMode::kPlus || - (mode == SkBlendMode::kSrcOver && !rgb_coverage); -} - void SkBlendMode_AppendStages(SkBlendMode mode, SkRasterPipeline* p) { auto stage = SkRasterPipeline::srcover; switch (mode) { |