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 "GrCaps.h" 11 #include "GrDrawTarget.h" 12 #include "GrGpu.h" 13 #include "GrPipelineBuilder.h" 14 #include "GrProcOptInfo.h" 15 #include "GrXferProcessor.h" 16 17 #include "batches/GrBatch.h" 18 19 GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, 20 GrXPOverridesForBatch* overrides) { 21 const GrPipelineBuilder& builder = *args.fPipelineBuilder; 22 23 // Create XferProcessor from DS's XPFactory 24 const GrXPFactory* xpFactory = builder.getXPFactory(); 25 SkAutoTUnref<GrXferProcessor> xferProcessor; 26 if (xpFactory) { 27 xferProcessor.reset(xpFactory->createXferProcessor(args.fOpts, 28 builder.hasMixedSamples(), 29 &args.fDstTexture, 30 *args.fCaps)); 31 if (!xferProcessor) { 32 return nullptr; 33 } 34 } else { 35 // This may return nullptr in the common case of src-over implemented using hw blending. 36 xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor( 37 *args.fCaps, 38 args.fOpts, 39 builder.hasMixedSamples(), 40 &args.fDstTexture)); 41 } 42 GrColor overrideColor = GrColor_ILLEGAL; 43 if (args.fOpts.fColorPOI.firstEffectiveProcessorIndex() != 0) { 44 overrideColor = args.fOpts.fColorPOI.inputColorToFirstEffectiveProccesor(); 45 } 46 47 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags; 48 49 const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() : 50 &GrPorterDuffXPFactory::SimpleSrcOverXP(); 51 optFlags = xpForOpts->getOptimizations(args.fOpts, 52 builder.getStencil().doesWrite(), 53 &overrideColor, 54 *args.fCaps); 55 56 // When path rendering the stencil settings are not always set on the GrPipelineBuilder 57 // so we must check the draw type. In cases where we will skip drawing we simply return a 58 // null GrPipeline. 59 if (GrXferProcessor::kSkipDraw_OptFlag & optFlags) { 60 return nullptr; 61 } 62 63 // No need to have an override color if it isn't even going to be used. 64 if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) { 65 overrideColor = GrColor_ILLEGAL; 66 } 67 68 GrPipeline* pipeline = new (memory) GrPipeline; 69 pipeline->fXferProcessor.reset(xferProcessor); 70 71 pipeline->fRenderTarget.reset(builder.fRenderTarget.get()); 72 SkASSERT(pipeline->fRenderTarget); 73 pipeline->fScissorState = *args.fScissor; 74 pipeline->fStencilSettings = builder.getStencil(); 75 pipeline->fDrawFace = builder.getDrawFace(); 76 77 pipeline->fFlags = 0; 78 if (builder.isHWAntialias()) { 79 pipeline->fFlags |= kHWAA_Flag; 80 } 81 if (builder.snapVerticesToPixelCenters()) { 82 pipeline->fFlags |= kSnapVertices_Flag; 83 } 84 85 int firstColorProcessorIdx = args.fOpts.fColorPOI.firstEffectiveProcessorIndex(); 86 87 // TODO: Once we can handle single or four channel input into coverage GrFragmentProcessors 88 // then we can use GrPipelineBuilder's coverageProcInfo (like color above) to set this initial 89 // information. 90 int firstCoverageProcessorIdx = 0; 91 92 pipeline->adjustProgramFromOptimizations(builder, optFlags, args.fOpts.fColorPOI, 93 args.fOpts.fCoveragePOI, &firstColorProcessorIdx, 94 &firstCoverageProcessorIdx); 95 96 bool usesLocalCoords = false; 97 98 // Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline 99 pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx; 100 int numTotalProcessors = pipeline->fNumColorProcessors + 101 builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx; 102 pipeline->fFragmentProcessors.reset(numTotalProcessors); 103 int currFPIdx = 0; 104 for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors(); 105 ++i, ++currFPIdx) { 106 const GrFragmentProcessor* fp = builder.getColorFragmentProcessor(i); 107 pipeline->fFragmentProcessors[currFPIdx].reset(fp); 108 usesLocalCoords = usesLocalCoords || fp->usesLocalCoords(); 109 } 110 111 for (int i = firstCoverageProcessorIdx; i < builder.numCoverageFragmentProcessors(); 112 ++i, ++currFPIdx) { 113 const GrFragmentProcessor* fp = builder.getCoverageFragmentProcessor(i); 114 pipeline->fFragmentProcessors[currFPIdx].reset(fp); 115 usesLocalCoords = usesLocalCoords || fp->usesLocalCoords(); 116 } 117 118 // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline. 119 overrides->fFlags = 0; 120 if (!SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) { 121 overrides->fFlags |= GrXPOverridesForBatch::kReadsColor_Flag; 122 } 123 if (GrColor_ILLEGAL != overrideColor) { 124 overrides->fFlags |= GrXPOverridesForBatch::kUseOverrideColor_Flag; 125 overrides->fOverrideColor = overrideColor; 126 } 127 if (!SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag)) { 128 overrides->fFlags |= GrXPOverridesForBatch::kReadsCoverage_Flag; 129 } 130 if (usesLocalCoords) { 131 overrides->fFlags |= GrXPOverridesForBatch::kReadsLocalCoords_Flag; 132 } 133 if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) { 134 overrides->fFlags |= GrXPOverridesForBatch::kCanTweakAlphaForCoverage_Flag; 135 } 136 137 GrXPFactory::InvariantBlendedColor blendedColor; 138 if (xpFactory) { 139 xpFactory->getInvariantBlendedColor(args.fOpts.fColorPOI, &blendedColor); 140 } else { 141 GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(args.fOpts.fColorPOI.color(), 142 args.fOpts.fColorPOI.validFlags(), 143 args.fOpts.fColorPOI.isOpaque(), 144 &blendedColor); 145 } 146 if (blendedColor.fWillBlendWithDst) { 147 overrides->fFlags |= GrXPOverridesForBatch::kWillColorBlendWithDst_Flag; 148 } 149 150 return pipeline; 151 } 152 153 static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) { 154 for (int i = 0; i < proc->numChildProcessors(); ++i) { 155 // need to recurse 156 add_dependencies_for_processor(&proc->childProcessor(i), rt); 157 } 158 159 for (int i = 0; i < proc->numTextures(); ++i) { 160 GrTexture* texture = proc->textureAccess(i).getTexture(); 161 SkASSERT(rt->getLastDrawTarget()); 162 rt->getLastDrawTarget()->addDependency(texture); 163 } 164 } 165 166 void GrPipeline::addDependenciesTo(GrRenderTarget* rt) const { 167 for (int i = 0; i < fFragmentProcessors.count(); ++i) { 168 add_dependencies_for_processor(fFragmentProcessors[i].get(), rt); 169 } 170 171 const GrXferProcessor& xfer = this->getXferProcessor(); 172 173 for (int i = 0; i < xfer.numTextures(); ++i) { 174 GrTexture* texture = xfer.textureAccess(i).getTexture(); 175 SkASSERT(rt->getLastDrawTarget()); 176 rt->getLastDrawTarget()->addDependency(texture); 177 } 178 } 179 180 void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder, 181 GrXferProcessor::OptFlags flags, 182 const GrProcOptInfo& colorPOI, 183 const GrProcOptInfo& coveragePOI, 184 int* firstColorProcessorIdx, 185 int* firstCoverageProcessorIdx) { 186 fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag); 187 fReadsFragPosition = this->getXferProcessor().willReadFragmentPosition(); 188 189 if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) || 190 (flags & GrXferProcessor::kOverrideColor_OptFlag)) { 191 *firstColorProcessorIdx = pipelineBuilder.numColorFragmentProcessors(); 192 } else { 193 if (colorPOI.readsFragPosition()) { 194 fReadsFragPosition = true; 195 } 196 } 197 198 if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) { 199 *firstCoverageProcessorIdx = pipelineBuilder.numCoverageFragmentProcessors(); 200 } else { 201 if (coveragePOI.readsFragPosition()) { 202 fReadsFragPosition = true; 203 } 204 } 205 } 206 207 //////////////////////////////////////////////////////////////////////////////// 208 209 bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b, 210 bool ignoreCoordTransforms) { 211 SkASSERT(&a != &b); 212 213 if (a.getRenderTarget() != b.getRenderTarget() || 214 a.fFragmentProcessors.count() != b.fFragmentProcessors.count() || 215 a.fNumColorProcessors != b.fNumColorProcessors || 216 a.fScissorState != b.fScissorState || 217 a.fFlags != b.fFlags || 218 a.fStencilSettings != b.fStencilSettings || 219 a.fDrawFace != b.fDrawFace) { 220 return false; 221 } 222 223 // Most of the time both are nullptr 224 if (a.fXferProcessor.get() || b.fXferProcessor.get()) { 225 if (!a.getXferProcessor().isEqual(b.getXferProcessor())) { 226 return false; 227 } 228 } 229 230 for (int i = 0; i < a.numFragmentProcessors(); i++) { 231 if (!a.getFragmentProcessor(i).isEqual(b.getFragmentProcessor(i), ignoreCoordTransforms)) { 232 return false; 233 } 234 } 235 return true; 236 } 237 238