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