Flutter Engine
The Flutter Engine
BlendFormula.h
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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
8#ifndef skgpu_BlendFormula_DEFINED
9#define skgpu_BlendFormula_DEFINED
10
14#include "src/gpu/Blend.h"
15
16#include <cstdint>
17
18enum class SkBlendMode;
19
20namespace skgpu {
21
22/**
23 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
24 */
26public:
27 /**
28 * Values the shader can write to primary and secondary outputs. These are all modulated by
29 * coverage. We will ignore the multiplies when not using coverage.
30 */
33 kCoverage_OutputType, //<! inputCoverage
34 kModulate_OutputType, //<! inputColor * inputCoverage
35 kSAModulate_OutputType, //<! inputColor.a * inputCoverage
36 kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
37 kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
38
40 };
41
42 constexpr BlendFormula(OutputType primaryOut,
43 OutputType secondaryOut,
47 : fPrimaryOutputType(primaryOut)
48 , fSecondaryOutputType(secondaryOut)
49 , fBlendEquation(SkTo<uint8_t>(equation))
50 , fSrcCoeff(SkTo<uint8_t>(srcCoeff))
51 , fDstCoeff(SkTo<uint8_t>(dstCoeff))
52 , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}
53
54 BlendFormula(const BlendFormula&) = default;
56
57 bool operator==(const BlendFormula& that) const {
61 fSrcCoeff == that.fSrcCoeff &&
62 fDstCoeff == that.fDstCoeff &&
63 fProps == that.fProps;
64 }
65
66 bool hasSecondaryOutput() const {
68 }
69 bool modifiesDst() const {
70 return SkToBool(fProps & kModifiesDst_Property);
71 }
72 bool unaffectedByDst() const {
73 return SkToBool(fProps & kUnaffectedByDst_Property);
74 }
75 // We don't always fully optimize the blend formula (e.g., for opaque src-over), so we include
76 // an "IfOpaque" variant to help set AnalysisProperties::kUnaffectedByDstValue in those cases.
78 return SkToBool(fProps & kUnaffectedByDstIfOpaque_Property);
79 }
80 bool usesInputColor() const {
81 return SkToBool(fProps & kUsesInputColor_Property);
82 }
84 return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
85 }
86
88 return static_cast<skgpu::BlendEquation>(fBlendEquation);
89 }
90
92 return static_cast<skgpu::BlendCoeff>(fSrcCoeff);
93 }
94
96 return static_cast<skgpu::BlendCoeff>(fDstCoeff);
97 }
98
100 return fPrimaryOutputType;
101 }
102
105 }
106
107private:
108 enum Properties {
109 kModifiesDst_Property = 1 << 0,
110 kUnaffectedByDst_Property = 1 << 1,
111 kUnaffectedByDstIfOpaque_Property = 1 << 2,
112 kUsesInputColor_Property = 1 << 3,
113 kCanTweakAlphaForCoverage_Property = 1 << 4,
114
115 kLast_Property = kCanTweakAlphaForCoverage_Property
116 };
118
119 /**
120 * Deduce the properties of a BlendFormula.
121 */
122 constexpr BlendFormula::Properties GetProperties(OutputType PrimaryOut,
123 OutputType SecondaryOut,
125 skgpu::BlendCoeff SrcCoeff,
126 skgpu::BlendCoeff DstCoeff) {
127 return
128 // The provided formula should already be optimized before a BlendFormula is constructed.
129 // Assert that here while setting up the properties in the constexpr constructor.
130 SkASSERT((kNone_OutputType == PrimaryOut) ==
131 !skgpu::BlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)),
133 SkASSERT((kNone_OutputType == SecondaryOut) == !skgpu::BlendCoeffRefsSrc2(DstCoeff)),
134 SkASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut),
135 SkASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut),
136
137 static_cast<Properties>(
138 (skgpu::BlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff)
139 ? kModifiesDst_Property
140 : 0) |
141 (!skgpu::BlendCoeffsUseDstColor(SrcCoeff, DstCoeff, false/*srcColorIsOpaque*/)
142 ? kUnaffectedByDst_Property
143 : 0) |
144 (!skgpu::BlendCoeffsUseDstColor(SrcCoeff, DstCoeff, true/*srcColorIsOpaque*/)
145 ? kUnaffectedByDstIfOpaque_Property
146 : 0) |
147 ((PrimaryOut >= kModulate_OutputType &&
148 skgpu::BlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
149 (SecondaryOut >= kModulate_OutputType &&
151 ? kUsesInputColor_Property
152 : 0) | // We assert later that SrcCoeff doesn't ref src2.
153 ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
154 kNone_OutputType == SecondaryOut &&
156 ? kCanTweakAlphaForCoverage_Property
157 : 0));
158 }
159
160 struct {
161 // We allot the enums one more bit than they require because MSVC seems to sign-extend
162 // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
165 uint32_t fBlendEquation : 6;
166 uint32_t fSrcCoeff : 6;
167 uint32_t fDstCoeff : 6;
168 Properties fProps : 32 - (4 + 4 + 6 + 6 + 6);
169 };
170
171 static_assert(kLast_OutputType < (1 << 3));
172 static_assert(static_cast<int>(skgpu::BlendEquation::kLast) < (1 << 5));
173 static_assert(static_cast<int>(skgpu::BlendCoeff::kLast) < (1 << 5));
174 static_assert(kLast_Property < (1 << 6));
175};
176
177static_assert(4 == sizeof(BlendFormula));
178
179SK_MAKE_BITFIELD_OPS(BlendFormula::Properties)
180
181BlendFormula GetBlendFormula(bool isOpaque, bool hasCoverage, SkBlendMode xfermode);
182
183BlendFormula GetLCDBlendFormula(SkBlendMode xfermode);
184
185} // namespace skgpu
186
187#endif // skgpu_BlendFormula_DEFINED
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
#define SK_MAKE_BITFIELD_OPS(X)
Definition: SkMacros.h:66
#define SK_DECL_BITFIELD_OPS_FRIENDS(X)
Definition: SkMacros.h:86
constexpr D SkTo(S s)
Definition: SkTo.h:16
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
OutputType secondaryOutput() const
Definition: BlendFormula.h:103
BlendFormula(const BlendFormula &)=default
skgpu::BlendEquation equation() const
Definition: BlendFormula.h:87
skgpu::BlendCoeff dstCoeff() const
Definition: BlendFormula.h:95
OutputType primaryOutput() const
Definition: BlendFormula.h:99
OutputType fSecondaryOutputType
Definition: BlendFormula.h:164
constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, skgpu::BlendEquation equation, skgpu::BlendCoeff srcCoeff, skgpu::BlendCoeff dstCoeff)
Definition: BlendFormula.h:42
bool hasSecondaryOutput() const
Definition: BlendFormula.h:66
bool unaffectedByDst() const
Definition: BlendFormula.h:72
bool canTweakAlphaForCoverage() const
Definition: BlendFormula.h:83
bool unaffectedByDstIfOpaque() const
Definition: BlendFormula.h:77
BlendFormula & operator=(const BlendFormula &)=default
skgpu::BlendCoeff srcCoeff() const
Definition: BlendFormula.h:91
bool modifiesDst() const
Definition: BlendFormula.h:69
bool usesInputColor() const
Definition: BlendFormula.h:80
bool operator==(const BlendFormula &that) const
Definition: BlendFormula.h:57
OutputType fPrimaryOutputType
Definition: BlendFormula.h:163
Definition: GpuTools.h:21
static constexpr bool BlendCoeffsUseSrcColor(BlendCoeff srcCoeff, BlendCoeff dstCoeff)
Definition: Blend.h:118
static constexpr bool BlendAllowsCoverageAsAlpha(BlendEquation equation, BlendCoeff srcCoeff, BlendCoeff dstCoeff)
Definition: Blend.h:179
BlendEquation
Definition: Blend.h:26
BlendFormula GetBlendFormula(bool isOpaque, bool hasCoverage, SkBlendMode xfermode)
static constexpr bool BlendCoeffsUseDstColor(BlendCoeff srcCoeff, BlendCoeff dstCoeff, bool srcColorIsOpaque)
Definition: Blend.h:122
BlendCoeff
Definition: Blend.h:60
BlendFormula GetLCDBlendFormula(SkBlendMode xfermode)
static constexpr bool BlendModifiesDst(BlendEquation equation, BlendCoeff srcCoeff, BlendCoeff dstCoeff)
Definition: Blend.h:134
static constexpr bool BlendCoeffRefsSrc2(const BlendCoeff coeff)
Definition: Blend.h:113