1 2 /* 3 * Copyright 2015 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "GrFragmentProcessor.h" 10 #include "GrCoordTransform.h" 11 #include "GrInvariantOutput.h" 12 #include "GrProcOptInfo.h" 13 #include "glsl/GrGLSLFragmentProcessor.h" 14 #include "glsl/GrGLSLFragmentShaderBuilder.h" 15 #include "glsl/GrGLSLProgramDataManager.h" 16 #include "glsl/GrGLSLUniformHandler.h" 17 #include "effects/GrConstColorProcessor.h" 18 #include "effects/GrXfermodeFragmentProcessor.h" 19 20 GrFragmentProcessor::~GrFragmentProcessor() { 21 // If we got here then our ref count must have reached zero, so we will have converted refs 22 // to pending executions for all children. 23 for (int i = 0; i < fChildProcessors.count(); ++i) { 24 fChildProcessors[i]->completedExecution(); 25 } 26 } 27 28 bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that, 29 bool ignoreCoordTransforms) const { 30 if (this->classID() != that.classID() || 31 !this->hasSameTextureAccesses(that)) { 32 return false; 33 } 34 if (ignoreCoordTransforms) { 35 if (this->numTransforms() != that.numTransforms()) { 36 return false; 37 } 38 } else if (!this->hasSameTransforms(that)) { 39 return false; 40 } 41 if (!this->onIsEqual(that)) { 42 return false; 43 } 44 if (this->numChildProcessors() != that.numChildProcessors()) { 45 return false; 46 } 47 for (int i = 0; i < this->numChildProcessors(); ++i) { 48 if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) { 49 return false; 50 } 51 } 52 return true; 53 } 54 55 GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const { 56 GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance(); 57 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count()); 58 for (int i = 0; i < fChildProcessors.count(); ++i) { 59 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance(); 60 } 61 return glFragProc; 62 } 63 64 void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) { 65 // Can't add texture accesses after registering any children since their texture accesses have 66 // already been bubbled up into our fTextureAccesses array 67 SkASSERT(fChildProcessors.empty()); 68 69 INHERITED::addTextureAccess(textureAccess); 70 fNumTexturesExclChildren++; 71 } 72 73 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { 74 // Can't add transforms after registering any children since their transforms have already been 75 // bubbled up into our fCoordTransforms array 76 SkASSERT(fChildProcessors.empty()); 77 78 fCoordTransforms.push_back(transform); 79 fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet; 80 SkDEBUGCODE(transform->setInProcessor();) 81 fNumTransformsExclChildren++; 82 } 83 84 int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) { 85 // Append the child's transforms to our transforms array and the child's textures array to our 86 // textures array 87 if (!child->fCoordTransforms.empty()) { 88 fCoordTransforms.push_back_n(child->fCoordTransforms.count(), 89 child->fCoordTransforms.begin()); 90 } 91 if (!child->fTextureAccesses.empty()) { 92 fTextureAccesses.push_back_n(child->fTextureAccesses.count(), 93 child->fTextureAccesses.begin()); 94 } 95 96 int index = fChildProcessors.count(); 97 fChildProcessors.push_back(SkRef(child)); 98 99 if (child->willReadFragmentPosition()) { 100 this->setWillReadFragmentPosition(); 101 } 102 103 if (child->usesLocalCoords()) { 104 fUsesLocalCoords = true; 105 } 106 107 return index; 108 } 109 110 void GrFragmentProcessor::notifyRefCntIsZero() const { 111 // See comment above GrProgramElement for a detailed explanation of why we do this. 112 for (int i = 0; i < fChildProcessors.count(); ++i) { 113 fChildProcessors[i]->addPendingExecution(); 114 fChildProcessors[i]->unref(); 115 } 116 } 117 118 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const { 119 if (this->numTransforms() != that.numTransforms()) { 120 return false; 121 } 122 int count = this->numTransforms(); 123 for (int i = 0; i < count; ++i) { 124 if (this->coordTransform(i) != that.coordTransform(i)) { 125 return false; 126 } 127 } 128 return true; 129 } 130 131 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputAlpha( 132 const GrFragmentProcessor* fp) { 133 if (!fp) { 134 return nullptr; 135 } 136 return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode); 137 } 138 139 const GrFragmentProcessor* GrFragmentProcessor::MulOutputByInputUnpremulColor( 140 const GrFragmentProcessor* fp) { 141 142 class PremulFragmentProcessor : public GrFragmentProcessor { 143 public: 144 PremulFragmentProcessor(const GrFragmentProcessor* processor) { 145 this->initClassID<PremulFragmentProcessor>(); 146 this->registerChildProcessor(processor); 147 } 148 149 const char* name() const override { return "Premultiply"; } 150 151 private: 152 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 153 class GLFP : public GrGLSLFragmentProcessor { 154 public: 155 void emitCode(EmitArgs& args) override { 156 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 157 this->emitChild(0, nullptr, args); 158 fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor, 159 args.fInputColor); 160 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor); 161 } 162 }; 163 return new GLFP; 164 } 165 166 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {} 167 168 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 169 170 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 171 // TODO: Add a helper to GrInvariantOutput that handles multiplying by color with flags? 172 if (!(inout->validFlags() & kA_GrColorComponentFlag)) { 173 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 174 return; 175 } 176 177 GrInvariantOutput childOutput(GrColor_WHITE, kRGBA_GrColorComponentFlags, false); 178 this->childProcessor(0).computeInvariantOutput(&childOutput); 179 180 if (0 == GrColorUnpackA(inout->color()) || 0 == GrColorUnpackA(childOutput.color())) { 181 inout->mulByKnownFourComponents(0x0); 182 return; 183 } 184 GrColorComponentFlags commonFlags = childOutput.validFlags() & inout->validFlags(); 185 GrColor c0 = GrPremulColor(inout->color()); 186 GrColor c1 = childOutput.color(); 187 GrColor color = 0x0; 188 if (commonFlags & kR_GrColorComponentFlag) { 189 color |= SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1)) << 190 GrColor_SHIFT_R; 191 } 192 if (commonFlags & kG_GrColorComponentFlag) { 193 color |= SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1)) << 194 GrColor_SHIFT_G; 195 } 196 if (commonFlags & kB_GrColorComponentFlag) { 197 color |= SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1)) << 198 GrColor_SHIFT_B; 199 } 200 inout->setToOther(commonFlags, color, GrInvariantOutput::kWill_ReadInput); 201 } 202 }; 203 if (!fp) { 204 return nullptr; 205 } 206 return new PremulFragmentProcessor(fp); 207 } 208 209 ////////////////////////////////////////////////////////////////////////////// 210 211 const GrFragmentProcessor* GrFragmentProcessor::OverrideInput(const GrFragmentProcessor* fp, 212 GrColor color) { 213 class ReplaceInputFragmentProcessor : public GrFragmentProcessor { 214 public: 215 ReplaceInputFragmentProcessor(const GrFragmentProcessor* child, GrColor color) 216 : fColor(color) { 217 this->initClassID<ReplaceInputFragmentProcessor>(); 218 this->registerChildProcessor(child); 219 } 220 221 const char* name() const override { return "Replace Color"; } 222 223 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 224 class GLFP : public GrGLSLFragmentProcessor { 225 public: 226 GLFP() : fHaveSetColor(false) {} 227 void emitCode(EmitArgs& args) override { 228 const char* colorName; 229 fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, 230 kVec4f_GrSLType, 231 kDefault_GrSLPrecision, 232 "Color", &colorName); 233 this->emitChild(0, colorName, args); 234 } 235 236 private: 237 void onSetData(const GrGLSLProgramDataManager& pdman, 238 const GrProcessor& fp) override { 239 GrColor color = fp.cast<ReplaceInputFragmentProcessor>().fColor; 240 if (!fHaveSetColor || color != fPreviousColor) { 241 static const float scale = 1.f / 255.f; 242 float floatColor[4] = { 243 GrColorUnpackR(color) * scale, 244 GrColorUnpackG(color) * scale, 245 GrColorUnpackB(color) * scale, 246 GrColorUnpackA(color) * scale, 247 }; 248 pdman.set4fv(fColorUni, 1, floatColor); 249 fPreviousColor = color; 250 fHaveSetColor = true; 251 } 252 } 253 254 GrGLSLProgramDataManager::UniformHandle fColorUni; 255 bool fHaveSetColor; 256 GrColor fPreviousColor; 257 }; 258 259 return new GLFP; 260 } 261 262 private: 263 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override 264 {} 265 266 bool onIsEqual(const GrFragmentProcessor& that) const override { 267 return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor; 268 } 269 270 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 271 inout->setToOther(kRGBA_GrColorComponentFlags, fColor, 272 GrInvariantOutput::kWillNot_ReadInput); 273 this->childProcessor(0).computeInvariantOutput(inout); 274 } 275 276 GrColor fColor; 277 }; 278 279 GrInvariantOutput childOut(0x0, kNone_GrColorComponentFlags, false); 280 fp->computeInvariantOutput(&childOut); 281 if (childOut.willUseInputColor()) { 282 return new ReplaceInputFragmentProcessor(fp, color); 283 } else { 284 return SkRef(fp); 285 } 286 } 287 288 const GrFragmentProcessor* GrFragmentProcessor::RunInSeries(const GrFragmentProcessor* series[], 289 int cnt) { 290 class SeriesFragmentProcessor : public GrFragmentProcessor { 291 public: 292 SeriesFragmentProcessor(const GrFragmentProcessor* children[], int cnt){ 293 SkASSERT(cnt > 1); 294 this->initClassID<SeriesFragmentProcessor>(); 295 for (int i = 0; i < cnt; ++i) { 296 this->registerChildProcessor(children[i]); 297 } 298 } 299 300 const char* name() const override { return "Series"; } 301 302 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 303 class GLFP : public GrGLSLFragmentProcessor { 304 public: 305 void emitCode(EmitArgs& args) override { 306 SkString input(args.fInputColor); 307 for (int i = 0; i < this->numChildProcessors() - 1; ++i) { 308 SkString temp; 309 temp.printf("out%d", i); 310 this->emitChild(i, input.c_str(), &temp, args); 311 input = temp; 312 } 313 // Last guy writes to our output variable. 314 this->emitChild(this->numChildProcessors() - 1, input.c_str(), args); 315 } 316 }; 317 return new GLFP; 318 } 319 320 private: 321 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override {} 322 323 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 324 325 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 326 GrProcOptInfo info; 327 SkTDArray<const GrFragmentProcessor*> children; 328 children.setCount(this->numChildProcessors()); 329 for (int i = 0; i < children.count(); ++i) { 330 children[i] = &this->childProcessor(i); 331 } 332 info.calcWithInitialValues(children.begin(), children.count(), inout->color(), 333 inout->validFlags(), false, false); 334 for (int i = 0; i < this->numChildProcessors(); ++i) { 335 this->childProcessor(i).computeInvariantOutput(inout); 336 } 337 } 338 }; 339 340 if (!cnt) { 341 return nullptr; 342 } 343 344 // Run the through the series, do the invariant output processing, and look for eliminations. 345 SkTDArray<const GrFragmentProcessor*> replacementSeries; 346 SkAutoTUnref<const GrFragmentProcessor> colorFP; 347 GrProcOptInfo info; 348 349 info.calcWithInitialValues(series, cnt, 0x0, kNone_GrColorComponentFlags, false, false); 350 if (kRGBA_GrColorComponentFlags == info.validFlags()) { 351 return GrConstColorProcessor::Create(info.color(), 352 GrConstColorProcessor::kIgnore_InputMode); 353 } else { 354 int firstIdx = info.firstEffectiveProcessorIndex(); 355 cnt -= firstIdx; 356 if (firstIdx > 0 && info.inputColorIsUsed()) { 357 colorFP.reset(GrConstColorProcessor::Create(info.inputColorToFirstEffectiveProccesor(), 358 GrConstColorProcessor::kIgnore_InputMode)); 359 cnt += 1; 360 replacementSeries.setCount(cnt); 361 replacementSeries[0] = colorFP; 362 for (int i = 0; i < cnt - 1; ++i) { 363 replacementSeries[i + 1] = series[firstIdx + i]; 364 } 365 series = replacementSeries.begin(); 366 } else { 367 series += firstIdx; 368 cnt -= firstIdx; 369 } 370 } 371 372 if (1 == cnt) { 373 return SkRef(series[0]); 374 } else { 375 return new SeriesFragmentProcessor(series, cnt); 376 } 377 } 378 379