1d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed/*
2d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed * Copyright 2006 The Android Open Source Project
3d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *
4d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed * Use of this source code is governed by a BSD-style license that can be
5d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed * found in the LICENSE file.
6d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed */
7d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
8d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#ifndef SkXfermodePriv_DEFINED
9d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#define SkXfermodePriv_DEFINED
10d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
11d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#include "SkBlendMode.h"
12d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#include "SkColor.h"
13d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#include "SkFlattenable.h"
14d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
15d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass GrFragmentProcessor;
16d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass GrTexture;
17d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass GrXPFactory;
18d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass SkRasterPipeline;
19d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass SkString;
20d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
21d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedstruct SkArithmeticParams;
22d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
23d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedstruct SkPM4f;
24d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedtypedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
25d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
26d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed/** \class SkXfermode
27d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *
28d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  SkXfermode is the base class for objects that are called to implement custom
29d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  "transfer-modes" in the drawing pipeline. The static function Create(Modes)
30d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  can be called to return an instance of any of the predefined subclasses as
31d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
32d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  then objects drawn with that paint have the xfermode applied.
33d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *
34d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  All subclasses are required to be reentrant-safe : it must be legal to share
35d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed *  the same instance between several threads.
36d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed */
37d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedclass SK_API SkXfermode : public SkFlattenable {
38d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedpublic:
39d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
40d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                        const SkAlpha aa[]) const;
41d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
42d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                        const SkAlpha aa[]) const;
43d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
44d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                        const SkAlpha aa[]) const;
45d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
46d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** Enum of possible coefficients to describe some xfermodes
47d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
48d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum Coeff {
49d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kZero_Coeff,    /** 0 */
50d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kOne_Coeff,     /** 1 */
51d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSC_Coeff,      /** src color */
52d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
53d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDC_Coeff,      /** dst color */
54d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
55d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSA_Coeff,      /** src alpha */
56d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
57d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDA_Coeff,      /** dst alpha */
58d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
59d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
60d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kCoeffCount
61d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
62d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
63d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** List of predefined xfermodes.
64d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        The algebra for the modes uses the following symbols:
65d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        Sa, Sc  - source alpha and color
66d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        Da, Dc - destination alpha and color (before compositing)
67d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        [a, c] - Resulting (alpha, color) values
68d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        For these equations, the colors are in premultiplied state.
69d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        If no xfermode is specified, kSrcOver is assumed.
70d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
71d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        that aren't Coeffs but have separable r,g,b computations, and finally
72d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        those that are not separable.
73d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
74d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum Mode {
75d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kClear_Mode,    //!< [0, 0]
76d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrc_Mode,      //!< [Sa, Sc]
77d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDst_Mode,      //!< [Da, Dc]
78d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcOver_Mode,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
79d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstOver_Mode,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
80d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
81d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstIn_Mode,    //!< [Da * Sa, Dc * Sa]
82d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
83d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
84d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcATop_Mode,  //!< [Da, Sc * Da + Dc * (1 - Sa)]
85d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstATop_Mode,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]
86d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
87d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kPlus_Mode,     //!< [Sa + Da, Sc + Dc]
88d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kModulate_Mode, // multiplies all components (= alpha and color)
89d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
90d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // Following blend modes are defined in the CSS Compositing standard:
91d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
92d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kScreen_Mode,
93d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kLastCoeffMode = kScreen_Mode,
94d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
95d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kOverlay_Mode,
96d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDarken_Mode,
97d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kLighten_Mode,
98d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kColorDodge_Mode,
99d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kColorBurn_Mode,
100d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kHardLight_Mode,
101d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSoftLight_Mode,
102d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDifference_Mode,
103d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kExclusion_Mode,
104d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kMultiply_Mode,
105d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kLastSeparableMode = kMultiply_Mode,
106d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
107d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kHue_Mode,
108d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSaturation_Mode,
109d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kColor_Mode,
110d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kLuminosity_Mode,
111d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kLastMode = kLuminosity_Mode
112d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
113d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
114d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
115d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     * Gets the name of the Mode as a string.
116d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
117d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static const char* ModeName(Mode);
118d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static const char* ModeName(SkBlendMode mode) {
119d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return ModeName(Mode(mode));
120d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
121d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
122d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
123d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  If the xfermode is one of the modes in the Mode enum, then asMode()
124d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  returns true and sets (if not null) mode accordingly. Otherwise it
125d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  returns false and ignores the mode parameter.
126d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
127d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual bool asMode(Mode* mode) const;
128d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
129d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
130d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  The same as calling xfermode->asMode(mode), except that this also checks
131d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
132d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
133d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool AsMode(const SkXfermode*, Mode* mode);
134d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool AsMode(const sk_sp<SkXfermode>& xfer, Mode* mode) {
135d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return AsMode(xfer.get(), mode);
136d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
137d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
138d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
139d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  Returns true if the xfermode claims to be the specified Mode. This works
140d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
141d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  you can say this without checking for a null...
142d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *
143d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  If (SkXfermode::IsMode(paint.getXfermode(),
144d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *                         SkXfermode::kDstOver_Mode)) {
145d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *      ...
146d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  }
147d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
148d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool IsMode(const SkXfermode* xfer, Mode mode);
149d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool IsMode(const sk_sp<SkXfermode>& xfer, Mode mode) {
150d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return IsMode(xfer.get(), mode);
151d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
152d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
153d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** Return an SkXfermode object for the specified mode.
154d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
155d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static sk_sp<SkXfermode> Make(SkBlendMode);
156d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static sk_sp<SkXfermode> Make(Mode m) { return Make((SkBlendMode)m); }
157d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
158d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
159d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  Skia maintains global xfermode objects corresponding to each BlendMode. This returns a
160d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  ptr to that global xfermode (or null if the mode is srcover). Thus the caller may use
161d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  the returned ptr, but it should leave its refcnt untouched.
162d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
163d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static SkXfermode* Peek(SkBlendMode mode) {
164d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        sk_sp<SkXfermode> xfer = Make(mode);
165d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        if (!xfer) {
166d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed            SkASSERT(SkBlendMode::kSrcOver == mode);
167d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed            return nullptr;
168d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        }
169d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        SkASSERT(!xfer->unique());
170d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return xfer.get();
171d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
172d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
173d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    SkBlendMode blend() const {
174d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        Mode mode;
175d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        SkAssertResult(this->asMode(&mode));
176d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return (SkBlendMode)mode;
177d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
178d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
179d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static SkXfermodeProc GetProc(SkBlendMode);
180d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static SkXfermodeProc4f GetProc4f(SkBlendMode);
181d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
182d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
183d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  If the specified mode can be represented by a pair of Coeff, then return
184d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  true and set (if not NULL) the corresponding coeffs. If the mode is
185d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  not representable as a pair of Coeffs, return false and ignore the
186d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  src and dst parameters.
187d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
188d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
189d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool ModeAsCoeff(SkBlendMode mode, Coeff* src, Coeff* dst) {
190d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return ModeAsCoeff((Mode)mode, src, dst);
191d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
192d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
193d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
194d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     * Returns whether or not the xfer mode can support treating coverage as alpha
195d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
196d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual bool supportsCoverageAsAlpha() const;
197d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
198d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
199d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
200d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
201d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
202d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
203d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool SupportsCoverageAsAlpha(const sk_sp<SkXfermode>& xfer) {
204d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return SupportsCoverageAsAlpha(xfer.get());
205d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
206d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
207d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum SrcColorOpacity {
208d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // The src color is known to be opaque (alpha == 255)
209d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kOpaque_SrcColorOpacity = 0,
210d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // The src color is known to be fully transparent (color == 0)
211d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kTransparentBlack_SrcColorOpacity = 1,
212d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // The src alpha is known to be fully transparent (alpha == 0)
213d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kTransparentAlpha_SrcColorOpacity = 2,
214d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        // The src color opacity is unknown
215d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kUnknown_SrcColorOpacity = 3
216d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
217d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
218d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
219d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
220d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     * input to this call is an enum describing known information about the opacity of the src color
221d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     * that will be given to the xfer mode.
222d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
223d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual bool isOpaque(SrcColorOpacity opacityType) const;
224d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
225d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /**
226d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  The same as calling xfermode->isOpaque(...), except that this also checks if
227d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     *  the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
228d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
229d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
230d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool IsOpaque(const sk_sp<SkXfermode>& xfer, SrcColorOpacity opacityType) {
231d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        return IsOpaque(xfer.get(), opacityType);
232d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    }
233d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static bool IsOpaque(SkBlendMode, SrcColorOpacity);
234d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
235d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#if SK_SUPPORT_GPU
236d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
237d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        The input to the returned FP is the src color. The dst color is
238d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        provided by the dst param which becomes a child FP of the returned FP.
239d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        It is legal for the function to return a null output. This indicates that
240d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        the output of the blend is simply the src color.
241d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed     */
242d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
243d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                                                            sk_sp<GrFragmentProcessor> dst) const;
244d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
245d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** A subclass must implement this factory function to work with the GPU backend.
246d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        The xfermode will return a factory for which the caller will get a ref. It is up
247d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        to the caller to install it. XferProcessors cannot use a background texture.
248d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed      */
249a16339297859f37df69230e64f05624cef511ad3Brian Salomon    virtual const GrXPFactory* asXPFactory() const;
250d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#endif
251d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
252d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    SK_TO_STRING_PUREVIRT()
253d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
254d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
255d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
256d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum D32Flags {
257d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsOpaque_D32Flag  = 1 << 0,
258d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsSingle_D32Flag  = 1 << 1,
259d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstIsSRGB_D32Flag    = 1 << 2,
260d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
261d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    typedef void (*D32Proc)(SkBlendMode, uint32_t dst[], const SkPM4f src[],
262d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                            int count, const SkAlpha coverage[]);
263d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static D32Proc GetD32Proc(SkBlendMode, uint32_t flags);
264d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
265d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum F16Flags {
266d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsOpaque_F16Flag  = 1 << 0,
267d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsSingle_F16Flag  = 1 << 1,
268d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
269d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    typedef void (*F16Proc)(SkBlendMode, uint64_t dst[], const SkPM4f src[], int count,
270d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed                            const SkAlpha coverage[]);
271d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static F16Proc GetF16Proc(SkBlendMode, uint32_t flags);
272d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
273d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum LCDFlags {
274d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsOpaque_LCDFlag    = 1 << 0,   // else src(s) may have alpha < 1
275d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kSrcIsSingle_LCDFlag    = 1 << 1,   // else src[count]
276d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kDstIsSRGB_LCDFlag      = 1 << 2,   // else l32 or f16
277d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
278d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
279d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    typedef void (*LCDF16Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
280d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static LCD32Proc GetLCD32Proc(uint32_t flags);
281d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    static LCDF16Proc GetLCDF16Proc(uint32_t) { return nullptr; }
282d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
283d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual bool isArithmetic(SkArithmeticParams*) const { return false; }
284d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
285d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedprotected:
286d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    SkXfermode() {}
287d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    /** The default implementation of xfer32/xfer16/xferA8 in turn call this
288d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        method, 1 color at a time (upscaled to a SkPMColor). The default
289d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        implementation of this method just returns dst. If performance is
290d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        important, your subclass should override xfer32/xfer16/xferA8 directly.
291d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
292d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        This method will not be called directly by the client, so it need not
293d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        be implemented if your subclass has overridden xfer32/xfer16/xferA8
294d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    */
295d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
296d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
297d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reedprivate:
298d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    enum {
299d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed        kModeCount = kLastMode + 1
300d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    };
301d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
302d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed    typedef SkFlattenable INHERITED;
303d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed};
304d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed
305d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#endif
306