blob: 954f8eb70ace675a389c7ea2be541ea8eaa0b078 [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@reedtribe.orge51755f2011-12-10 19:36:56 +00008#include "SkArithmeticMode.h"
9#include "SkColorPriv.h"
Stephen Whitea5d432e2016-04-19 14:07:06 -040010#include "SkNx.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000011#include "SkReadBuffer.h"
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000012#include "SkString.h"
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000013#include "SkUnPreMultiply.h"
Stephen Whitea5d432e2016-04-19 14:07:06 -040014#include "SkWriteBuffer.h"
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000015#if SK_SUPPORT_GPU
egdaniel16a04b82015-01-14 10:49:18 -080016#include "SkArithmeticMode_gpu.h"
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000017#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000018
19class SkArithmeticMode_scalar : public SkXfermode {
20public:
reed87811232016-02-22 06:59:37 -080021 SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
22 bool enforcePMColor) {
23 fK[0] = k1;
24 fK[1] = k2;
25 fK[2] = k3;
26 fK[3] = k4;
27 fEnforcePMColor = enforcePMColor;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000028 }
reed87811232016-02-22 06:59:37 -080029
30 void xfer32(SkPMColor[], const SkPMColor[], int count, const SkAlpha[]) const override;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000031
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +000032 SK_TO_STRING_OVERRIDE()
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000033 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
34
35#if SK_SUPPORT_GPU
robertphillips4f037942016-02-09 05:09:27 -080036 const GrFragmentProcessor* getFragmentProcessorForImageFilter(
37 const GrFragmentProcessor* dst) const override;
38 GrXPFactory* asXPFactory() const override;
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000039#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000040
41private:
mtklein36352bf2015-03-25 18:17:31 -070042 void flatten(SkWriteBuffer& buffer) const override {
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000043 buffer.writeScalar(fK[0]);
44 buffer.writeScalar(fK[1]);
45 buffer.writeScalar(fK[2]);
46 buffer.writeScalar(fK[3]);
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +000047 buffer.writeBool(fEnforcePMColor);
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +000048 }
halcanary27a6e862016-01-21 14:15:10 -080049
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000050 SkScalar fK[4];
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +000051 bool fEnforcePMColor;
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000052
reed9fa60da2014-08-21 07:59:51 -070053 friend class SkArithmeticMode;
54
skia.committer@gmail.com98ded842013-01-23 07:06:17 +000055 typedef SkXfermode INHERITED;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000056};
57
reed9fa60da2014-08-21 07:59:51 -070058SkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) {
59 const SkScalar k1 = buffer.readScalar();
60 const SkScalar k2 = buffer.readScalar();
61 const SkScalar k3 = buffer.readScalar();
62 const SkScalar k4 = buffer.readScalar();
63 const bool enforcePMColor = buffer.readBool();
reed87811232016-02-22 06:59:37 -080064 return SkArithmeticMode::Create(k1, k2, k3, k4, enforcePMColor);
reed9fa60da2014-08-21 07:59:51 -070065}
66
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000067void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
reed@google.com30da7452012-12-17 19:55:24 +000068 int count, const SkAlpha aaCoverage[]) const {
Stephen Whitea5d432e2016-04-19 14:07:06 -040069 const Sk4f k1 = fK[0] * (1/255.0f),
70 k2 = fK[1],
71 k3 = fK[2],
72 k4 = fK[3] * 255.0f + 0.5f;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000073
Stephen Whitea5d432e2016-04-19 14:07:06 -040074 auto pin = [](float min, const Sk4f& val, float max) {
75 return Sk4f::Max(min, Sk4f::Min(val, max));
76 };
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000077
Stephen Whitea5d432e2016-04-19 14:07:06 -040078 for (int i = 0; i < count; i++) {
79 if (aaCoverage && aaCoverage[i] == 0) {
80 continue;
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000081 }
Stephen Whitea5d432e2016-04-19 14:07:06 -040082
83 Sk4f s = SkNx_cast<float>(Sk4b::Load(src+i)),
84 d = SkNx_cast<float>(Sk4b::Load(dst+i)),
85 r = pin(0, k1*s*d + k2*s + k3*d + k4, 255);
86
87 if (fEnforcePMColor) {
88 Sk4f a = SkNx_shuffle<3,3,3,3>(r);
89 r = Sk4f::Min(a, r);
90 }
91
92 if (aaCoverage && aaCoverage[i] != 255) {
93 Sk4f c = aaCoverage[i] * (1/255.0f);
94 r = d + (r-d)*c;
95 }
96
97 SkNx_cast<uint8_t>(r).store(dst+i);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000098 }
99}
100
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000101#ifndef SK_IGNORE_TO_STRING
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000102void SkArithmeticMode_scalar::toString(SkString* str) const {
103 str->append("SkArithmeticMode_scalar: ");
104 for (int i = 0; i < 4; ++i) {
105 str->appendScalar(fK[i]);
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +0000106 str->append(" ");
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000107 }
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +0000108 str->appendS32(fEnforcePMColor ? 1 : 0);
robertphillips@google.comb83b6b42013-01-22 14:32:09 +0000109}
110#endif
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000111
112///////////////////////////////////////////////////////////////////////////////
113
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000114SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
commit-bot@chromium.org51a11b72014-04-02 19:32:15 +0000115 SkScalar k3, SkScalar k4,
116 bool enforcePMColor) {
reed87811232016-02-22 06:59:37 -0800117 if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
118 SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
119 return SkXfermode::Create(SkXfermode::kSrc_Mode);
120 } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
121 SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
122 return SkXfermode::Create(SkXfermode::kDst_Mode);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000123 }
reed87811232016-02-22 06:59:37 -0800124
125 return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000126}
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000127
128
129//////////////////////////////////////////////////////////////////////////////
130
131#if SK_SUPPORT_GPU
robertphillips4f037942016-02-09 05:09:27 -0800132const GrFragmentProcessor* SkArithmeticMode_scalar::getFragmentProcessorForImageFilter(
133 const GrFragmentProcessor* dst) const {
134 return GrArithmeticFP::Create(SkScalarToFloat(fK[0]),
135 SkScalarToFloat(fK[1]),
136 SkScalarToFloat(fK[2]),
137 SkScalarToFloat(fK[3]),
138 fEnforcePMColor,
139 dst);
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000140}
141
robertphillips4f037942016-02-09 05:09:27 -0800142GrXPFactory* SkArithmeticMode_scalar::asXPFactory() const {
143 return GrArithmeticXPFactory::Create(SkScalarToFloat(fK[0]),
144 SkScalarToFloat(fK[1]),
145 SkScalarToFloat(fK[2]),
146 SkScalarToFloat(fK[3]),
147 fEnforcePMColor);
egdanielf351aa32015-01-14 12:53:01 -0800148}
149
senorblanco@chromium.org9a6eb0e2013-05-29 20:55:09 +0000150#endif
151
152SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
153 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
154SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END