1 /* 2 * Copyright 2014 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 #ifndef GrPipelineAnalysis_DEFINED 9 #define GrPipelineAnalysis_DEFINED 10 11 #include "GrColor.h" 12 13 class GrDrawOp; 14 class GrFragmentProcessor; 15 class GrPrimitiveProcessor; 16 17 class GrPipelineAnalysisColor { 18 public: 19 enum class Opaque { 20 kNo, 21 kYes, 22 }; 23 24 GrPipelineAnalysisColor(Opaque opaque = Opaque::kNo) 25 : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0) {} 26 27 GrPipelineAnalysisColor(GrColor color) { this->setToConstant(color); } 28 29 void setToConstant(GrColor color) { 30 fColor = color; 31 if (GrColorIsOpaque(color)) { 32 fFlags = kColorIsKnown_Flag | kIsOpaque_Flag; 33 } else { 34 fFlags = kColorIsKnown_Flag; 35 } 36 } 37 38 void setToUnknown() { fFlags = 0; } 39 40 void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; } 41 42 bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); } 43 44 bool isConstant(GrColor* color) const { 45 if (kColorIsKnown_Flag & fFlags) { 46 *color = fColor; 47 return true; 48 } 49 return false; 50 } 51 52 private: 53 enum Flags { 54 kColorIsKnown_Flag = 0x1, 55 kIsOpaque_Flag = 0x2, 56 }; 57 uint32_t fFlags; 58 GrColor fColor; 59 }; 60 61 enum class GrPipelineAnalysisCoverage { kNone, kSingleChannel, kLCD }; 62 63 /** 64 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processor. 65 * It is used to recognize optimizations that can simplify the generated shader or make blending 66 * more effecient. 67 */ 68 class GrColorFragmentProcessorAnalysis { 69 public: 70 GrColorFragmentProcessorAnalysis() = default; 71 72 GrColorFragmentProcessorAnalysis(const GrPipelineAnalysisColor& input) 73 : GrColorFragmentProcessorAnalysis() { 74 fAllProcessorsCompatibleWithCoverageAsAlpha = true; 75 fIsOpaque = input.isOpaque(); 76 GrColor color; 77 if (input.isConstant(&color)) { 78 fLastKnownOutputColor = GrColor4f::FromGrColor(color); 79 fProcessorsVisitedWithKnownOutput = 0; 80 } 81 } 82 83 void reset(const GrPipelineAnalysisColor& input) { 84 *this = GrColorFragmentProcessorAnalysis(input); 85 } 86 87 /** 88 * Runs through a series of processors and updates calculated values. This can be called 89 * repeatedly for cases when the sequence of processors is not in a contiguous array. 90 */ 91 void analyzeProcessors(const GrFragmentProcessor* const* processors, int cnt); 92 93 bool isOpaque() const { return fIsOpaque; } 94 95 /** 96 * Are all the fragment processors compatible with conflating coverage with color prior to the 97 * the first fragment processor. This result does not consider processors that should be 98 * eliminated as indicated by initialProcessorsToEliminate(). 99 */ 100 bool allProcessorsCompatibleWithCoverageAsAlpha() const { 101 return fAllProcessorsCompatibleWithCoverageAsAlpha; 102 } 103 104 /** 105 * Do any of the fragment processors require local coords. This result does not consider 106 * processors that should be eliminated as indicated by initialProcessorsToEliminate(). 107 */ 108 bool usesLocalCoords() const { return fUsesLocalCoords; } 109 110 /** 111 * If we detected that the result after the first N processors is a known color then we 112 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with 113 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if 114 * there are only N processors) sees its expected input. If this returns 0 then there are no 115 * processors to eliminate. 116 */ 117 int initialProcessorsToEliminate(GrColor* newPipelineInputColor) const { 118 if (fProcessorsVisitedWithKnownOutput > 0) { 119 *newPipelineInputColor = fLastKnownOutputColor.toGrColor(); 120 } 121 return SkTMax(0, fProcessorsVisitedWithKnownOutput); 122 } 123 124 int initialProcessorsToEliminate(GrColor4f* newPipelineInputColor) const { 125 if (fProcessorsVisitedWithKnownOutput > 0) { 126 *newPipelineInputColor = fLastKnownOutputColor; 127 } 128 return SkTMax(0, fProcessorsVisitedWithKnownOutput); 129 } 130 131 GrPipelineAnalysisColor outputColor() const { 132 if (fProcessorsVisitedWithKnownOutput != fTotalProcessorsVisited) { 133 return GrPipelineAnalysisColor(fIsOpaque ? GrPipelineAnalysisColor::Opaque::kYes 134 : GrPipelineAnalysisColor::Opaque::kNo); 135 } 136 return GrPipelineAnalysisColor(fLastKnownOutputColor.toGrColor()); 137 } 138 139 private: 140 int fTotalProcessorsVisited = 0; 141 // negative one means even the color is unknown before adding the first processor. 142 int fProcessorsVisitedWithKnownOutput = -1; 143 bool fIsOpaque = false; 144 bool fAllProcessorsCompatibleWithCoverageAsAlpha = true; 145 bool fUsesLocalCoords = false; 146 GrColor4f fLastKnownOutputColor; 147 }; 148 149 #endif 150