blob: 62595cf1eef38157f0840dfb171d9b6cc414b021 [file] [log] [blame]
robertphillips@google.comb83b6b42013-01-22 14:32:09 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Reed403d1542016-09-26 18:51:24 -04008#include "SkArithmeticModePriv.h"
mike@reedtribe.orge51755f2011-12-10 19:36:56 +00009#include "SkColorPriv.h"
mtkleind58f8402016-04-10 06:23:28 -070010#include "SkNx.h"
mtklein05e3c392016-07-25 05:56:16 -070011#include "SkRasterPipeline.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000013#include "SkString.h"
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000014#include "SkUnPreMultiply.h"
mtkleind58f8402016-04-10 06:23:28 -070015#include "SkWriteBuffer.h"
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000016#if SK_SUPPORT_GPU
egdaniel16a04b82015-01-14 10:49:18 -080017#include "SkArithmeticMode_gpu.h"
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000018#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000019
20class SkArithmeticMode_scalar : public SkXfermode {
21public:
reed87811232016-02-22 06:59:37 -080022 SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
23 bool enforcePMColor) {
24 fK[0] = k1;
25 fK[1] = k2;
26 fK[2] = k3;
27 fK[3] = k4;
28 fEnforcePMColor = enforcePMColor;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000029 }
halcanary9d524f22016-03-29 09:03:52 -070030
reed87811232016-02-22 06:59:37 -080031 void xfer32(SkPMColor[], const SkPMColor[], int count, const SkAlpha[]) const override;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000032
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +000033 SK_TO_STRING_OVERRIDE()
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000034 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
35
36#if SK_SUPPORT_GPU
bungeman06ca8ec2016-06-09 08:01:03 -070037 sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
38 sk_sp<GrFragmentProcessor> dst) const override;
39 sk_sp<GrXPFactory> asXPFactory() const override;
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000040#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000041
reed374772b2016-10-05 17:33:02 -070042 bool isArithmetic(SkArithmeticParams* params) const override {
43 if (params) {
44 memcpy(params->fK, fK, 4 * sizeof(float));
45 params->fEnforcePMColor = fEnforcePMColor;
46 }
47 return true;
48 }
49
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000050private:
mtklein36352bf2015-03-25 18:17:31 -070051 void flatten(SkWriteBuffer& buffer) const override {
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000052 buffer.writeScalar(fK[0]);
53 buffer.writeScalar(fK[1]);
54 buffer.writeScalar(fK[2]);
55 buffer.writeScalar(fK[3]);
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +000056 buffer.writeBool(fEnforcePMColor);
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000057 }
halcanary27a6e862016-01-21 14:15:10 -080058
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000059 SkScalar fK[4];
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +000060 bool fEnforcePMColor;
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000061
reed9fa60da2014-08-21 07:59:51 -070062 friend class SkArithmeticMode;
63
skia.committer@gmail.com98ded842013-01-23 07:06:17 +000064 typedef SkXfermode INHERITED;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000065};
66
reed60c9b582016-04-03 09:11:13 -070067sk_sp<SkFlattenable> SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070068 const SkScalar k1 = buffer.readScalar();
69 const SkScalar k2 = buffer.readScalar();
70 const SkScalar k3 = buffer.readScalar();
71 const SkScalar k4 = buffer.readScalar();
72 const bool enforcePMColor = buffer.readBool();
reed60c9b582016-04-03 09:11:13 -070073 return SkArithmeticMode::Make(k1, k2, k3, k4, enforcePMColor);
reed9fa60da2014-08-21 07:59:51 -070074}
75
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000076void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
reed@google.com30da7452012-12-17 19:55:24 +000077 int count, const SkAlpha aaCoverage[]) const {
mtkleind58f8402016-04-10 06:23:28 -070078 const Sk4f k1 = fK[0] * (1/255.0f),
79 k2 = fK[1],
80 k3 = fK[2],
81 k4 = fK[3] * 255.0f + 0.5f;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000082
mtkleind58f8402016-04-10 06:23:28 -070083 auto pin = [](float min, const Sk4f& val, float max) {
84 return Sk4f::Max(min, Sk4f::Min(val, max));
85 };
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000086
mtkleind58f8402016-04-10 06:23:28 -070087 for (int i = 0; i < count; i++) {
88 if (aaCoverage && aaCoverage[i] == 0) {
89 continue;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000090 }
mtkleind58f8402016-04-10 06:23:28 -070091
92 Sk4f s = SkNx_cast<float>(Sk4b::Load(src+i)),
93 d = SkNx_cast<float>(Sk4b::Load(dst+i)),
94 r = pin(0, k1*s*d + k2*s + k3*d + k4, 255);
95
96 if (fEnforcePMColor) {
97 Sk4f a = SkNx_shuffle<3,3,3,3>(r);
98 r = Sk4f::Min(a, r);
99 }
100
101 if (aaCoverage && aaCoverage[i] != 255) {
102 Sk4f c = aaCoverage[i] * (1/255.0f);
103 r = d + (r-d)*c;
104 }
105
106 SkNx_cast<uint8_t>(r).store(dst+i);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000107 }
108}
109
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000110#ifndef SK_IGNORE_TO_STRING
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000111void SkArithmeticMode_scalar::toString(SkString* str) const {
112 str->append("SkArithmeticMode_scalar: ");
113 for (int i = 0; i < 4; ++i) {
114 str->appendScalar(fK[i]);
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +0000115 str->append(" ");
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000116 }
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +0000117 str->appendS32(fEnforcePMColor ? 1 : 0);
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000118}
119#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000120
121///////////////////////////////////////////////////////////////////////////////
122
reedcfb6bdf2016-03-29 11:32:50 -0700123sk_sp<SkXfermode> SkArithmeticMode::Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
124 bool enforcePMColor) {
reed87811232016-02-22 06:59:37 -0800125 if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
126 SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
reedcfb6bdf2016-03-29 11:32:50 -0700127 return SkXfermode::Make(SkXfermode::kSrc_Mode);
reed87811232016-02-22 06:59:37 -0800128 } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
129 SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
reedcfb6bdf2016-03-29 11:32:50 -0700130 return SkXfermode::Make(SkXfermode::kDst_Mode);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000131 }
reedcfb6bdf2016-03-29 11:32:50 -0700132 return sk_make_sp<SkArithmeticMode_scalar>(k1, k2, k3, k4, enforcePMColor);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000133}
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000134
135
136//////////////////////////////////////////////////////////////////////////////
137
138#if SK_SUPPORT_GPU
bungeman06ca8ec2016-06-09 08:01:03 -0700139sk_sp<GrFragmentProcessor> SkArithmeticMode_scalar::makeFragmentProcessorForImageFilter(
140 sk_sp<GrFragmentProcessor> dst) const {
141 return GrArithmeticFP::Make(SkScalarToFloat(fK[0]),
142 SkScalarToFloat(fK[1]),
143 SkScalarToFloat(fK[2]),
144 SkScalarToFloat(fK[3]),
145 fEnforcePMColor,
146 std::move(dst));
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000147}
148
bungeman06ca8ec2016-06-09 08:01:03 -0700149sk_sp<GrXPFactory> SkArithmeticMode_scalar::asXPFactory() const {
150 return GrArithmeticXPFactory::Make(SkScalarToFloat(fK[0]),
151 SkScalarToFloat(fK[1]),
152 SkScalarToFloat(fK[2]),
153 SkScalarToFloat(fK[3]),
154 fEnforcePMColor);
egdanielf351aa32015-01-14 12:53:01 -0800155}
156
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000157#endif
158
159SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
160 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
161SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END