blob: 7e1e26e91a2ba4e40ebf49dd1dae335864176138 [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
Mike Klein4e92b822017-04-26 13:45:36 -04008#include "SkArenaAlloc.h"
Mike Kleine902f8d2016-10-26 15:32:26 -04009#include "SkBlendModePriv.h"
Mike Klein4e92b822017-04-26 13:45:36 -040010#include "SkBlitRow.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000011#include "SkColorFilter.h"
Cary Clarka4083c92017-09-15 11:59:23 -040012#include "SkColorData.h"
Mike Klein4e92b822017-04-26 13:45:36 -040013#include "SkColorSpaceXformer.h"
reeddb873d82015-03-01 19:53:47 -080014#include "SkModeColorFilter.h"
Mike Klein4e92b822017-04-26 13:45:36 -040015#include "SkPM4f.h"
Mike Klein744908e2016-11-11 12:51:36 -050016#include "SkPM4fPriv.h"
Mike Klein4e92b822017-04-26 13:45:36 -040017#include "SkRandom.h"
Mike Klein96b333a2016-10-12 11:05:05 -040018#include "SkRasterPipeline.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000019#include "SkReadBuffer.h"
robertphillips@google.com1202c2a2013-05-23 14:00:17 +000020#include "SkString.h"
Mike Klein4e92b822017-04-26 13:45:36 -040021#include "SkUtils.h"
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +000022#include "SkValidationUtils.h"
Mike Klein4e92b822017-04-26 13:45:36 -040023#include "SkWriteBuffer.h"
reed@google.com31b30442014-02-06 20:59:47 +000024
reedc7141eb2016-01-11 13:08:59 -080025//////////////////////////////////////////////////////////////////////////////////////////////////
26
Mike Reedce9514c2017-06-11 22:14:14 -040027SkModeColorFilter::SkModeColorFilter(SkColor color, SkBlendMode mode) {
28 fColor = color;
29 fMode = mode;
30 // cache
31 fPMColor = SkPreMultiplyColor(fColor);
32}
33
Mike Reedfaba3712016-11-03 14:45:31 -040034bool SkModeColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const {
reeddb873d82015-03-01 19:53:47 -080035 if (color) {
36 *color = fColor;
reed@google.com43c50c82011-04-14 15:50:52 +000037 }
reeddb873d82015-03-01 19:53:47 -080038 if (mode) {
Mike Reedfaba3712016-11-03 14:45:31 -040039 *mode = fMode;
reed@google.com8b0d0f62012-06-04 18:10:33 +000040 }
reeddb873d82015-03-01 19:53:47 -080041 return true;
42}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000043
reeddb873d82015-03-01 19:53:47 -080044uint32_t SkModeColorFilter::getFlags() const {
reedc5b12282016-02-19 13:38:53 -080045 uint32_t flags = 0;
reed62a320c2015-03-24 06:35:23 -070046 switch (fMode) {
Mike Reed7d954ad2016-10-28 15:42:34 -040047 case SkBlendMode::kDst: //!< [Da, Dc]
48 case SkBlendMode::kSrcATop: //!< [Da, Sc * Da + (1 - Sa) * Dc]
reed31255652016-02-08 12:56:56 -080049 flags |= kAlphaUnchanged_Flag;
reed62a320c2015-03-24 06:35:23 -070050 default:
51 break;
52 }
reed31255652016-02-08 12:56:56 -080053 return flags;
reeddb873d82015-03-01 19:53:47 -080054}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000055
reeddb873d82015-03-01 19:53:47 -080056void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
57 buffer.writeColor(fColor);
Mike Reed7d954ad2016-10-28 15:42:34 -040058 buffer.writeUInt((int)fMode);
reeddb873d82015-03-01 19:53:47 -080059}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000060
reed60c9b582016-04-03 09:11:13 -070061sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070062 SkColor color = buffer.readColor();
Mike Reed7d954ad2016-10-28 15:42:34 -040063 SkBlendMode mode = (SkBlendMode)buffer.readUInt();
reed60c9b582016-04-03 09:11:13 -070064 return SkColorFilter::MakeModeFilter(color, mode);
reed9fa60da2014-08-21 07:59:51 -070065}
66
Mike Kleinfdf31032017-05-09 14:57:58 -040067void SkModeColorFilter::onAppendStages(SkRasterPipeline* p,
Mike Klein744908e2016-11-11 12:51:36 -050068 SkColorSpace* dst,
Herb Derbyac04fef2017-01-13 17:34:33 -050069 SkArenaAlloc* scratch,
Mike Klein744908e2016-11-11 12:51:36 -050070 bool shaderIsOpaque) const {
Mike Kleinc5093412016-11-04 16:36:39 -040071 p->append(SkRasterPipeline::move_src_dst);
Mike Klein073073e2017-08-03 09:42:53 -040072 p->append_constant_color(scratch, SkPM4f_from_SkColor(fColor, dst));
Mike Kleincb3ceb72017-06-09 15:58:37 -040073 SkBlendMode_AppendStages(fMode, p);
Mike Klein96b333a2016-10-12 11:05:05 -040074}
75
Mike Klein4e92b822017-04-26 13:45:36 -040076sk_sp<SkColorFilter> SkModeColorFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
Mike Reed6d9f4292017-07-06 12:32:55 -040077 SkColor color = xformer->apply(fColor);
78 if (color != fColor) {
79 return SkColorFilter::MakeModeFilter(color, fMode);
80 }
81 return this->INHERITED::onMakeColorSpace(xformer);
Mike Klein4e92b822017-04-26 13:45:36 -040082}
83
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000084///////////////////////////////////////////////////////////////////////////////
85#if SK_SUPPORT_GPU
86#include "GrBlend.h"
bsalomonae4738f2015-09-15 15:33:27 -070087#include "effects/GrXfermodeFragmentProcessor.h"
88#include "effects/GrConstColorProcessor.h"
joshualitteb2a6762014-12-04 11:35:33 -080089#include "SkGr.h"
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000090
Brian Salomonaff329b2017-08-11 09:40:37 -040091std::unique_ptr<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
Brian Salomon4cbb6e62017-10-25 15:12:19 -040092 GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const {
Mike Reed7d954ad2016-10-28 15:42:34 -040093 if (SkBlendMode::kDst == fMode) {
bsalomone25eea42015-09-29 06:38:55 -070094 return nullptr;
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000095 }
bsalomone25eea42015-09-29 06:38:55 -070096
Brian Salomon4cbb6e62017-10-25 15:12:19 -040097 auto constFP = GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpaceInfo),
Ethan Nicholase9d172a2017-11-20 12:12:24 -050098 GrConstColorProcessor::InputMode::kIgnore);
Brian Salomonaff329b2017-08-11 09:40:37 -040099 auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
bsalomone25eea42015-09-29 06:38:55 -0700100 if (!fp) {
101 return nullptr;
102 }
103#ifdef SK_DEBUG
104 // With a solid color input this should always be able to compute the blended color
105 // (at least for coeff modes)
Mike Reed7d954ad2016-10-28 15:42:34 -0400106 if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) {
Brian Salomoncb30bb22017-02-12 09:28:54 -0500107 SkASSERT(fp->hasConstantOutputForConstantInput());
bsalomone25eea42015-09-29 06:38:55 -0700108 }
109#endif
110 return fp;
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000111}
112
113#endif
114
115///////////////////////////////////////////////////////////////////////////////
116
Mike Reed7d954ad2016-10-28 15:42:34 -0400117sk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) {
reed9fa60da2014-08-21 07:59:51 -0700118 if (!SkIsValidMode(mode)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700119 return nullptr;
reed9fa60da2014-08-21 07:59:51 -0700120 }
121
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 unsigned alpha = SkColorGetA(color);
123
124 // first collaps some modes if possible
125
Mike Reed7d954ad2016-10-28 15:42:34 -0400126 if (SkBlendMode::kClear == mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 color = 0;
Mike Reed7d954ad2016-10-28 15:42:34 -0400128 mode = SkBlendMode::kSrc;
129 } else if (SkBlendMode::kSrcOver == mode) {
reed@android.com845fdac2009-06-23 03:01:32 +0000130 if (0 == alpha) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400131 mode = SkBlendMode::kDst;
reed@android.com845fdac2009-06-23 03:01:32 +0000132 } else if (255 == alpha) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400133 mode = SkBlendMode::kSrc;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 }
135 // else just stay srcover
136 }
137
138 // weed out combinations that are noops, and just return null
Mike Reed7d954ad2016-10-28 15:42:34 -0400139 if (SkBlendMode::kDst == mode ||
140 (0 == alpha && (SkBlendMode::kSrcOver == mode ||
141 SkBlendMode::kDstOver == mode ||
142 SkBlendMode::kDstOut == mode ||
143 SkBlendMode::kSrcATop == mode ||
144 SkBlendMode::kXor == mode ||
145 SkBlendMode::kDarken == mode)) ||
146 (0xFF == alpha && SkBlendMode::kDstIn == mode)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700147 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000149
Mike Reede8f28812017-06-12 21:58:03 -0400150 return SkModeColorFilter::Make(color, mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151}