blob: ba3b50d763b1ea7f1c67fbd638515190c16b5c28 [file] [log] [blame]
reed@android.com845fdac2009-06-23 03:01:32 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com845fdac2009-06-23 03:01:32 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com845fdac2009-06-23 03:01:32 +00006 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00007
reed@android.comc4cae852009-09-23 15:06:10 +00008#include "SkBlitRow.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkColorFilter.h"
10#include "SkColorPriv.h"
reeddb873d82015-03-01 19:53:47 -080011#include "SkModeColorFilter.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
13#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkUtils.h"
robertphillips@google.com1202c2a2013-05-23 14:00:17 +000015#include "SkString.h"
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +000016#include "SkValidationUtils.h"
reeddd9ffea2016-02-18 12:39:14 -080017#include "SkPM4f.h"
reed@google.com31b30442014-02-06 20:59:47 +000018
reedc7141eb2016-01-11 13:08:59 -080019//////////////////////////////////////////////////////////////////////////////////////////////////
20
21#ifndef SK_IGNORE_TO_STRING
22void SkModeColorFilter::toString(SkString* str) const {
23 str->append("SkModeColorFilter: color: 0x");
24 str->appendHex(fColor);
25 str->append(" mode: ");
26 str->append(SkXfermode::ModeName(fMode));
27}
28#endif
29
reeddb873d82015-03-01 19:53:47 -080030bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
31 if (color) {
32 *color = fColor;
reed@google.com43c50c82011-04-14 15:50:52 +000033 }
reeddb873d82015-03-01 19:53:47 -080034 if (mode) {
35 *mode = fMode;
reed@google.com8b0d0f62012-06-04 18:10:33 +000036 }
reeddb873d82015-03-01 19:53:47 -080037 return true;
38}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000039
reeddb873d82015-03-01 19:53:47 -080040uint32_t SkModeColorFilter::getFlags() const {
reedc5b12282016-02-19 13:38:53 -080041 uint32_t flags = 0;
reed62a320c2015-03-24 06:35:23 -070042 switch (fMode) {
43 case SkXfermode::kDst_Mode: //!< [Da, Dc]
44 case SkXfermode::kSrcATop_Mode: //!< [Da, Sc * Da + (1 - Sa) * Dc]
reed31255652016-02-08 12:56:56 -080045 flags |= kAlphaUnchanged_Flag;
reed62a320c2015-03-24 06:35:23 -070046 default:
47 break;
48 }
reed31255652016-02-08 12:56:56 -080049 return flags;
reeddb873d82015-03-01 19:53:47 -080050}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000051
reeddb873d82015-03-01 19:53:47 -080052void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
53 SkPMColor color = fPMColor;
54 SkXfermodeProc proc = fProc;
halcanary9d524f22016-03-29 09:03:52 -070055
reed31255652016-02-08 12:56:56 -080056 for (int i = 0; i < count; i++) {
57 result[i] = proc(color, shader[i]);
58 }
59}
mtklein95cc0122015-04-27 15:11:01 -070060
reed31255652016-02-08 12:56:56 -080061void SkModeColorFilter::filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const {
62 SkPM4f color = SkPM4f::FromPMColor(fPMColor);
63 SkXfermodeProc4f proc = SkXfermode::GetProc4f(fMode);
halcanary9d524f22016-03-29 09:03:52 -070064
reeddb873d82015-03-01 19:53:47 -080065 for (int i = 0; i < count; i++) {
66 result[i] = proc(color, shader[i]);
reed@google.com8b0d0f62012-06-04 18:10:33 +000067 }
reeddb873d82015-03-01 19:53:47 -080068}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000069
reeddb873d82015-03-01 19:53:47 -080070void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
71 buffer.writeColor(fColor);
72 buffer.writeUInt(fMode);
73}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000074
reeddb873d82015-03-01 19:53:47 -080075void SkModeColorFilter::updateCache() {
76 fPMColor = SkPreMultiplyColor(fColor);
77 fProc = SkXfermode::GetProc(fMode);
reeddb873d82015-03-01 19:53:47 -080078}
reed@android.com8a1c16f2008-12-17 15:59:43 +000079
reed60c9b582016-04-03 09:11:13 -070080sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070081 SkColor color = buffer.readColor();
82 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt();
reed60c9b582016-04-03 09:11:13 -070083 return SkColorFilter::MakeModeFilter(color, mode);
reed9fa60da2014-08-21 07:59:51 -070084}
85
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000086///////////////////////////////////////////////////////////////////////////////
87#if SK_SUPPORT_GPU
88#include "GrBlend.h"
egdaniel605dd0f2014-11-12 08:35:25 -080089#include "GrInvariantOutput.h"
bsalomonae4738f2015-09-15 15:33:27 -070090#include "effects/GrXfermodeFragmentProcessor.h"
91#include "effects/GrConstColorProcessor.h"
joshualitteb2a6762014-12-04 11:35:33 -080092#include "SkGr.h"
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000093
bungeman06ca8ec2016-06-09 08:01:03 -070094sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(GrContext*) const {
bsalomone25eea42015-09-29 06:38:55 -070095 if (SkXfermode::kDst_Mode == fMode) {
96 return nullptr;
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000097 }
bsalomone25eea42015-09-29 06:38:55 -070098
bungeman06ca8ec2016-06-09 08:01:03 -070099 sk_sp<GrFragmentProcessor> constFP(
100 GrConstColorProcessor::Make(SkColorToPremulGrColor(fColor),
101 GrConstColorProcessor::kIgnore_InputMode));
102 sk_sp<GrFragmentProcessor> fp(
103 GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode));
bsalomone25eea42015-09-29 06:38:55 -0700104 if (!fp) {
105 return nullptr;
106 }
107#ifdef SK_DEBUG
108 // With a solid color input this should always be able to compute the blended color
109 // (at least for coeff modes)
110 if (fMode <= SkXfermode::kLastCoeffMode) {
111 static SkRandom gRand;
112 GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColorComponentFlags,
113 false);
114 fp->computeInvariantOutput(&io);
115 SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags);
116 }
117#endif
118 return fp;
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000119}
120
121#endif
122
123///////////////////////////////////////////////////////////////////////////////
124
reedc7141eb2016-01-11 13:08:59 -0800125class Src_SkModeColorFilter final : public SkModeColorFilter {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126public:
reed@google.com43c50c82011-04-14 15:50:52 +0000127 Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128
mtklein36352bf2015-03-25 18:17:31 -0700129 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
reed@google.com8b0d0f62012-06-04 18:10:33 +0000130 sk_memset32(result, this->getPMColor(), count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 }
132
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000133private:
reed@google.com43c50c82011-04-14 15:50:52 +0000134 typedef SkModeColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135};
136
reedc7141eb2016-01-11 13:08:59 -0800137class SrcOver_SkModeColorFilter final : public SkModeColorFilter {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138public:
mtklein95cc0122015-04-27 15:11:01 -0700139 SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrcOver_Mode) { }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140
mtklein36352bf2015-03-25 18:17:31 -0700141 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
mtklein95cc0122015-04-27 15:11:01 -0700142 SkBlitRow::Color32(result, shader, count, this->getPMColor());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 }
144
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000145private:
reed@google.com43c50c82011-04-14 15:50:52 +0000146 typedef SkModeColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147};
148
reed@google.com43c50c82011-04-14 15:50:52 +0000149///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150
reedd053ce92016-03-22 10:17:23 -0700151sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkXfermode::Mode mode) {
reed9fa60da2014-08-21 07:59:51 -0700152 if (!SkIsValidMode(mode)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700153 return nullptr;
reed9fa60da2014-08-21 07:59:51 -0700154 }
155
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156 unsigned alpha = SkColorGetA(color);
157
158 // first collaps some modes if possible
159
reed@android.com845fdac2009-06-23 03:01:32 +0000160 if (SkXfermode::kClear_Mode == mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161 color = 0;
reed@android.com845fdac2009-06-23 03:01:32 +0000162 mode = SkXfermode::kSrc_Mode;
163 } else if (SkXfermode::kSrcOver_Mode == mode) {
164 if (0 == alpha) {
165 mode = SkXfermode::kDst_Mode;
166 } else if (255 == alpha) {
167 mode = SkXfermode::kSrc_Mode;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 }
169 // else just stay srcover
170 }
171
172 // weed out combinations that are noops, and just return null
reed@android.com845fdac2009-06-23 03:01:32 +0000173 if (SkXfermode::kDst_Mode == mode ||
174 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
175 SkXfermode::kDstOver_Mode == mode ||
176 SkXfermode::kDstOut_Mode == mode ||
177 SkXfermode::kSrcATop_Mode == mode ||
178 SkXfermode::kXor_Mode == mode ||
179 SkXfermode::kDarken_Mode == mode)) ||
180 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700181 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000183
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 switch (mode) {
reed@google.com43c50c82011-04-14 15:50:52 +0000185 case SkXfermode::kSrc_Mode:
reedd053ce92016-03-22 10:17:23 -0700186 return sk_make_sp<Src_SkModeColorFilter>(color);
reed@google.com43c50c82011-04-14 15:50:52 +0000187 case SkXfermode::kSrcOver_Mode:
reedd053ce92016-03-22 10:17:23 -0700188 return sk_make_sp<SrcOver_SkModeColorFilter>(color);
reed@google.com43c50c82011-04-14 15:50:52 +0000189 default:
reedd053ce92016-03-22 10:17:23 -0700190 return SkModeColorFilter::Make(color, mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191 }
192}