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 "gl/GrGLCaps.h"
10
11GrXferProcessor::GrXferProcessor()
12    : fWillReadDstColor(false), fReadsCoverage(true), fDstCopyTextureOffset() {
13}
14
15GrXferProcessor::GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
16    : fWillReadDstColor(willReadDstColor)
17    , fReadsCoverage(true)
18    , fDstCopyTextureOffset() {
19    if (dstCopy && dstCopy->texture()) {
20        fDstCopy.reset(dstCopy->texture());
21        fDstCopyTextureOffset = dstCopy->offset();
22        this->addTextureAccess(&fDstCopy);
23        this->setWillReadFragmentPosition();
24    }
25}
26
27GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
28                                                            const GrProcOptInfo& coveragePOI,
29                                                            bool doesStencilWrite,
30                                                            GrColor* overrideColor,
31                                                            const GrDrawTargetCaps& caps) {
32    GrXferProcessor::OptFlags flags = this->onGetOptimizations(colorPOI,
33                                                               coveragePOI,
34                                                               doesStencilWrite,
35                                                               overrideColor,
36                                                               caps);
37
38    if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
39        fReadsCoverage = false;
40    }
41    return flags;
42}
43
44void GrXferProcessor::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
45    uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
46    if (this->getDstCopyTexture() &&
47        kTopLeft_GrSurfaceOrigin == this->getDstCopyTexture()->origin()) {
48        key |= 0x2;
49    }
50    b->add32(key);
51    this->onGetGLProcessorKey(caps, b);
52}
53
54bool GrXferProcessor::willNeedXferBarrier(const GrRenderTarget* rt,
55                                          const GrDrawTargetCaps& caps,
56                                          GrXferBarrierType* outBarrierType) const {
57    if (static_cast<const GrSurface*>(rt) == this->getDstCopyTexture()) {
58        // Texture barriers are required when a shader reads and renders to the same texture.
59        SkASSERT(rt);
60        SkASSERT(caps.textureBarrierSupport());
61        *outBarrierType = kTexture_GrXferBarrierType;
62        return true;
63    }
64    return this->onWillNeedXferBarrier(rt, caps, outBarrierType);
65}
66
67#ifdef SK_DEBUG
68static const char* equation_string(GrBlendEquation eq) {
69    switch (eq) {
70        case kAdd_GrBlendEquation:
71            return "add";
72        case kSubtract_GrBlendEquation:
73            return "subtract";
74        case kReverseSubtract_GrBlendEquation:
75            return "reverse_subtract";
76        case kScreen_GrBlendEquation:
77            return "screen";
78        case kOverlay_GrBlendEquation:
79            return "overlay";
80        case kDarken_GrBlendEquation:
81            return "darken";
82        case kLighten_GrBlendEquation:
83            return "lighten";
84        case kColorDodge_GrBlendEquation:
85            return "color_dodge";
86        case kColorBurn_GrBlendEquation:
87            return "color_burn";
88        case kHardLight_GrBlendEquation:
89            return "hard_light";
90        case kSoftLight_GrBlendEquation:
91            return "soft_light";
92        case kDifference_GrBlendEquation:
93            return "difference";
94        case kExclusion_GrBlendEquation:
95            return "exclusion";
96        case kMultiply_GrBlendEquation:
97            return "multiply";
98        case kHSLHue_GrBlendEquation:
99            return "hsl_hue";
100        case kHSLSaturation_GrBlendEquation:
101            return "hsl_saturation";
102        case kHSLColor_GrBlendEquation:
103            return "hsl_color";
104        case kHSLLuminosity_GrBlendEquation:
105            return "hsl_luminosity";
106    };
107    return "";
108}
109
110static const char* coeff_string(GrBlendCoeff coeff) {
111    switch (coeff) {
112        case kZero_GrBlendCoeff:
113            return "zero";
114        case kOne_GrBlendCoeff:
115            return "one";
116        case kSC_GrBlendCoeff:
117            return "src_color";
118        case kISC_GrBlendCoeff:
119            return "inv_src_color";
120        case kDC_GrBlendCoeff:
121            return "dst_color";
122        case kIDC_GrBlendCoeff:
123            return "inv_dst_color";
124        case kSA_GrBlendCoeff:
125            return "src_alpha";
126        case kISA_GrBlendCoeff:
127            return "inv_src_alpha";
128        case kDA_GrBlendCoeff:
129            return "dst_alpha";
130        case kIDA_GrBlendCoeff:
131            return "inv_dst_alpha";
132        case kConstC_GrBlendCoeff:
133            return "const_color";
134        case kIConstC_GrBlendCoeff:
135            return "inv_const_color";
136        case kConstA_GrBlendCoeff:
137            return "const_alpha";
138        case kIConstA_GrBlendCoeff:
139            return "inv_const_alpha";
140        case kS2C_GrBlendCoeff:
141            return "src2_color";
142        case kIS2C_GrBlendCoeff:
143            return "inv_src2_color";
144        case kS2A_GrBlendCoeff:
145            return "src2_alpha";
146        case kIS2A_GrBlendCoeff:
147            return "inv_src2_alpha";
148    }
149    return "";
150}
151
152SkString GrXferProcessor::BlendInfo::dump() const {
153    SkString out;
154    out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
155               fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
156               coeff_string(fDstBlend), fBlendConstant);
157    return out;
158}
159#endif
160
161///////////////////////////////////////////////////////////////////////////////
162
163GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
164                                                  const GrProcOptInfo& coveragePOI,
165                                                  const GrDeviceCoordTexture* dstCopy,
166                                                  const GrDrawTargetCaps& caps) const {
167#ifdef SK_DEBUG
168    if (this->willReadDstColor(caps, colorPOI, coveragePOI)) {
169        if (!caps.shaderCaps()->dstReadInShaderSupport()) {
170            SkASSERT(dstCopy && dstCopy->texture());
171        } else {
172            SkASSERT(!dstCopy || !dstCopy->texture());
173        }
174    } else {
175        SkASSERT(!dstCopy || !dstCopy->texture());
176    }
177#endif
178    return this->onCreateXferProcessor(caps, colorPOI, coveragePOI, dstCopy);
179}
180
181bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
182                                  const GrProcOptInfo& coveragePOI) const {
183    return (this->willReadDstColor(caps, colorPOI, coveragePOI)
184            && !caps.shaderCaps()->dstReadInShaderSupport());
185}
186
187