1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrXferProcessor.h"
9#include "GrPipeline.h"
10#include "gl/GrGLCaps.h"
11
12GrXferProcessor::GrXferProcessor()
13        : fWillReadDstColor(false)
14        , fDstReadUsesMixedSamples(false)
15        , fIsLCD(false) {}
16
17GrXferProcessor::GrXferProcessor(bool willReadDstColor, bool hasMixedSamples,
18                                 GrProcessorAnalysisCoverage coverage)
19        : fWillReadDstColor(willReadDstColor)
20        , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples)
21        , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {}
22
23bool GrXferProcessor::hasSecondaryOutput() const {
24    if (!this->willReadDstColor()) {
25        return this->onHasSecondaryOutput();
26    }
27    return this->dstReadUsesMixedSamples();
28}
29
30void GrXferProcessor::getBlendInfo(BlendInfo* blendInfo) const {
31    blendInfo->reset();
32    if (!this->willReadDstColor()) {
33        this->onGetBlendInfo(blendInfo);
34    } else if (this->dstReadUsesMixedSamples()) {
35        blendInfo->fDstBlend = kIS2A_GrBlendCoeff;
36    }
37}
38
39void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b,
40                                          const GrSurfaceOrigin* originIfDstTexture) const {
41    uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
42    if (key) {
43        if (originIfDstTexture) {
44            key |= 0x2;
45            if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
46                key |= 0x4;
47            }
48        }
49        if (this->dstReadUsesMixedSamples()) {
50            key |= 0x8;
51        }
52    }
53    if (fIsLCD) {
54        key |= 0x10;
55    }
56    b->add32(key);
57    this->onGetGLSLProcessorKey(caps, b);
58}
59
60#ifdef SK_DEBUG
61static const char* equation_string(GrBlendEquation eq) {
62    switch (eq) {
63        case kAdd_GrBlendEquation:
64            return "add";
65        case kSubtract_GrBlendEquation:
66            return "subtract";
67        case kReverseSubtract_GrBlendEquation:
68            return "reverse_subtract";
69        case kScreen_GrBlendEquation:
70            return "screen";
71        case kOverlay_GrBlendEquation:
72            return "overlay";
73        case kDarken_GrBlendEquation:
74            return "darken";
75        case kLighten_GrBlendEquation:
76            return "lighten";
77        case kColorDodge_GrBlendEquation:
78            return "color_dodge";
79        case kColorBurn_GrBlendEquation:
80            return "color_burn";
81        case kHardLight_GrBlendEquation:
82            return "hard_light";
83        case kSoftLight_GrBlendEquation:
84            return "soft_light";
85        case kDifference_GrBlendEquation:
86            return "difference";
87        case kExclusion_GrBlendEquation:
88            return "exclusion";
89        case kMultiply_GrBlendEquation:
90            return "multiply";
91        case kHSLHue_GrBlendEquation:
92            return "hsl_hue";
93        case kHSLSaturation_GrBlendEquation:
94            return "hsl_saturation";
95        case kHSLColor_GrBlendEquation:
96            return "hsl_color";
97        case kHSLLuminosity_GrBlendEquation:
98            return "hsl_luminosity";
99    };
100    return "";
101}
102
103static const char* coeff_string(GrBlendCoeff coeff) {
104    switch (coeff) {
105        case kZero_GrBlendCoeff:
106            return "zero";
107        case kOne_GrBlendCoeff:
108            return "one";
109        case kSC_GrBlendCoeff:
110            return "src_color";
111        case kISC_GrBlendCoeff:
112            return "inv_src_color";
113        case kDC_GrBlendCoeff:
114            return "dst_color";
115        case kIDC_GrBlendCoeff:
116            return "inv_dst_color";
117        case kSA_GrBlendCoeff:
118            return "src_alpha";
119        case kISA_GrBlendCoeff:
120            return "inv_src_alpha";
121        case kDA_GrBlendCoeff:
122            return "dst_alpha";
123        case kIDA_GrBlendCoeff:
124            return "inv_dst_alpha";
125        case kConstC_GrBlendCoeff:
126            return "const_color";
127        case kIConstC_GrBlendCoeff:
128            return "inv_const_color";
129        case kConstA_GrBlendCoeff:
130            return "const_alpha";
131        case kIConstA_GrBlendCoeff:
132            return "inv_const_alpha";
133        case kS2C_GrBlendCoeff:
134            return "src2_color";
135        case kIS2C_GrBlendCoeff:
136            return "inv_src2_color";
137        case kS2A_GrBlendCoeff:
138            return "src2_alpha";
139        case kIS2A_GrBlendCoeff:
140            return "inv_src2_alpha";
141    }
142    return "";
143}
144
145SkString GrXferProcessor::BlendInfo::dump() const {
146    SkString out;
147    out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
148               fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
149               coeff_string(fDstBlend), fBlendConstant);
150    return out;
151}
152#endif
153
154///////////////////////////////////////////////////////////////////////////////
155
156GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
157        const GrXPFactory* factory,
158        const GrProcessorAnalysisColor& color,
159        const GrProcessorAnalysisCoverage& coverage,
160        const GrCaps& caps) {
161    AnalysisProperties result;
162    if (factory) {
163        result = factory->analysisProperties(color, coverage, caps);
164    } else {
165        result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps);
166    }
167    SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture));
168    if ((result & AnalysisProperties::kReadsDstInShader) &&
169        !caps.shaderCaps()->dstReadInShaderSupport()) {
170        result |= AnalysisProperties::kRequiresDstTexture;
171        if (caps.textureBarrierSupport()) {
172            result |= AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws;
173        }
174    }
175    return result;
176}
177
178sk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory,
179                                                            const GrProcessorAnalysisColor& color,
180                                                            GrProcessorAnalysisCoverage coverage,
181                                                            bool hasMixedSamples,
182                                                            const GrCaps& caps) {
183    SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
184    if (factory) {
185        return factory->makeXferProcessor(color, coverage, hasMixedSamples, caps);
186    } else {
187        return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, hasMixedSamples,
188                                                               caps);
189    }
190}
191