aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkBlendMode.cpp
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-09-16 09:44:27 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-18 18:45:54 +0000
commit5f8774268ce4a0674a80e8cb5b0aeb4ea9b92a48 (patch)
tree4ab1c7d673455f1e602d3507d419c00d8db0c204 /src/core/SkBlendMode.cpp
parente9034493cd0ee21271f26943da8e6cdad794a580 (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.cpp48
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) {