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 "GrPipeline.h"
9 
10 #include "GrAppliedClip.h"
11 #include "GrCaps.h"
12 #include "GrGpu.h"
13 #include "GrPipelineBuilder.h"
14 #include "GrRenderTargetContext.h"
15 #include "GrRenderTargetOpList.h"
16 #include "GrRenderTargetPriv.h"
17 #include "GrXferProcessor.h"
18 
19 #include "ops/GrOp.h"
20 
init(const InitArgs & args)21 GrPipelineOptimizations GrPipeline::init(const InitArgs& args) {
22     SkASSERT(args.fAnalysis);
23     SkASSERT(args.fRenderTarget);
24 
25     fRenderTarget.reset(args.fRenderTarget);
26 
27     fFlags = args.fFlags;
28     if (args.fAppliedClip) {
29         fScissorState = args.fAppliedClip->scissorState();
30         if (args.fAppliedClip->hasStencilClip()) {
31             fFlags |= kHasStencilClip_Flag;
32         }
33         fWindowRectsState = args.fAppliedClip->windowRectsState();
34     }
35     if (args.fProcessors->usesDistanceVectorField()) {
36         fFlags |= kUsesDistanceVectorField_Flag;
37     }
38     if (args.fProcessors->disableOutputConversionToSRGB()) {
39         fFlags |= kDisableOutputConversionToSRGB_Flag;
40     }
41     if (args.fProcessors->allowSRGBInputs()) {
42         fFlags |= kAllowSRGBInputs_Flag;
43     }
44     if (!args.fUserStencil->isDisabled(fFlags & kHasStencilClip_Flag)) {
45         fFlags |= kStencilEnabled_Flag;
46     }
47 
48     fUserStencilSettings = args.fUserStencil;
49 
50     fDrawFace = static_cast<int16_t>(args.fDrawFace);
51 
52     bool isHWAA = kHWAntialias_Flag & args.fFlags;
53 
54     // Create XferProcessor from DS's XPFactory
55     bool hasMixedSamples = args.fRenderTarget->isMixedSampled() && (isHWAA || isStencilEnabled());
56     const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
57     sk_sp<GrXferProcessor> xferProcessor;
58     if (xpFactory) {
59         xferProcessor.reset(xpFactory->createXferProcessor(*args.fAnalysis, hasMixedSamples,
60                                                            &args.fDstTexture, *args.fCaps));
61         SkASSERT(xferProcessor);
62     } else {
63         // This may return nullptr in the common case of src-over implemented using hw blending.
64         xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
65                 *args.fCaps, *args.fAnalysis, hasMixedSamples, &args.fDstTexture));
66     }
67     GrColor overrideColor = GrColor_ILLEGAL;
68     int colorFPsToEliminate =
69             args.fAnalysis->getInputColorOverrideAndColorProcessorEliminationCount(&overrideColor);
70     colorFPsToEliminate = SkTMax(colorFPsToEliminate, 0);
71 
72     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
73 
74     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
75                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
76     optFlags = xpForOpts->getOptimizations(*args.fAnalysis);
77 
78     // No need to have an override color if it isn't even going to be used.
79     if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) {
80         overrideColor = GrColor_ILLEGAL;
81     }
82 
83     fXferProcessor.reset(xferProcessor.get());
84 
85     if ((optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) {
86         colorFPsToEliminate = args.fProcessors->numColorFragmentProcessors();
87     }
88 
89     // Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline, possibly removing some of the
90     // color fragment processors.
91     fNumColorProcessors = args.fProcessors->numColorFragmentProcessors() - colorFPsToEliminate;
92     int numTotalProcessors =
93             fNumColorProcessors + args.fProcessors->numCoverageFragmentProcessors();
94     if (args.fAppliedClip && args.fAppliedClip->clipCoverageFragmentProcessor()) {
95         ++numTotalProcessors;
96     }
97     fFragmentProcessors.reset(numTotalProcessors);
98     int currFPIdx = 0;
99     for (int i = colorFPsToEliminate; i < args.fProcessors->numColorFragmentProcessors();
100          ++i, ++currFPIdx) {
101         const GrFragmentProcessor* fp = args.fProcessors->colorFragmentProcessor(i);
102         fFragmentProcessors[currFPIdx].reset(fp);
103     }
104 
105     for (int i = 0; i < args.fProcessors->numCoverageFragmentProcessors(); ++i, ++currFPIdx) {
106         const GrFragmentProcessor* fp = args.fProcessors->coverageFragmentProcessor(i);
107         fFragmentProcessors[currFPIdx].reset(fp);
108     }
109     if (args.fAppliedClip) {
110         if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
111             fFragmentProcessors[currFPIdx].reset(fp);
112         }
113     }
114 
115     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
116     GrPipelineOptimizations optimizations;
117     optimizations.fFlags = 0;
118     if (GrColor_ILLEGAL != overrideColor) {
119         optimizations.fFlags |= GrPipelineOptimizations::kUseOverrideColor_Flag;
120         optimizations.fOverrideColor = overrideColor;
121     }
122     if (args.fAnalysis->usesLocalCoords()) {
123         optimizations.fFlags |= GrPipelineOptimizations::kReadsLocalCoords_Flag;
124     }
125     if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
126         optimizations.fFlags |= GrPipelineOptimizations::kCanTweakAlphaForCoverage_Flag;
127     }
128     return optimizations;
129 }
130 
add_dependencies_for_processor(const GrFragmentProcessor * proc,GrRenderTarget * rt)131 static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) {
132     GrFragmentProcessor::TextureAccessIter iter(proc);
133     while (const GrProcessor::TextureSampler* sampler = iter.next()) {
134         SkASSERT(rt->getLastOpList());
135         rt->getLastOpList()->addDependency(sampler->texture());
136     }
137 }
138 
addDependenciesTo(GrRenderTarget * rt) const139 void GrPipeline::addDependenciesTo(GrRenderTarget* rt) const {
140     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
141         add_dependencies_for_processor(fFragmentProcessors[i].get(), rt);
142     }
143 
144     const GrXferProcessor& xfer = this->getXferProcessor();
145 
146     for (int i = 0; i < xfer.numTextureSamplers(); ++i) {
147         GrTexture* texture = xfer.textureSampler(i).texture();
148         SkASSERT(rt->getLastOpList());
149         rt->getLastOpList()->addDependency(texture);
150     }
151 }
152 
GrPipeline(GrRenderTarget * rt,SkBlendMode blendmode)153 GrPipeline::GrPipeline(GrRenderTarget* rt, SkBlendMode blendmode)
154     : fRenderTarget(rt)
155     , fScissorState()
156     , fWindowRectsState()
157     , fUserStencilSettings(&GrUserStencilSettings::kUnused)
158     , fDrawFace(static_cast<uint16_t>(GrDrawFace::kBoth))
159     , fFlags()
160     , fXferProcessor(GrPorterDuffXPFactory::CreateNoCoverageXP(blendmode).get())
161     , fFragmentProcessors()
162     , fNumColorProcessors(0) {
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 
AreEqual(const GrPipeline & a,const GrPipeline & b)167 bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b) {
168     SkASSERT(&a != &b);
169 
170     if (a.getRenderTarget() != b.getRenderTarget() ||
171         a.fFragmentProcessors.count() != b.fFragmentProcessors.count() ||
172         a.fNumColorProcessors != b.fNumColorProcessors ||
173         a.fScissorState != b.fScissorState ||
174         a.fWindowRectsState != b.fWindowRectsState ||
175         a.fFlags != b.fFlags ||
176         a.fUserStencilSettings != b.fUserStencilSettings ||
177         a.fDrawFace != b.fDrawFace) {
178         return false;
179     }
180 
181     // Most of the time both are nullptr
182     if (a.fXferProcessor.get() || b.fXferProcessor.get()) {
183         if (!a.getXferProcessor().isEqual(b.getXferProcessor())) {
184             return false;
185         }
186     }
187 
188     for (int i = 0; i < a.numFragmentProcessors(); i++) {
189         if (!a.getFragmentProcessor(i).isEqual(b.getFragmentProcessor(i))) {
190             return false;
191         }
192     }
193     return true;
194 }
195