1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h"
11cb93a386Sopenharmony_ci#include "include/private/SkMacros.h"
12cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrBlend.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrProcessor.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrProcessorAnalysis.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h"
19cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLBlend.h"
20cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
21cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
22cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLUniformHandler.h"
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci/**
25cb93a386Sopenharmony_ci * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
26cb93a386Sopenharmony_ci */
27cb93a386Sopenharmony_ciclass BlendFormula {
28cb93a386Sopenharmony_cipublic:
29cb93a386Sopenharmony_ci    /**
30cb93a386Sopenharmony_ci     * Values the shader can write to primary and secondary outputs. These are all modulated by
31cb93a386Sopenharmony_ci     * coverage. The XP will ignore the multiplies when not using coverage.
32cb93a386Sopenharmony_ci     */
33cb93a386Sopenharmony_ci    enum OutputType {
34cb93a386Sopenharmony_ci        kNone_OutputType,        //<! 0
35cb93a386Sopenharmony_ci        kCoverage_OutputType,    //<! inputCoverage
36cb93a386Sopenharmony_ci        kModulate_OutputType,    //<! inputColor * inputCoverage
37cb93a386Sopenharmony_ci        kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
38cb93a386Sopenharmony_ci        kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
39cb93a386Sopenharmony_ci        kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci        kLast_OutputType = kISCModulate_OutputType
42cb93a386Sopenharmony_ci    };
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation,
45cb93a386Sopenharmony_ci                           GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff)
46cb93a386Sopenharmony_ci            : fPrimaryOutputType(primaryOut)
47cb93a386Sopenharmony_ci            , fSecondaryOutputType(secondaryOut)
48cb93a386Sopenharmony_ci            , fBlendEquation(equation)
49cb93a386Sopenharmony_ci            , fSrcCoeff(srcCoeff)
50cb93a386Sopenharmony_ci            , fDstCoeff(dstCoeff)
51cb93a386Sopenharmony_ci            , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    BlendFormula(const BlendFormula&) = default;
54cb93a386Sopenharmony_ci    BlendFormula& operator=(const BlendFormula&) = default;
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    bool operator==(const BlendFormula& that) const {
57cb93a386Sopenharmony_ci        return fPrimaryOutputType == that.fPrimaryOutputType &&
58cb93a386Sopenharmony_ci               fSecondaryOutputType == that. fSecondaryOutputType &&
59cb93a386Sopenharmony_ci               fBlendEquation == that.fBlendEquation &&
60cb93a386Sopenharmony_ci               fSrcCoeff == that.fSrcCoeff &&
61cb93a386Sopenharmony_ci               fDstCoeff == that.fDstCoeff &&
62cb93a386Sopenharmony_ci               fProps == that.fProps;
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    bool hasSecondaryOutput() const {
66cb93a386Sopenharmony_ci        return kNone_OutputType != fSecondaryOutputType;
67cb93a386Sopenharmony_ci    }
68cb93a386Sopenharmony_ci    bool modifiesDst() const {
69cb93a386Sopenharmony_ci        return SkToBool(fProps & kModifiesDst_Property);
70cb93a386Sopenharmony_ci    }
71cb93a386Sopenharmony_ci    bool unaffectedByDst() const {
72cb93a386Sopenharmony_ci        return SkToBool(fProps & kUnaffectedByDst_Property);
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci    // We don't always fully optimize the blend formula (e.g., for opaque src-over), so we include
75cb93a386Sopenharmony_ci    // an "IfOpaque" variant to help set AnalysisProperties::kUnaffectedByDstValue in those cases.
76cb93a386Sopenharmony_ci    bool unaffectedByDstIfOpaque() const {
77cb93a386Sopenharmony_ci        return SkToBool(fProps & kUnaffectedByDstIfOpaque_Property);
78cb93a386Sopenharmony_ci    }
79cb93a386Sopenharmony_ci    bool usesInputColor() const {
80cb93a386Sopenharmony_ci        return SkToBool(fProps & kUsesInputColor_Property);
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci    bool canTweakAlphaForCoverage() const {
83cb93a386Sopenharmony_ci        return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
84cb93a386Sopenharmony_ci    }
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    GrBlendEquation equation() const {
87cb93a386Sopenharmony_ci        return fBlendEquation;
88cb93a386Sopenharmony_ci    }
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    GrBlendCoeff srcCoeff() const {
91cb93a386Sopenharmony_ci        return fSrcCoeff;
92cb93a386Sopenharmony_ci    }
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    GrBlendCoeff dstCoeff() const {
95cb93a386Sopenharmony_ci        return fDstCoeff;
96cb93a386Sopenharmony_ci    }
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    OutputType primaryOutput() const {
99cb93a386Sopenharmony_ci        return fPrimaryOutputType;
100cb93a386Sopenharmony_ci    }
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    OutputType secondaryOutput() const {
103cb93a386Sopenharmony_ci        return fSecondaryOutputType;
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ciprivate:
107cb93a386Sopenharmony_ci    enum Properties {
108cb93a386Sopenharmony_ci        kModifiesDst_Property              = 1 << 0,
109cb93a386Sopenharmony_ci        kUnaffectedByDst_Property          = 1 << 1,
110cb93a386Sopenharmony_ci        kUnaffectedByDstIfOpaque_Property  = 1 << 2,
111cb93a386Sopenharmony_ci        kUsesInputColor_Property           = 1 << 3,
112cb93a386Sopenharmony_ci        kCanTweakAlphaForCoverage_Property = 1 << 4,
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci        kLast_Property = kCanTweakAlphaForCoverage_Property
115cb93a386Sopenharmony_ci    };
116cb93a386Sopenharmony_ci    SK_DECL_BITFIELD_OPS_FRIENDS(Properties)
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    /**
119cb93a386Sopenharmony_ci     * Deduce the properties of a BlendFormula.
120cb93a386Sopenharmony_ci     */
121cb93a386Sopenharmony_ci    static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut,
122cb93a386Sopenharmony_ci                                              GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff,
123cb93a386Sopenharmony_ci                                              GrBlendCoeff DstCoeff);
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci    struct {
126cb93a386Sopenharmony_ci        // We allot the enums one more bit than they require because MSVC seems to sign-extend
127cb93a386Sopenharmony_ci        // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
128cb93a386Sopenharmony_ci        OutputType        fPrimaryOutputType    : 4;
129cb93a386Sopenharmony_ci        OutputType        fSecondaryOutputType  : 4;
130cb93a386Sopenharmony_ci        GrBlendEquation   fBlendEquation        : 6;
131cb93a386Sopenharmony_ci        GrBlendCoeff      fSrcCoeff             : 6;
132cb93a386Sopenharmony_ci        GrBlendCoeff      fDstCoeff             : 6;
133cb93a386Sopenharmony_ci        Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
134cb93a386Sopenharmony_ci    };
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    static_assert(kLast_OutputType      < (1 << 3));
137cb93a386Sopenharmony_ci    static_assert(kLast_GrBlendEquation < (1 << 5));
138cb93a386Sopenharmony_ci    static_assert(kLast_GrBlendCoeff    < (1 << 5));
139cb93a386Sopenharmony_ci    static_assert(kLast_Property        < (1 << 6));
140cb93a386Sopenharmony_ci};
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_cistatic_assert(4 == sizeof(BlendFormula));
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ciSK_MAKE_BITFIELD_OPS(BlendFormula::Properties)
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ciconstexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut,
147cb93a386Sopenharmony_ci                                                               OutputType SecondaryOut,
148cb93a386Sopenharmony_ci                                                               GrBlendEquation BlendEquation,
149cb93a386Sopenharmony_ci                                                               GrBlendCoeff SrcCoeff,
150cb93a386Sopenharmony_ci                                                               GrBlendCoeff DstCoeff) {
151cb93a386Sopenharmony_ci    return
152cb93a386Sopenharmony_ci    // The provided formula should already be optimized before a BlendFormula is constructed.
153cb93a386Sopenharmony_ci    // Assert that here while setting up the properties in the constexpr constructor.
154cb93a386Sopenharmony_ci    SkASSERT((kNone_OutputType == PrimaryOut) == !GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)),
155cb93a386Sopenharmony_ci    SkASSERT(!GrBlendCoeffRefsSrc2(SrcCoeff)),
156cb93a386Sopenharmony_ci    SkASSERT((kNone_OutputType == SecondaryOut) == !GrBlendCoeffRefsSrc2(DstCoeff)),
157cb93a386Sopenharmony_ci    SkASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut),
158cb93a386Sopenharmony_ci    SkASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut),
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci    static_cast<Properties>(
161cb93a386Sopenharmony_ci        (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) |
162cb93a386Sopenharmony_ci        (!GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff, false/*srcColorIsOpaque*/)
163cb93a386Sopenharmony_ci                    ? kUnaffectedByDst_Property
164cb93a386Sopenharmony_ci                    : 0) |
165cb93a386Sopenharmony_ci        (!GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff, true/*srcColorIsOpaque*/)
166cb93a386Sopenharmony_ci                    ? kUnaffectedByDstIfOpaque_Property
167cb93a386Sopenharmony_ci                    : 0) |
168cb93a386Sopenharmony_ci        ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
169cb93a386Sopenharmony_ci                            (SecondaryOut >= kModulate_OutputType &&
170cb93a386Sopenharmony_ci                            GrBlendCoeffRefsSrc2(DstCoeff))
171cb93a386Sopenharmony_ci                    ? kUsesInputColor_Property
172cb93a386Sopenharmony_ci                    : 0) |  // We assert later that SrcCoeff doesn't ref src2.
173cb93a386Sopenharmony_ci        ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
174cb93a386Sopenharmony_ci                            kNone_OutputType == SecondaryOut &&
175cb93a386Sopenharmony_ci                            GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff)
176cb93a386Sopenharmony_ci                    ? kCanTweakAlphaForCoverage_Property
177cb93a386Sopenharmony_ci                    : 0));
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ci/**
181cb93a386Sopenharmony_ci * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
182cb93a386Sopenharmony_ci * Porter Duff formula.
183cb93a386Sopenharmony_ci */
184cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
185cb93a386Sopenharmony_ci    // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none.
186cb93a386Sopenharmony_ci    return (kZero_GrBlendCoeff == srcCoeff &&
187cb93a386Sopenharmony_ci            (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff))
188cb93a386Sopenharmony_ci           ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType,
189cb93a386Sopenharmony_ci                          kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff)
190cb93a386Sopenharmony_ci           : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType,
191cb93a386Sopenharmony_ci                        kAdd_GrBlendEquation, srcCoeff, dstCoeff);
192cb93a386Sopenharmony_ci}
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci/**
195cb93a386Sopenharmony_ci * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in
196cb93a386Sopenharmony_ci * LCD dst-out.
197cb93a386Sopenharmony_ci */
198cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
199cb93a386Sopenharmony_ci    return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType,
200cb93a386Sopenharmony_ci                        kAdd_GrBlendEquation, srcCoeff, dstCoeff);
201cb93a386Sopenharmony_ci}
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci/**
204cb93a386Sopenharmony_ci * When there is coverage, the equation with f=coverage is:
205cb93a386Sopenharmony_ci *
206cb93a386Sopenharmony_ci *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
207cb93a386Sopenharmony_ci *
208cb93a386Sopenharmony_ci * This can be rewritten as:
209cb93a386Sopenharmony_ci *
210cb93a386Sopenharmony_ci *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
211cb93a386Sopenharmony_ci *
212cb93a386Sopenharmony_ci * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
213cb93a386Sopenharmony_ci * HW dst coeff with IS2C.
214cb93a386Sopenharmony_ci *
215cb93a386Sopenharmony_ci * Xfer modes: dst-atop (Sa!=1)
216cb93a386Sopenharmony_ci */
217cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageFormula(
218cb93a386Sopenharmony_ci        BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) {
219cb93a386Sopenharmony_ci    return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput,
220cb93a386Sopenharmony_ci                        kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff);
221cb93a386Sopenharmony_ci}
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci/**
224cb93a386Sopenharmony_ci * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
225cb93a386Sopenharmony_ci *
226cb93a386Sopenharmony_ci *   D' = f * D * dstCoeff + (1-f) * D
227cb93a386Sopenharmony_ci *
228cb93a386Sopenharmony_ci * This can be rewritten as:
229cb93a386Sopenharmony_ci *
230cb93a386Sopenharmony_ci *   D' = D - D * [f * (1 - dstCoeff)]
231cb93a386Sopenharmony_ci *
232cb93a386Sopenharmony_ci * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
233cb93a386Sopenharmony_ci * subtract HW blend equation with coeffs of (DC, One).
234cb93a386Sopenharmony_ci *
235cb93a386Sopenharmony_ci * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
236cb93a386Sopenharmony_ci */
237cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula(
238cb93a386Sopenharmony_ci        BlendFormula::OutputType oneMinusDstCoeffModulateOutput) {
239cb93a386Sopenharmony_ci    return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType,
240cb93a386Sopenharmony_ci                        kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff);
241cb93a386Sopenharmony_ci}
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci/**
244cb93a386Sopenharmony_ci * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
245cb93a386Sopenharmony_ci *
246cb93a386Sopenharmony_ci *   D' = f * S * srcCoeff + (1-f) * D
247cb93a386Sopenharmony_ci *
248cb93a386Sopenharmony_ci * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
249cb93a386Sopenharmony_ci * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
250cb93a386Sopenharmony_ci *
251cb93a386Sopenharmony_ci * Xfer modes (Sa!=1): src, src-in, src-out
252cb93a386Sopenharmony_ci */
253cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) {
254cb93a386Sopenharmony_ci    return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType,
255cb93a386Sopenharmony_ci                        kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff);
256cb93a386Sopenharmony_ci}
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci/**
259cb93a386Sopenharmony_ci * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
260cb93a386Sopenharmony_ci * with and without an opaque input color. Optimization properties are deduced at compile time so we
261cb93a386Sopenharmony_ci * can make runtime decisions quickly. RGB coverage is not supported.
262cb93a386Sopenharmony_ci */
263cb93a386Sopenharmony_cistatic constexpr BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
264cb93a386Sopenharmony_ci                     /*>> No coverage, input color unknown <<*/ {{
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ci    /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
267cb93a386Sopenharmony_ci    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
268cb93a386Sopenharmony_ci    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
269cb93a386Sopenharmony_ci    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
270cb93a386Sopenharmony_ci    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
271cb93a386Sopenharmony_ci    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
272cb93a386Sopenharmony_ci    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff),
273cb93a386Sopenharmony_ci    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
274cb93a386Sopenharmony_ci    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
275cb93a386Sopenharmony_ci    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
276cb93a386Sopenharmony_ci    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kSA_GrBlendCoeff),
277cb93a386Sopenharmony_ci    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
278cb93a386Sopenharmony_ci    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
279cb93a386Sopenharmony_ci    /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
280cb93a386Sopenharmony_ci    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci                     }, /*>> Has coverage, input color unknown <<*/ {
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
285cb93a386Sopenharmony_ci    /* src */        MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff),
286cb93a386Sopenharmony_ci    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
287cb93a386Sopenharmony_ci    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
288cb93a386Sopenharmony_ci    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
289cb93a386Sopenharmony_ci    /* src-in */     MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff),
290cb93a386Sopenharmony_ci    /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
291cb93a386Sopenharmony_ci    /* src-out */    MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff),
292cb93a386Sopenharmony_ci    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
293cb93a386Sopenharmony_ci    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
294cb93a386Sopenharmony_ci    /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
295cb93a386Sopenharmony_ci    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
296cb93a386Sopenharmony_ci    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
297cb93a386Sopenharmony_ci    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
298cb93a386Sopenharmony_ci    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci                     }}, /*>> No coverage, input color opaque <<*/ {{
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_ci    /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
303cb93a386Sopenharmony_ci    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
304cb93a386Sopenharmony_ci    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
305cb93a386Sopenharmony_ci    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff), // see comment below
306cb93a386Sopenharmony_ci    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
307cb93a386Sopenharmony_ci    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
308cb93a386Sopenharmony_ci    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
309cb93a386Sopenharmony_ci    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
310cb93a386Sopenharmony_ci    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
311cb93a386Sopenharmony_ci    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
312cb93a386Sopenharmony_ci    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
313cb93a386Sopenharmony_ci    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
314cb93a386Sopenharmony_ci    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
315cb93a386Sopenharmony_ci    /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
316cb93a386Sopenharmony_ci    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_ci                     }, /*>> Has coverage, input color opaque <<*/ {
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_ci    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
321cb93a386Sopenharmony_ci    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
322cb93a386Sopenharmony_ci    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
323cb93a386Sopenharmony_ci    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
324cb93a386Sopenharmony_ci    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
325cb93a386Sopenharmony_ci    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
326cb93a386Sopenharmony_ci    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
327cb93a386Sopenharmony_ci    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
328cb93a386Sopenharmony_ci    /* dst-out */    MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
329cb93a386Sopenharmony_ci    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
330cb93a386Sopenharmony_ci    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
331cb93a386Sopenharmony_ci    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
332cb93a386Sopenharmony_ci    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
333cb93a386Sopenharmony_ci    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
334cb93a386Sopenharmony_ci    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
335cb93a386Sopenharmony_ci}}};
336cb93a386Sopenharmony_ci// In the above table src-over is not optimized to src mode when the color is opaque because we
337cb93a386Sopenharmony_ci// found no advantage to doing so. Also, we are using a global src-over XP in most cases which is
338cb93a386Sopenharmony_ci// not specialized for opaque input. For GPUs where dropping to src (and thus able to disable
339cb93a386Sopenharmony_ci// blending) is an advantage we change the blend mode to src before getitng the blend formula from
340cb93a386Sopenharmony_ci// this table.
341cb93a386Sopenharmony_cistatic constexpr BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
342cb93a386Sopenharmony_ci    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
343cb93a386Sopenharmony_ci    /* src */        MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
344cb93a386Sopenharmony_ci    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
345cb93a386Sopenharmony_ci    /* src-over */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
346cb93a386Sopenharmony_ci    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
347cb93a386Sopenharmony_ci    /* src-in */     MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
348cb93a386Sopenharmony_ci    /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
349cb93a386Sopenharmony_ci    /* src-out */    MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
350cb93a386Sopenharmony_ci    /* dst-out */    MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff),
351cb93a386Sopenharmony_ci    /* src-atop */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
352cb93a386Sopenharmony_ci    /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
353cb93a386Sopenharmony_ci    /* xor */        MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
354cb93a386Sopenharmony_ci    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff),
355cb93a386Sopenharmony_ci    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
356cb93a386Sopenharmony_ci    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff),
357cb93a386Sopenharmony_ci};
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_cistatic BlendFormula get_blend_formula(bool isOpaque,
360cb93a386Sopenharmony_ci                                      bool hasCoverage,
361cb93a386Sopenharmony_ci                                      SkBlendMode xfermode) {
362cb93a386Sopenharmony_ci    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
363cb93a386Sopenharmony_ci    return gBlendTable[isOpaque][hasCoverage][(int)xfermode];
364cb93a386Sopenharmony_ci}
365cb93a386Sopenharmony_ci
366cb93a386Sopenharmony_cistatic BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
367cb93a386Sopenharmony_ci    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci    return gLCDBlendTable[(int)xfermode];
370cb93a386Sopenharmony_ci}
371cb93a386Sopenharmony_ci
372cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ciclass PorterDuffXferProcessor : public GrXferProcessor {
375cb93a386Sopenharmony_cipublic:
376cb93a386Sopenharmony_ci    PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage)
377cb93a386Sopenharmony_ci            : INHERITED(kPorterDuffXferProcessor_ClassID, /*willReadDstColor=*/false, coverage)
378cb93a386Sopenharmony_ci            , fBlendFormula(blendFormula) {
379cb93a386Sopenharmony_ci    }
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ci    const char* name() const override { return "Porter Duff"; }
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ci    SkString getShaderDfxInfo() const override;
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ci    BlendFormula getBlendFormula() const { return fBlendFormula; }
388cb93a386Sopenharmony_ci
389cb93a386Sopenharmony_ciprivate:
390cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
391cb93a386Sopenharmony_ci
392cb93a386Sopenharmony_ci    bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci    void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
395cb93a386Sopenharmony_ci        blendInfo->fEquation = fBlendFormula.equation();
396cb93a386Sopenharmony_ci        blendInfo->fSrcBlend = fBlendFormula.srcCoeff();
397cb93a386Sopenharmony_ci        blendInfo->fDstBlend = fBlendFormula.dstCoeff();
398cb93a386Sopenharmony_ci        blendInfo->fWriteColor = fBlendFormula.modifiesDst();
399cb93a386Sopenharmony_ci    }
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ci    bool onIsEqual(const GrXferProcessor& xpBase) const override {
402cb93a386Sopenharmony_ci        const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
403cb93a386Sopenharmony_ci        return fBlendFormula == xp.fBlendFormula;
404cb93a386Sopenharmony_ci    }
405cb93a386Sopenharmony_ci
406cb93a386Sopenharmony_ci    const BlendFormula fBlendFormula;
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_ci    using INHERITED = GrXferProcessor;
409cb93a386Sopenharmony_ci};
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_cistatic void append_color_output(const PorterDuffXferProcessor& xp,
414cb93a386Sopenharmony_ci                                GrGLSLXPFragmentBuilder* fragBuilder,
415cb93a386Sopenharmony_ci                                BlendFormula::OutputType outputType, const char* output,
416cb93a386Sopenharmony_ci                                const char* inColor, const char* inCoverage) {
417cb93a386Sopenharmony_ci    SkASSERT(inCoverage);
418cb93a386Sopenharmony_ci    SkASSERT(inColor);
419cb93a386Sopenharmony_ci    switch (outputType) {
420cb93a386Sopenharmony_ci        case BlendFormula::kNone_OutputType:
421cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = half4(0.0);", output);
422cb93a386Sopenharmony_ci            break;
423cb93a386Sopenharmony_ci        case BlendFormula::kCoverage_OutputType:
424cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
425cb93a386Sopenharmony_ci            break;
426cb93a386Sopenharmony_ci        case BlendFormula::kModulate_OutputType:
427cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
428cb93a386Sopenharmony_ci            break;
429cb93a386Sopenharmony_ci        case BlendFormula::kSAModulate_OutputType:
430cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
431cb93a386Sopenharmony_ci            break;
432cb93a386Sopenharmony_ci        case BlendFormula::kISAModulate_OutputType:
433cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
434cb93a386Sopenharmony_ci            break;
435cb93a386Sopenharmony_ci        case BlendFormula::kISCModulate_OutputType:
436cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage);
437cb93a386Sopenharmony_ci            break;
438cb93a386Sopenharmony_ci        default:
439cb93a386Sopenharmony_ci            SK_ABORT("Unsupported output type.");
440cb93a386Sopenharmony_ci            break;
441cb93a386Sopenharmony_ci    }
442cb93a386Sopenharmony_ci}
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ciSkString PorterDuffXferProcessor::getShaderDfxInfo() const
445cb93a386Sopenharmony_ci{
446cb93a386Sopenharmony_ci    SkString format;
447cb93a386Sopenharmony_ci    format.printf("ShaderDfx_PorterDuffXfer_%d_%d", fBlendFormula.primaryOutput(), fBlendFormula.secondaryOutput());
448cb93a386Sopenharmony_ci    return format;
449cb93a386Sopenharmony_ci}
450cb93a386Sopenharmony_ci
451cb93a386Sopenharmony_civoid PorterDuffXferProcessor::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
452cb93a386Sopenharmony_ci    b->add32(fBlendFormula.primaryOutput() | (fBlendFormula.secondaryOutput() << 3));
453cb93a386Sopenharmony_ci    static_assert(BlendFormula::kLast_OutputType < 8);
454cb93a386Sopenharmony_ci}
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> PorterDuffXferProcessor::makeProgramImpl() const {
457cb93a386Sopenharmony_ci    class Impl : public ProgramImpl {
458cb93a386Sopenharmony_ci    private:
459cb93a386Sopenharmony_ci        void emitOutputsForBlendState(const EmitArgs& args) override {
460cb93a386Sopenharmony_ci            const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
461cb93a386Sopenharmony_ci            GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
462cb93a386Sopenharmony_ci
463cb93a386Sopenharmony_ci            const BlendFormula& blendFormula = xp.fBlendFormula;
464cb93a386Sopenharmony_ci            if (blendFormula.hasSecondaryOutput()) {
465cb93a386Sopenharmony_ci                append_color_output(xp,
466cb93a386Sopenharmony_ci                                    fragBuilder,
467cb93a386Sopenharmony_ci                                    blendFormula.secondaryOutput(),
468cb93a386Sopenharmony_ci                                    args.fOutputSecondary,
469cb93a386Sopenharmony_ci                                    args.fInputColor,
470cb93a386Sopenharmony_ci                                    args.fInputCoverage);
471cb93a386Sopenharmony_ci            }
472cb93a386Sopenharmony_ci            append_color_output(xp,
473cb93a386Sopenharmony_ci                                fragBuilder,
474cb93a386Sopenharmony_ci                                blendFormula.primaryOutput(),
475cb93a386Sopenharmony_ci                                args.fOutputPrimary,
476cb93a386Sopenharmony_ci                                args.fInputColor,
477cb93a386Sopenharmony_ci                                args.fInputCoverage);
478cb93a386Sopenharmony_ci        }
479cb93a386Sopenharmony_ci    };
480cb93a386Sopenharmony_ci
481cb93a386Sopenharmony_ci    return std::make_unique<Impl>();
482cb93a386Sopenharmony_ci}
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_ciclass ShaderPDXferProcessor : public GrXferProcessor {
487cb93a386Sopenharmony_cipublic:
488cb93a386Sopenharmony_ci    ShaderPDXferProcessor(SkBlendMode xfermode, GrProcessorAnalysisCoverage coverage)
489cb93a386Sopenharmony_ci            : INHERITED(kShaderPDXferProcessor_ClassID, /*willReadDstColor=*/true, coverage)
490cb93a386Sopenharmony_ci            , fXfermode(xfermode) {
491cb93a386Sopenharmony_ci    }
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_ci    const char* name() const override { return "Porter Duff Shader"; }
494cb93a386Sopenharmony_ci
495cb93a386Sopenharmony_ci    SkString getShaderDfxInfo() const override;
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ciprivate:
500cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
501cb93a386Sopenharmony_ci
502cb93a386Sopenharmony_ci    bool onIsEqual(const GrXferProcessor& xpBase) const override {
503cb93a386Sopenharmony_ci        const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
504cb93a386Sopenharmony_ci        return fXfermode == xp.fXfermode;
505cb93a386Sopenharmony_ci    }
506cb93a386Sopenharmony_ci
507cb93a386Sopenharmony_ci    const SkBlendMode fXfermode;
508cb93a386Sopenharmony_ci
509cb93a386Sopenharmony_ci    using INHERITED = GrXferProcessor;
510cb93a386Sopenharmony_ci};
511cb93a386Sopenharmony_ci
512cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
513cb93a386Sopenharmony_ci
514cb93a386Sopenharmony_ciSkString ShaderPDXferProcessor::getShaderDfxInfo() const
515cb93a386Sopenharmony_ci{
516cb93a386Sopenharmony_ci    SkString format;
517cb93a386Sopenharmony_ci    format.printf("ShaderDfx_ShaderPDXfer_%d", fXfermode);
518cb93a386Sopenharmony_ci    return format;
519cb93a386Sopenharmony_ci}
520cb93a386Sopenharmony_ci
521cb93a386Sopenharmony_civoid ShaderPDXferProcessor::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
522cb93a386Sopenharmony_ci    b->add32(static_cast<int>(fXfermode));
523cb93a386Sopenharmony_ci}
524cb93a386Sopenharmony_ci
525cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> ShaderPDXferProcessor::makeProgramImpl() const {
526cb93a386Sopenharmony_ci    class Impl : public ProgramImpl {
527cb93a386Sopenharmony_ci    private:
528cb93a386Sopenharmony_ci        void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
529cb93a386Sopenharmony_ci                                     GrGLSLUniformHandler* uniformHandler,
530cb93a386Sopenharmony_ci                                     const char* srcColor,
531cb93a386Sopenharmony_ci                                     const char* srcCoverage,
532cb93a386Sopenharmony_ci                                     const char* dstColor,
533cb93a386Sopenharmony_ci                                     const char* outColor,
534cb93a386Sopenharmony_ci                                     const char* outColorSecondary,
535cb93a386Sopenharmony_ci                                     const GrXferProcessor& proc) override {
536cb93a386Sopenharmony_ci            const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ci            GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.fXfermode);
539cb93a386Sopenharmony_ci
540cb93a386Sopenharmony_ci            // Apply coverage.
541cb93a386Sopenharmony_ci            DefaultCoverageModulation(fragBuilder,
542cb93a386Sopenharmony_ci                                      srcCoverage,
543cb93a386Sopenharmony_ci                                      dstColor,
544cb93a386Sopenharmony_ci                                      outColor,
545cb93a386Sopenharmony_ci                                      outColorSecondary,
546cb93a386Sopenharmony_ci                                      xp);
547cb93a386Sopenharmony_ci        }
548cb93a386Sopenharmony_ci    };
549cb93a386Sopenharmony_ci
550cb93a386Sopenharmony_ci    return std::make_unique<Impl>();
551cb93a386Sopenharmony_ci}
552cb93a386Sopenharmony_ci
553cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
554cb93a386Sopenharmony_ci
555cb93a386Sopenharmony_ciclass PDLCDXferProcessor : public GrXferProcessor {
556cb93a386Sopenharmony_cipublic:
557cb93a386Sopenharmony_ci    static sk_sp<const GrXferProcessor> Make(SkBlendMode mode,
558cb93a386Sopenharmony_ci                                             const GrProcessorAnalysisColor& inputColor);
559cb93a386Sopenharmony_ci
560cb93a386Sopenharmony_ci    const char* name() const override { return "Porter Duff LCD"; }
561cb93a386Sopenharmony_ci
562cb93a386Sopenharmony_ci    SkString getShaderDfxInfo() const override { return SkString("ShaderDfx_PDLCDXfer"); }
563cb93a386Sopenharmony_ci
564cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
565cb93a386Sopenharmony_ci
566cb93a386Sopenharmony_ciprivate:
567cb93a386Sopenharmony_ci    PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha);
568cb93a386Sopenharmony_ci
569cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
570cb93a386Sopenharmony_ci
571cb93a386Sopenharmony_ci    void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
572cb93a386Sopenharmony_ci        blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
573cb93a386Sopenharmony_ci        blendInfo->fDstBlend = kISC_GrBlendCoeff;
574cb93a386Sopenharmony_ci        blendInfo->fBlendConstant = fBlendConstant;
575cb93a386Sopenharmony_ci    }
576cb93a386Sopenharmony_ci
577cb93a386Sopenharmony_ci    bool onIsEqual(const GrXferProcessor& xpBase) const override {
578cb93a386Sopenharmony_ci        const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
579cb93a386Sopenharmony_ci        if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) {
580cb93a386Sopenharmony_ci            return false;
581cb93a386Sopenharmony_ci        }
582cb93a386Sopenharmony_ci        return true;
583cb93a386Sopenharmony_ci    }
584cb93a386Sopenharmony_ci
585cb93a386Sopenharmony_ci    SkPMColor4f fBlendConstant;
586cb93a386Sopenharmony_ci    float fAlpha;
587cb93a386Sopenharmony_ci
588cb93a386Sopenharmony_ci    using INHERITED = GrXferProcessor;
589cb93a386Sopenharmony_ci};
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_ciPDLCDXferProcessor::PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha)
592cb93a386Sopenharmony_ci    : INHERITED(kPDLCDXferProcessor_ClassID, /*willReadDstColor=*/false,
593cb93a386Sopenharmony_ci                GrProcessorAnalysisCoverage::kLCD)
594cb93a386Sopenharmony_ci    , fBlendConstant(blendConstant)
595cb93a386Sopenharmony_ci    , fAlpha(alpha) {
596cb93a386Sopenharmony_ci}
597cb93a386Sopenharmony_ci
598cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode,
599cb93a386Sopenharmony_ci                                                      const GrProcessorAnalysisColor& color) {
600cb93a386Sopenharmony_ci    if (SkBlendMode::kSrcOver != mode) {
601cb93a386Sopenharmony_ci        return nullptr;
602cb93a386Sopenharmony_ci    }
603cb93a386Sopenharmony_ci    SkPMColor4f blendConstantPM;
604cb93a386Sopenharmony_ci    if (!color.isConstant(&blendConstantPM)) {
605cb93a386Sopenharmony_ci        return nullptr;
606cb93a386Sopenharmony_ci    }
607cb93a386Sopenharmony_ci    SkColor4f blendConstantUPM = blendConstantPM.unpremul();
608cb93a386Sopenharmony_ci    float alpha = blendConstantUPM.fA;
609cb93a386Sopenharmony_ci    blendConstantPM = { blendConstantUPM.fR, blendConstantUPM.fG, blendConstantUPM.fB, 1 };
610cb93a386Sopenharmony_ci    return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstantPM, alpha));
611cb93a386Sopenharmony_ci}
612cb93a386Sopenharmony_ci
613cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> PDLCDXferProcessor::makeProgramImpl() const {
614cb93a386Sopenharmony_ci    class Impl : public ProgramImpl {
615cb93a386Sopenharmony_ci    private:
616cb93a386Sopenharmony_ci        void emitOutputsForBlendState(const EmitArgs& args) override {
617cb93a386Sopenharmony_ci            const char* alpha;
618cb93a386Sopenharmony_ci            fAlphaUniform = args.fUniformHandler->addUniform(nullptr,
619cb93a386Sopenharmony_ci                                                             kFragment_GrShaderFlag,
620cb93a386Sopenharmony_ci                                                             kHalf_GrSLType,
621cb93a386Sopenharmony_ci                                                             "alpha",
622cb93a386Sopenharmony_ci                                                             &alpha);
623cb93a386Sopenharmony_ci            GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
624cb93a386Sopenharmony_ci            // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
625cb93a386Sopenharmony_ci            // value of the src color. We know that there are no color stages (or we wouldn't have
626cb93a386Sopenharmony_ci            // created this xp) and the r,g, and b channels of the op's input color are baked into
627cb93a386Sopenharmony_ci            // the blend constant.
628cb93a386Sopenharmony_ci            SkASSERT(args.fInputCoverage);
629cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("%s = %s * %s;",
630cb93a386Sopenharmony_ci                                     args.fOutputPrimary,
631cb93a386Sopenharmony_ci                                     alpha, args.fInputCoverage);
632cb93a386Sopenharmony_ci        }
633cb93a386Sopenharmony_ci
634cb93a386Sopenharmony_ci        void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
635cb93a386Sopenharmony_ci            float alpha = xp.cast<PDLCDXferProcessor>().fAlpha;
636cb93a386Sopenharmony_ci            if (fLastAlpha != alpha) {
637cb93a386Sopenharmony_ci                pdm.set1f(fAlphaUniform, alpha);
638cb93a386Sopenharmony_ci                fLastAlpha = alpha;
639cb93a386Sopenharmony_ci            }
640cb93a386Sopenharmony_ci        }
641cb93a386Sopenharmony_ci
642cb93a386Sopenharmony_ci        GrGLSLUniformHandler::UniformHandle fAlphaUniform;
643cb93a386Sopenharmony_ci        float fLastAlpha = SK_FloatNaN;
644cb93a386Sopenharmony_ci    };
645cb93a386Sopenharmony_ci
646cb93a386Sopenharmony_ci    return std::make_unique<Impl>();
647cb93a386Sopenharmony_ci}
648cb93a386Sopenharmony_ci
649cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
650cb93a386Sopenharmony_ci
651cb93a386Sopenharmony_ciconstexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
652cb93a386Sopenharmony_ci        : fBlendMode(xfermode) {}
653cb93a386Sopenharmony_ci
654cb93a386Sopenharmony_ciconst GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
655cb93a386Sopenharmony_ci    SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
656cb93a386Sopenharmony_ci
657cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
658cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
659cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
660cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
661cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
662cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
663cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
664cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
665cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
666cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
667cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
668cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
669cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
670cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
671cb93a386Sopenharmony_ci    static constexpr const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
672cb93a386Sopenharmony_ci
673cb93a386Sopenharmony_ci    switch (blendMode) {
674cb93a386Sopenharmony_ci        case SkBlendMode::kClear:
675cb93a386Sopenharmony_ci            return &gClearPDXPF;
676cb93a386Sopenharmony_ci        case SkBlendMode::kSrc:
677cb93a386Sopenharmony_ci            return &gSrcPDXPF;
678cb93a386Sopenharmony_ci        case SkBlendMode::kDst:
679cb93a386Sopenharmony_ci            return &gDstPDXPF;
680cb93a386Sopenharmony_ci        case SkBlendMode::kSrcOver:
681cb93a386Sopenharmony_ci            return &gSrcOverPDXPF;
682cb93a386Sopenharmony_ci        case SkBlendMode::kDstOver:
683cb93a386Sopenharmony_ci            return &gDstOverPDXPF;
684cb93a386Sopenharmony_ci        case SkBlendMode::kSrcIn:
685cb93a386Sopenharmony_ci            return &gSrcInPDXPF;
686cb93a386Sopenharmony_ci        case SkBlendMode::kDstIn:
687cb93a386Sopenharmony_ci            return &gDstInPDXPF;
688cb93a386Sopenharmony_ci        case SkBlendMode::kSrcOut:
689cb93a386Sopenharmony_ci            return &gSrcOutPDXPF;
690cb93a386Sopenharmony_ci        case SkBlendMode::kDstOut:
691cb93a386Sopenharmony_ci            return &gDstOutPDXPF;
692cb93a386Sopenharmony_ci        case SkBlendMode::kSrcATop:
693cb93a386Sopenharmony_ci            return &gSrcATopPDXPF;
694cb93a386Sopenharmony_ci        case SkBlendMode::kDstATop:
695cb93a386Sopenharmony_ci            return &gDstATopPDXPF;
696cb93a386Sopenharmony_ci        case SkBlendMode::kXor:
697cb93a386Sopenharmony_ci            return &gXorPDXPF;
698cb93a386Sopenharmony_ci        case SkBlendMode::kPlus:
699cb93a386Sopenharmony_ci            return &gPlusPDXPF;
700cb93a386Sopenharmony_ci        case SkBlendMode::kModulate:
701cb93a386Sopenharmony_ci            return &gModulatePDXPF;
702cb93a386Sopenharmony_ci        case SkBlendMode::kScreen:
703cb93a386Sopenharmony_ci            return &gScreenPDXPF;
704cb93a386Sopenharmony_ci        default:
705cb93a386Sopenharmony_ci            SK_ABORT("Unexpected blend mode.");
706cb93a386Sopenharmony_ci    }
707cb93a386Sopenharmony_ci}
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor(
710cb93a386Sopenharmony_ci        const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
711cb93a386Sopenharmony_ci        const GrCaps& caps, GrClampType clampType) const {
712cb93a386Sopenharmony_ci    bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD;
713cb93a386Sopenharmony_ci    // See comment in MakeSrcOverXferProcessor about color.isOpaque here
714cb93a386Sopenharmony_ci    if (isLCD &&
715cb93a386Sopenharmony_ci        SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/
716cb93a386Sopenharmony_ci        !caps.shaderCaps()->dualSourceBlendingSupport() &&
717cb93a386Sopenharmony_ci        !caps.shaderCaps()->dstReadInShaderSupport()) {
718cb93a386Sopenharmony_ci        // If we don't have dual source blending or in shader dst reads, we fall back to this
719cb93a386Sopenharmony_ci        // trick for rendering SrcOver LCD text instead of doing a dst copy.
720cb93a386Sopenharmony_ci        return PDLCDXferProcessor::Make(fBlendMode, color);
721cb93a386Sopenharmony_ci    }
722cb93a386Sopenharmony_ci    BlendFormula blendFormula = [&](){
723cb93a386Sopenharmony_ci        if (isLCD) {
724cb93a386Sopenharmony_ci            return get_lcd_blend_formula(fBlendMode);
725cb93a386Sopenharmony_ci        }
726cb93a386Sopenharmony_ci        if (fBlendMode == SkBlendMode::kSrcOver && color.isOpaque() &&
727cb93a386Sopenharmony_ci            coverage == GrProcessorAnalysisCoverage::kNone &&
728cb93a386Sopenharmony_ci            caps.shouldCollapseSrcOverToSrcWhenAble())
729cb93a386Sopenharmony_ci        {
730cb93a386Sopenharmony_ci            return get_blend_formula(true, false, SkBlendMode::kSrc);
731cb93a386Sopenharmony_ci        }
732cb93a386Sopenharmony_ci        return get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage,
733cb93a386Sopenharmony_ci                                 fBlendMode);
734cb93a386Sopenharmony_ci    }();
735cb93a386Sopenharmony_ci
736cb93a386Sopenharmony_ci    // Skia always saturates after the kPlus blend mode, so it requires shader-based blending when
737cb93a386Sopenharmony_ci    // pixels aren't guaranteed to automatically be normalized (i.e. any floating point config).
738cb93a386Sopenharmony_ci    if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) ||
739cb93a386Sopenharmony_ci        (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/)) ||
740cb93a386Sopenharmony_ci        (GrClampType::kAuto != clampType && SkBlendMode::kPlus == fBlendMode)) {
741cb93a386Sopenharmony_ci        return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(fBlendMode, coverage));
742cb93a386Sopenharmony_ci    }
743cb93a386Sopenharmony_ci    return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
744cb93a386Sopenharmony_ci}
745cb93a386Sopenharmony_ci
746cb93a386Sopenharmony_cistatic inline GrXPFactory::AnalysisProperties analysis_properties(
747cb93a386Sopenharmony_ci        const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage,
748cb93a386Sopenharmony_ci        const GrCaps& caps, GrClampType clampType, SkBlendMode mode) {
749cb93a386Sopenharmony_ci    using AnalysisProperties = GrXPFactory::AnalysisProperties;
750cb93a386Sopenharmony_ci    AnalysisProperties props = AnalysisProperties::kNone;
751cb93a386Sopenharmony_ci    bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage;
752cb93a386Sopenharmony_ci    bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage;
753cb93a386Sopenharmony_ci    BlendFormula formula = [&](){
754cb93a386Sopenharmony_ci        if (isLCD) {
755cb93a386Sopenharmony_ci            return gLCDBlendTable[(int)mode];
756cb93a386Sopenharmony_ci        }
757cb93a386Sopenharmony_ci        return get_blend_formula(color.isOpaque(), hasCoverage, mode);
758cb93a386Sopenharmony_ci    }();
759cb93a386Sopenharmony_ci
760cb93a386Sopenharmony_ci    if (formula.canTweakAlphaForCoverage() && !isLCD) {
761cb93a386Sopenharmony_ci        props |= AnalysisProperties::kCompatibleWithCoverageAsAlpha;
762cb93a386Sopenharmony_ci    }
763cb93a386Sopenharmony_ci
764cb93a386Sopenharmony_ci    if (isLCD) {
765cb93a386Sopenharmony_ci        // See comment in MakeSrcOverXferProcessor about color.isOpaque here
766cb93a386Sopenharmony_ci        if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/
767cb93a386Sopenharmony_ci            !caps.shaderCaps()->dualSourceBlendingSupport() &&
768cb93a386Sopenharmony_ci            !caps.shaderCaps()->dstReadInShaderSupport()) {
769cb93a386Sopenharmony_ci            props |= AnalysisProperties::kIgnoresInputColor;
770cb93a386Sopenharmony_ci        } else {
771cb93a386Sopenharmony_ci            // For LCD blending, if the color is not opaque we must read the dst in shader even if
772cb93a386Sopenharmony_ci            // we have dual source blending. The opaqueness check must be done after blending so for
773cb93a386Sopenharmony_ci            // simplicity we only allow src-over to not take the dst read path (though src, src-in,
774cb93a386Sopenharmony_ci            // and DstATop would also work). We also fall into the dst read case for src-over if we
775cb93a386Sopenharmony_ci            // do not have dual source blending.
776cb93a386Sopenharmony_ci            if (SkBlendMode::kSrcOver != mode ||
777cb93a386Sopenharmony_ci                /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque.
778cb93a386Sopenharmony_ci                (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
779cb93a386Sopenharmony_ci                props |= AnalysisProperties::kReadsDstInShader;
780cb93a386Sopenharmony_ci            }
781cb93a386Sopenharmony_ci        }
782cb93a386Sopenharmony_ci    } else {
783cb93a386Sopenharmony_ci        // With dual-source blending we never need the destination color in the shader.
784cb93a386Sopenharmony_ci        if (!caps.shaderCaps()->dualSourceBlendingSupport()) {
785cb93a386Sopenharmony_ci            if (formula.hasSecondaryOutput()) {
786cb93a386Sopenharmony_ci                props |= AnalysisProperties::kReadsDstInShader;
787cb93a386Sopenharmony_ci            }
788cb93a386Sopenharmony_ci        }
789cb93a386Sopenharmony_ci    }
790cb93a386Sopenharmony_ci
791cb93a386Sopenharmony_ci    if (GrClampType::kAuto != clampType && SkBlendMode::kPlus == mode) {
792cb93a386Sopenharmony_ci        props |= AnalysisProperties::kReadsDstInShader;
793cb93a386Sopenharmony_ci    }
794cb93a386Sopenharmony_ci
795cb93a386Sopenharmony_ci    if (!formula.modifiesDst() || !formula.usesInputColor()) {
796cb93a386Sopenharmony_ci        props |= AnalysisProperties::kIgnoresInputColor;
797cb93a386Sopenharmony_ci    }
798cb93a386Sopenharmony_ci    if (formula.unaffectedByDst() || (formula.unaffectedByDstIfOpaque() && color.isOpaque() &&
799cb93a386Sopenharmony_ci                                      !hasCoverage)) {
800cb93a386Sopenharmony_ci        props |= AnalysisProperties::kUnaffectedByDstValue;
801cb93a386Sopenharmony_ci    }
802cb93a386Sopenharmony_ci    return props;
803cb93a386Sopenharmony_ci}
804cb93a386Sopenharmony_ci
805cb93a386Sopenharmony_ciGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties(
806cb93a386Sopenharmony_ci        const GrProcessorAnalysisColor& color,
807cb93a386Sopenharmony_ci        const GrProcessorAnalysisCoverage& coverage,
808cb93a386Sopenharmony_ci        const GrCaps& caps,
809cb93a386Sopenharmony_ci        GrClampType clampType) const {
810cb93a386Sopenharmony_ci    return analysis_properties(color, coverage, caps, clampType, fBlendMode);
811cb93a386Sopenharmony_ci}
812cb93a386Sopenharmony_ci
813cb93a386Sopenharmony_ciGR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
814cb93a386Sopenharmony_ci
815cb93a386Sopenharmony_ci#if GR_TEST_UTILS
816cb93a386Sopenharmony_ciconst GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
817cb93a386Sopenharmony_ci    SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
818cb93a386Sopenharmony_ci    return GrPorterDuffXPFactory::Get(mode);
819cb93a386Sopenharmony_ci}
820cb93a386Sopenharmony_ci#endif
821cb93a386Sopenharmony_ci
822cb93a386Sopenharmony_civoid GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
823cb93a386Sopenharmony_ci                                                 int* outPrimary,
824cb93a386Sopenharmony_ci                                                 int* outSecondary) {
825cb93a386Sopenharmony_ci    if (!!strcmp(xp->name(), "Porter Duff")) {
826cb93a386Sopenharmony_ci        *outPrimary = *outSecondary = -1;
827cb93a386Sopenharmony_ci        return;
828cb93a386Sopenharmony_ci    }
829cb93a386Sopenharmony_ci    BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
830cb93a386Sopenharmony_ci    *outPrimary = blendFormula.primaryOutput();
831cb93a386Sopenharmony_ci    *outSecondary = blendFormula.secondaryOutput();
832cb93a386Sopenharmony_ci}
833cb93a386Sopenharmony_ci
834cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////
835cb93a386Sopenharmony_ci// SrcOver Global functions
836cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////
837cb93a386Sopenharmony_ciconst GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
838cb93a386Sopenharmony_ci    static BlendFormula gSrcOverBlendFormula =
839cb93a386Sopenharmony_ci            MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff);
840cb93a386Sopenharmony_ci    static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula,
841cb93a386Sopenharmony_ci                                              GrProcessorAnalysisCoverage::kSingleChannel);
842cb93a386Sopenharmony_ci    return gSrcOverXP;
843cb93a386Sopenharmony_ci}
844cb93a386Sopenharmony_ci
845cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor(
846cb93a386Sopenharmony_ci        const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
847cb93a386Sopenharmony_ci        const GrCaps& caps) {
848cb93a386Sopenharmony_ci    // We want to not make an xfer processor if possible. Thus for the simple case where we are not
849cb93a386Sopenharmony_ci    // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
850cb93a386Sopenharmony_ci    // the general case where we convert a src-over blend that has solid coverage and an opaque
851cb93a386Sopenharmony_ci    // color to src-mode, which allows disabling of blending.
852cb93a386Sopenharmony_ci    if (coverage != GrProcessorAnalysisCoverage::kLCD) {
853cb93a386Sopenharmony_ci        if (color.isOpaque() && coverage == GrProcessorAnalysisCoverage::kNone &&
854cb93a386Sopenharmony_ci            caps.shouldCollapseSrcOverToSrcWhenAble()) {
855cb93a386Sopenharmony_ci            BlendFormula blendFormula = get_blend_formula(true, false, SkBlendMode::kSrc);
856cb93a386Sopenharmony_ci            return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
857cb93a386Sopenharmony_ci        }
858cb93a386Sopenharmony_ci        // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
859cb93a386Sopenharmony_ci        // We don't simply return the address of that XP here because our caller would have to unref
860cb93a386Sopenharmony_ci        // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
861cb93a386Sopenharmony_ci        // safe.
862cb93a386Sopenharmony_ci        return nullptr;
863cb93a386Sopenharmony_ci    }
864cb93a386Sopenharmony_ci
865cb93a386Sopenharmony_ci    // Currently up the stack Skia is requiring that the dst is opaque or that the client has said
866cb93a386Sopenharmony_ci    // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color
867cb93a386Sopenharmony_ci    // being opaque or not. This allows us to use faster code paths as well as avoid various bugs
868cb93a386Sopenharmony_ci    // that occur with dst reads in the shader blending. For now we disable the check for
869cb93a386Sopenharmony_ci    // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make
870cb93a386Sopenharmony_ci    // the correct decision here.
871cb93a386Sopenharmony_ci    //
872cb93a386Sopenharmony_ci    // This also fixes a chrome bug on macs where we are getting random fuzziness when doing
873cb93a386Sopenharmony_ci    // blending in the shader for non opaque sources.
874cb93a386Sopenharmony_ci    if (color.isConstant() && /*color.isOpaque() &&*/
875cb93a386Sopenharmony_ci        !caps.shaderCaps()->dualSourceBlendingSupport() &&
876cb93a386Sopenharmony_ci        !caps.shaderCaps()->dstReadInShaderSupport()) {
877cb93a386Sopenharmony_ci        // If we don't have dual source blending or in shader dst reads, we fall
878cb93a386Sopenharmony_ci        // back to this trick for rendering SrcOver LCD text instead of doing a
879cb93a386Sopenharmony_ci        // dst copy.
880cb93a386Sopenharmony_ci        return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color);
881cb93a386Sopenharmony_ci    }
882cb93a386Sopenharmony_ci
883cb93a386Sopenharmony_ci    BlendFormula blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
884cb93a386Sopenharmony_ci    // See comment above regarding why the opaque check is commented out here.
885cb93a386Sopenharmony_ci    if (/*!color.isOpaque() ||*/
886cb93a386Sopenharmony_ci        (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
887cb93a386Sopenharmony_ci        return sk_sp<GrXferProcessor>(new ShaderPDXferProcessor(SkBlendMode::kSrcOver, coverage));
888cb93a386Sopenharmony_ci    }
889cb93a386Sopenharmony_ci    return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
890cb93a386Sopenharmony_ci}
891cb93a386Sopenharmony_ci
892cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) {
893cb93a386Sopenharmony_ci    BlendFormula formula = get_blend_formula(false, false, blendmode);
894cb93a386Sopenharmony_ci    return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone);
895cb93a386Sopenharmony_ci}
896cb93a386Sopenharmony_ci
897cb93a386Sopenharmony_ciGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties(
898cb93a386Sopenharmony_ci        const GrProcessorAnalysisColor& color,
899cb93a386Sopenharmony_ci        const GrProcessorAnalysisCoverage& coverage,
900cb93a386Sopenharmony_ci        const GrCaps& caps,
901cb93a386Sopenharmony_ci        GrClampType clampType) {
902cb93a386Sopenharmony_ci    return analysis_properties(color, coverage, caps, clampType, SkBlendMode::kSrcOver);
903cb93a386Sopenharmony_ci}
904