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 "GrPipelineBuilder.h"
9
10#include "GrBatch.h"
11#include "GrBlend.h"
12#include "GrPaint.h"
13#include "GrPipeline.h"
14#include "GrProcOptInfo.h"
15#include "GrXferProcessor.h"
16#include "effects/GrPorterDuffXferProcessor.h"
17
18GrPipelineBuilder::GrPipelineBuilder()
19    : fFlags(0x0)
20    , fDrawFace(kBoth_DrawFace)
21    , fColorProcInfoValid(false)
22    , fCoverageProcInfoValid(false)
23    , fColorCache(GrColor_ILLEGAL)
24    , fCoverageCache(GrColor_ILLEGAL) {
25    SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
26}
27
28GrPipelineBuilder& GrPipelineBuilder::operator=(const GrPipelineBuilder& that) {
29    fRenderTarget.reset(SkSafeRef(that.fRenderTarget.get()));
30    fFlags = that.fFlags;
31    fStencilSettings = that.fStencilSettings;
32    fDrawFace = that.fDrawFace;
33    fXPFactory.reset(SkRef(that.getXPFactory()));
34    fColorStages = that.fColorStages;
35    fCoverageStages = that.fCoverageStages;
36    fClip = that.fClip;
37
38    fColorProcInfoValid = that.fColorProcInfoValid;
39    fCoverageProcInfoValid = that.fCoverageProcInfoValid;
40    fColorCache = that.fColorCache;
41    fCoverageCache = that.fCoverageCache;
42    if (fColorProcInfoValid) {
43        fColorProcInfo = that.fColorProcInfo;
44    }
45    if (fCoverageProcInfoValid) {
46        fCoverageProcInfo = that.fCoverageProcInfo;
47    }
48    return *this;
49}
50
51void GrPipelineBuilder::setFromPaint(const GrPaint& paint, GrRenderTarget* rt, const GrClip& clip) {
52    SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numFragmentStages());
53
54    fColorStages.reset();
55    fCoverageStages.reset();
56
57    for (int i = 0; i < paint.numColorStages(); ++i) {
58        fColorStages.push_back(paint.getColorStage(i));
59    }
60
61    for (int i = 0; i < paint.numCoverageStages(); ++i) {
62        fCoverageStages.push_back(paint.getCoverageStage(i));
63    }
64
65    fXPFactory.reset(SkRef(paint.getXPFactory()));
66
67    this->setRenderTarget(rt);
68
69    // These have no equivalent in GrPaint, set them to defaults
70    fDrawFace = kBoth_DrawFace;
71    fStencilSettings.setDisabled();
72    fFlags = 0;
73
74    fClip = clip;
75
76    this->setState(GrPipelineBuilder::kDither_Flag, paint.isDither());
77    this->setState(GrPipelineBuilder::kHWAntialias_Flag,
78                   rt->isMultisampled() && paint.isAntiAlias());
79
80    fColorProcInfoValid = false;
81    fCoverageProcInfoValid = false;
82
83    fColorCache = GrColor_ILLEGAL;
84    fCoverageCache = GrColor_ILLEGAL;
85}
86
87//////////////////////////////////////////////////////////////////////////////s
88
89bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps,
90                                          const GrProcOptInfo& colorPOI,
91                                          const GrProcOptInfo& coveragePOI) const {
92    return this->getXPFactory()->willNeedDstCopy(caps, colorPOI, coveragePOI);
93}
94
95void GrPipelineBuilder::AutoRestoreFragmentProcessors::set(GrPipelineBuilder* pipelineBuilder) {
96    if (fPipelineBuilder) {
97        int m = fPipelineBuilder->numColorFragmentStages() - fColorEffectCnt;
98        SkASSERT(m >= 0);
99        fPipelineBuilder->fColorStages.pop_back_n(m);
100
101        int n = fPipelineBuilder->numCoverageFragmentStages() - fCoverageEffectCnt;
102        SkASSERT(n >= 0);
103        fPipelineBuilder->fCoverageStages.pop_back_n(n);
104        if (m + n > 0) {
105            fPipelineBuilder->fColorProcInfoValid = false;
106            fPipelineBuilder->fCoverageProcInfoValid = false;
107        }
108        SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
109    }
110    fPipelineBuilder = pipelineBuilder;
111    if (NULL != pipelineBuilder) {
112        fColorEffectCnt = pipelineBuilder->numColorFragmentStages();
113        fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentStages();
114        SkDEBUGCODE(++pipelineBuilder->fBlockEffectRemovalCnt;)
115    }
116}
117
118////////////////////////////////////////////////////////////////////////////////
119
120GrPipelineBuilder::~GrPipelineBuilder() {
121    SkASSERT(0 == fBlockEffectRemovalCnt);
122}
123
124////////////////////////////////////////////////////////////////////////////////
125
126bool GrPipelineBuilder::willBlendWithDst(const GrPrimitiveProcessor* pp) const {
127    this->calcColorInvariantOutput(pp);
128    this->calcCoverageInvariantOutput(pp);
129
130    GrXPFactory::InvariantOutput output;
131    fXPFactory->getInvariantOutput(fColorProcInfo, fCoverageProcInfo, &output);
132    return output.fWillBlendWithDst;
133}
134
135void GrPipelineBuilder::calcColorInvariantOutput(const GrPrimitiveProcessor* pp) const {
136    fColorProcInfo.calcColorWithPrimProc(pp, fColorStages.begin(), this->numColorFragmentStages());
137    fColorProcInfoValid = false;
138
139}
140
141void GrPipelineBuilder::calcCoverageInvariantOutput(const GrPrimitiveProcessor* pp) const {
142    fCoverageProcInfo.calcCoverageWithPrimProc(pp, fCoverageStages.begin(),
143                                               this->numCoverageFragmentStages());
144    fCoverageProcInfoValid = false;
145}
146
147void GrPipelineBuilder::calcColorInvariantOutput(const GrBatch* batch) const {
148    fColorProcInfo.calcColorWithBatch(batch, fColorStages.begin(), this->numColorFragmentStages());
149    fColorProcInfoValid = false;
150}
151
152void GrPipelineBuilder::calcCoverageInvariantOutput(const GrBatch* batch) const {
153    fCoverageProcInfo.calcCoverageWithBatch(batch, fCoverageStages.begin(),
154                                            this->numCoverageFragmentStages());
155    fCoverageProcInfoValid = false;
156}
157
158
159void GrPipelineBuilder::calcColorInvariantOutput(GrColor color) const {
160    if (!fColorProcInfoValid || color != fColorCache) {
161        GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
162        fColorProcInfo.calcWithInitialValues(fColorStages.begin(),this->numColorFragmentStages(),
163                                             color, flags, false);
164        fColorProcInfoValid = true;
165        fColorCache = color;
166    }
167}
168
169void GrPipelineBuilder::calcCoverageInvariantOutput(GrColor coverage) const {
170    if (!fCoverageProcInfoValid || coverage != fCoverageCache) {
171        GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
172        fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(),
173                                                this->numCoverageFragmentStages(), coverage, flags,
174                                                true);
175        fCoverageProcInfoValid = true;
176        fCoverageCache = coverage;
177    }
178}
179