blob: 95494529608da5a4a7642b91be7588cc3b34d319 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkXfermode_DEFINED
11#define SkXfermode_DEFINED
12
13#include "SkFlattenable.h"
14#include "SkColor.h"
15
joshualittb0a8a372014-09-23 09:50:21 -070016class GrFragmentProcessor;
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000017class GrTexture;
egdaniel378092f2014-12-03 10:40:13 -080018class GrXPFactory;
robertphillips@google.comb83b6b42013-01-22 14:32:09 +000019class SkString;
20
reed@android.com8a1c16f2008-12-17 15:59:43 +000021/** \class SkXfermode
reed@google.comfb6deed2013-10-10 17:35:58 +000022 *
23 * SkXfermode is the base class for objects that are called to implement custom
24 * "transfer-modes" in the drawing pipeline. The static function Create(Modes)
25 * can be called to return an instance of any of the predefined subclasses as
26 * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
27 * then objects drawn with that paint have the xfermode applied.
28 *
29 * All subclasses are required to be reentrant-safe : it must be legal to share
30 * the same instance between several threads.
31 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000032class SK_API SkXfermode : public SkFlattenable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000033public:
reed@android.com8a1c16f2008-12-17 15:59:43 +000034 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000035 const SkAlpha aa[]) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000036 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000037 const SkAlpha aa[]) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000038 virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
reed@google.com30da7452012-12-17 19:55:24 +000039 const SkAlpha aa[]) const;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000040
reed@android.comd252db02009-04-01 18:31:44 +000041 /** Enum of possible coefficients to describe some xfermodes
42 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 enum Coeff {
reed@android.comd252db02009-04-01 18:31:44 +000044 kZero_Coeff, /** 0 */
45 kOne_Coeff, /** 1 */
46 kSC_Coeff, /** src color */
47 kISC_Coeff, /** inverse src color (i.e. 1 - sc) */
48 kDC_Coeff, /** dst color */
49 kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */
50 kSA_Coeff, /** src alpha */
51 kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */
52 kDA_Coeff, /** dst alpha */
53 kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000054
reed@android.com8a1c16f2008-12-17 15:59:43 +000055 kCoeffCount
56 };
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000057
reed@android.coma0f5d152009-06-22 17:38:10 +000058 /** List of predefined xfermodes.
59 The algebra for the modes uses the following symbols:
60 Sa, Sc - source alpha and color
61 Da, Dc - destination alpha and color (before compositing)
62 [a, c] - Resulting (alpha, color) values
63 For these equations, the colors are in premultiplied state.
64 If no xfermode is specified, kSrcOver is assumed.
bsalomon@google.com8da9bc72013-04-19 15:03:21 +000065 The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
66 that aren't Coeffs but have separable r,g,b computations, and finally
67 those that are not separable.
reed@android.coma0f5d152009-06-22 17:38:10 +000068 */
69 enum Mode {
70 kClear_Mode, //!< [0, 0]
71 kSrc_Mode, //!< [Sa, Sc]
72 kDst_Mode, //!< [Da, Dc]
pkasting129319f2015-10-29 08:41:15 -070073 kSrcOver_Mode, //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
74 kDstOver_Mode, //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
reed@android.coma0f5d152009-06-22 17:38:10 +000075 kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
pkasting129319f2015-10-29 08:41:15 -070076 kDstIn_Mode, //!< [Da * Sa, Dc * Sa]
reed@android.coma0f5d152009-06-22 17:38:10 +000077 kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
78 kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
pkasting129319f2015-10-29 08:41:15 -070079 kSrcATop_Mode, //!< [Da, Sc * Da + Dc * (1 - Sa)]
80 kDstATop_Mode, //!< [Sa, Dc * Sa + Sc * (1 - Da)]
81 kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +000082 kPlus_Mode, //!< [Sa + Da, Sc + Dc]
reed@google.com8d3cd7a2013-01-30 21:36:11 +000083 kModulate_Mode, // multiplies all components (= alpha and color)
rmistry@google.comfbfcd562012-08-23 18:09:54 +000084
skia.committer@gmail.com64334352013-03-06 07:01:46 +000085 // Following blend modes are defined in the CSS Compositing standard:
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +000086 // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
bsalomon@google.comb0091b82013-04-15 15:16:47 +000087 kScreen_Mode,
bsalomon@google.com8da9bc72013-04-19 15:03:21 +000088 kLastCoeffMode = kScreen_Mode,
89
90 kOverlay_Mode,
reed@android.coma0f5d152009-06-22 17:38:10 +000091 kDarken_Mode,
92 kLighten_Mode,
93 kColorDodge_Mode,
94 kColorBurn_Mode,
95 kHardLight_Mode,
96 kSoftLight_Mode,
97 kDifference_Mode,
98 kExclusion_Mode,
reed@google.com25cfa692013-02-04 20:06:00 +000099 kMultiply_Mode,
bsalomon@google.com8da9bc72013-04-19 15:03:21 +0000100 kLastSeparableMode = kMultiply_Mode,
reed@android.coma0f5d152009-06-22 17:38:10 +0000101
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000102 kHue_Mode,
103 kSaturation_Mode,
104 kColor_Mode,
105 kLuminosity_Mode,
commit-bot@chromium.orgb24f8932013-03-05 16:23:59 +0000106 kLastMode = kLuminosity_Mode
reed@android.coma0f5d152009-06-22 17:38:10 +0000107 };
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000108
commit-bot@chromium.orgd7aaf602013-04-01 12:51:34 +0000109 /**
110 * Gets the name of the Mode as a string.
111 */
112 static const char* ModeName(Mode);
reed@android.coma0f5d152009-06-22 17:38:10 +0000113
reed@google.comc0d4aa22011-04-13 21:12:04 +0000114 /**
115 * If the xfermode is one of the modes in the Mode enum, then asMode()
116 * returns true and sets (if not null) mode accordingly. Otherwise it
117 * returns false and ignores the mode parameter.
vandebo@chromium.org48543272011-02-08 19:28:07 +0000118 */
reed@google.com30da7452012-12-17 19:55:24 +0000119 virtual bool asMode(Mode* mode) const;
vandebo@chromium.org48543272011-02-08 19:28:07 +0000120
reed@google.com43c50c82011-04-14 15:50:52 +0000121 /**
122 * The same as calling xfermode->asMode(mode), except that this also checks
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000123 * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
reed@google.com43c50c82011-04-14 15:50:52 +0000124 */
reed@google.com30da7452012-12-17 19:55:24 +0000125 static bool AsMode(const SkXfermode*, Mode* mode);
reed@google.com43c50c82011-04-14 15:50:52 +0000126
mike@reedtribe.orge303fcf2011-11-17 02:16:43 +0000127 /**
128 * Returns true if the xfermode claims to be the specified Mode. This works
129 * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
130 * you can say this without checking for a null...
131 *
132 * If (SkXfermode::IsMode(paint.getXfermode(),
133 * SkXfermode::kDstOver_Mode)) {
134 * ...
135 * }
136 */
reed@google.com30da7452012-12-17 19:55:24 +0000137 static bool IsMode(const SkXfermode* xfer, Mode mode);
mike@reedtribe.orge303fcf2011-11-17 02:16:43 +0000138
reed@android.coma0f5d152009-06-22 17:38:10 +0000139 /** Return an SkXfermode object for the specified mode.
140 */
141 static SkXfermode* Create(Mode mode);
142
143 /** Return a function pointer to a routine that applies the specified
144 porter-duff transfer mode.
145 */
146 static SkXfermodeProc GetProc(Mode mode);
reed31255652016-02-08 12:56:56 -0800147 static SkXfermodeProc4f GetProc4f(Mode);
reed@android.coma0f5d152009-06-22 17:38:10 +0000148
reed@google.comc0d4aa22011-04-13 21:12:04 +0000149 /**
reed@google.com43c50c82011-04-14 15:50:52 +0000150 * If the specified mode can be represented by a pair of Coeff, then return
151 * true and set (if not NULL) the corresponding coeffs. If the mode is
152 * not representable as a pair of Coeffs, return false and ignore the
153 * src and dst parameters.
reed@android.coma0f5d152009-06-22 17:38:10 +0000154 */
reed@google.com43c50c82011-04-14 15:50:52 +0000155 static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
reed@android.coma0f5d152009-06-22 17:38:10 +0000156
reed@google.com44699382013-10-31 17:28:30 +0000157 SK_ATTR_DEPRECATED("use AsMode(...)")
reed@google.com30da7452012-12-17 19:55:24 +0000158 static bool IsMode(const SkXfermode* xfer, Mode* mode) {
reed@google.com43c50c82011-04-14 15:50:52 +0000159 return AsMode(xfer, mode);
160 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000161
egdanieldcfb7cf2015-01-22 06:52:29 -0800162 /**
163 * Returns whether or not the xfer mode can support treating coverage as alpha
mtklein2766c002015-06-26 11:45:03 -0700164 */
egdanieldcfb7cf2015-01-22 06:52:29 -0800165 virtual bool supportsCoverageAsAlpha() const;
166
167 /**
168 * The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
169 * the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
170 */
171 static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
172
173 enum SrcColorOpacity {
174 // The src color is known to be opaque (alpha == 255)
175 kOpaque_SrcColorOpacity = 0,
176 // The src color is known to be fully transparent (color == 0)
177 kTransparentBlack_SrcColorOpacity = 1,
178 // The src alpha is known to be fully transparent (alpha == 0)
179 kTransparentAlpha_SrcColorOpacity = 2,
180 // The src color opacity is unknown
181 kUnknown_SrcColorOpacity = 3
182 };
183
184 /**
185 * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
186 * input to this call is an enum describing known information about the opacity of the src color
187 * that will be given to the xfer mode.
188 */
189 virtual bool isOpaque(SrcColorOpacity opacityType) const;
190
191 /**
192 * The same as calling xfermode->isOpaque(...), except that this also checks if
193 * the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
194 */
195 static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
196
bsalomonae4738f2015-09-15 15:33:27 -0700197 /** Used to do in-shader blending between two colors computed in the shader via a
198 GrFragmentProcessor. The input to the returned FP is the src color. The dst color is
199 provided by the dst param which becomes a child FP of the returned FP. If the params are
200 null then this is just a query of whether the SkXfermode could support this functionality.
201 It is legal for the function to succeed but return a null output. This indicates that
202 the output of the blend is simply the src color.
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000203 */
bsalomon4a339522015-10-06 08:40:50 -0700204 virtual bool asFragmentProcessor(const GrFragmentProcessor** output,
bsalomonae4738f2015-09-15 15:33:27 -0700205 const GrFragmentProcessor* dst) const;
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000206
egdaniel378092f2014-12-03 10:40:13 -0800207 /** A subclass may implement this factory function to work with the GPU backend. It is legal
egdanielc4b72722015-11-23 13:20:41 -0800208 to call this with xpf NULL to simply test the return value. If xpf is non-NULL then the
209 xfermode may optionally allocate a factory to return to the caller as *xpf. The caller
210 will install it and own a ref to it. Since the xfermode may or may not assign *xpf, the
211 caller should set *xpf to NULL beforehand. XferProcessors cannot use a background texture.
212 */
egdanielf2342722015-11-20 15:12:59 -0800213 virtual bool asXPFactory(GrXPFactory** xpf) const;
egdaniel378092f2014-12-03 10:40:13 -0800214
egdaniel58136162015-01-20 10:19:22 -0800215 /** Returns true if the xfermode can be expressed as an xfer processor factory (xpFactory).
egdanielc4b72722015-11-23 13:20:41 -0800216 This helper calls the asXPFactory() virtual. If the xfermode is NULL, it is treated as
217 kSrcOver_Mode. It is legal to call this with xpf param NULL to simply test the return value.
218 */
219 static inline bool AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
220 if (nullptr == xfermode) {
221 if (xpf) {
222 *xpf = nullptr;
223 }
224 return true;
225 }
226 return xfermode->asXPFactory(xpf);
227 }
bsalomon@google.comf51c0132013-03-27 18:31:15 +0000228
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000229 SK_TO_STRING_PUREVIRT()
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000230 SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000231 SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
232
reed395eabe2016-01-30 18:52:31 -0800233 enum PM4fFlags {
234 kSrcIsOpaque_PM4fFlag = 1 << 0,
235 kDstIsSRGB_PM4fFlag = 1 << 1,
236 };
237 struct PM4fState {
238 const SkXfermode* fXfer;
239 uint32_t fFlags;
240 };
241 typedef void (*PM4fProc1)(const PM4fState&, uint32_t dst[], const SkPM4f& src,
242 int count, const SkAlpha coverage[]);
243 typedef void (*PM4fProcN)(const PM4fState&, uint32_t dst[], const SkPM4f src[],
244 int count, const SkAlpha coverage[]);
reed31255652016-02-08 12:56:56 -0800245
reed395eabe2016-01-30 18:52:31 -0800246 static PM4fProc1 GetPM4fProc1(Mode, uint32_t flags);
247 static PM4fProcN GetPM4fProcN(Mode, uint32_t flags);
248 virtual PM4fProc1 getPM4fProc1(uint32_t flags) const;
249 virtual PM4fProcN getPM4fProcN(uint32_t flags) const;
250
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251protected:
commit-bot@chromium.orgbd0be252014-05-15 15:40:41 +0000252 SkXfermode() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253 /** The default implementation of xfer32/xfer16/xferA8 in turn call this
254 method, 1 color at a time (upscaled to a SkPMColor). The default
bsalomonae4738f2015-09-15 15:33:27 -0700255 implementation of this method just returns dst. If performance is
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 important, your subclass should override xfer32/xfer16/xferA8 directly.
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000257
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258 This method will not be called directly by the client, so it need not
259 be implemented if your subclass has overridden xfer32/xfer16/xferA8
260 */
reed@google.com30da7452012-12-17 19:55:24 +0000261 virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262
263private:
reed@android.coma0f5d152009-06-22 17:38:10 +0000264 enum {
265 kModeCount = kLastMode + 1
266 };
commit-bot@chromium.org86490572013-10-04 16:52:55 +0000267
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268 typedef SkFlattenable INHERITED;
269};
270
reed@android.com8a1c16f2008-12-17 15:59:43 +0000271#endif