diff options
author | Mike Klein <mtklein@chromium.org> | 2017-08-24 13:06:23 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-24 18:51:57 +0000 |
commit | fb126fa96e0f49f5dc17a9a043acced68be99e93 (patch) | |
tree | 5a9616cb9fdf2600e4ad9454e96d6f8a1492a7a5 /src/core/SkBlendMode.cpp | |
parent | f05bddaac3d8219fcaf623b64897ced81c05d437 (diff) |
rework plus blend mode
The most interesting parts of this are how plus interacts with partial
coverage. Plus needs its clamp to happen after the lerp.
Luckily, some of its math folds away:
d' = clamp[ d*(1-c) + (s+d)*c ] ==
clamp[ d - dc + sc + dc ] ==
clamp[ d + sc ]
What's nice there is that coverage can be folded into the src term.
This suggests that we can re-write the plus stage to clamp internally
(and thus, be viable for 8-bit) if we always pre-scale with coverage.
We don't have a way to pre-scale with 565 coverage until now, but
it's only a step or two away from there. We can use the alternate
formulation we derived for alpha for lerp_565, calculating the alpha
coverage from red, green, and blue coverages _and_ the values of src
and dst alpha.
While we already pre-scale srcover today for 8-bit or constant coverage,
we cannot do the same for 565. When evaluating the expression
d' = s + (1-a)d
we need the a term to be pre-scaled with red's coverage when calculating
dr', with blue's when calculating db', etc. Essentially we need to
carry around a bunch of extra values, and we've got no way to do that.
So instead, we'll just carefully pre-scale plus with any coverage, and
keep post-lerping srcover when we have 565 coverage.
Change-Id: I7a7a52eec7d482e1b98bb8a01ea0a3d5e67bef65
Reviewed-on: https://skia-review.googlesource.com/38300
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src/core/SkBlendMode.cpp')
-rw-r--r-- | src/core/SkBlendMode.cpp | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/src/core/SkBlendMode.cpp b/src/core/SkBlendMode.cpp index 35d49d2499..ef96cc0376 100644 --- a/src/core/SkBlendMode.cpp +++ b/src/core/SkBlendMode.cpp @@ -62,7 +62,15 @@ bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoe return true; } -void SkBlendMode_AppendStagesNoClamp(SkBlendMode mode, SkRasterPipeline* p) { +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) { case SkBlendMode::kClear: stage = SkRasterPipeline::clear; break; @@ -100,14 +108,6 @@ void SkBlendMode_AppendStagesNoClamp(SkBlendMode mode, SkRasterPipeline* p) { p->append(stage); } -void SkBlendMode_AppendClampIfNeeded(SkBlendMode mode, SkRasterPipeline* p) { - if (mode == SkBlendMode::kPlus) { - // Both clamp_a and clamp_1 would preserve premultiplication invariants here, - // so we pick clamp_1 for being a smidge faster. - p->append(SkRasterPipeline::clamp_1); - } -} - SkPM4f SkBlendMode_Apply(SkBlendMode mode, const SkPM4f& src, const SkPM4f& dst) { // special-case simple/common modes... switch (mode) { |