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 "include/private/SkColorData.h" 12 13 class GrDrawOp; 14 class GrFragmentProcessor; 15 16 class GrProcessorAnalysisColor { 17 public: 18 enum class Opaque { 19 kNo, 20 kYes, 21 }; 22 23 constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo) 24 : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0) 25 , fColor(SK_PMColor4fTRANSPARENT) {} 26 GrProcessorAnalysisColor(const SkPMColor4f & color)27 GrProcessorAnalysisColor(const SkPMColor4f& color) { this->setToConstant(color); } 28 setToConstant(const SkPMColor4f & color)29 void setToConstant(const SkPMColor4f& color) { 30 fColor = color; 31 if (color.isOpaque()) { 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 isUnknown()42 bool isUnknown() const { return SkToBool(fFlags == 0); } 43 isOpaque()44 bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); } 45 46 bool isConstant(SkPMColor4f* color = nullptr) const { 47 if (kColorIsKnown_Flag & fFlags) { 48 if (color) { 49 *color = fColor; 50 } 51 return true; 52 } 53 return false; 54 } 55 56 bool operator==(const GrProcessorAnalysisColor& that) const { 57 if (fFlags != that.fFlags) { 58 return false; 59 } 60 return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true; 61 } 62 63 /** The returned value reflects the common properties of the two inputs. */ Combine(const GrProcessorAnalysisColor & a,const GrProcessorAnalysisColor & b)64 static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a, 65 const GrProcessorAnalysisColor& b) { 66 GrProcessorAnalysisColor result; 67 uint32_t commonFlags = a.fFlags & b.fFlags; 68 if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) { 69 result.fColor = a.fColor; 70 result.fFlags = a.fFlags; 71 } else if (kIsOpaque_Flag & commonFlags) { 72 result.fFlags = kIsOpaque_Flag; 73 } 74 return result; 75 } 76 77 private: 78 enum Flags { 79 kColorIsKnown_Flag = 0x1, 80 kIsOpaque_Flag = 0x2, 81 }; 82 uint32_t fFlags; 83 SkPMColor4f fColor; 84 }; 85 86 enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD }; 87 88 /** 89 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processors. 90 * It is used to recognize optimizations that can simplify the generated shader or make blending 91 * more effecient. 92 */ 93 class GrColorFragmentProcessorAnalysis { 94 public: 95 GrColorFragmentProcessorAnalysis() = delete; 96 97 GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input, 98 std::unique_ptr<GrFragmentProcessor> const fps[], 99 int count); 100 isOpaque()101 bool isOpaque() const { return fIsOpaque; } 102 103 /** 104 * Are all the fragment processors compatible with conflating coverage with color prior to the 105 * the first fragment processor. This result assumes that processors that should be eliminated 106 * as indicated by initialProcessorsToEliminate() are in fact eliminated. 107 */ allProcessorsCompatibleWithCoverageAsAlpha()108 bool allProcessorsCompatibleWithCoverageAsAlpha() const { 109 return fCompatibleWithCoverageAsAlpha; 110 } 111 112 /** 113 * Do any of the fragment processors require local coords. This result assumes that 114 * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in 115 * fact eliminated. 116 */ usesLocalCoords()117 bool usesLocalCoords() const { return fUsesLocalCoords; } 118 119 /** 120 * Do any of the fragment processors read back the destination color? 121 */ willReadDstColor()122 bool willReadDstColor() const { return fWillReadDstColor; } 123 124 /** 125 * Will we require a destination-surface texture? 126 */ 127 bool requiresDstTexture(const GrCaps& caps) const; 128 129 /** 130 * If we detected that the result after the first N processors is a known color then we 131 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with 132 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if 133 * there are only N processors) sees its expected input. If this returns 0 then there are no 134 * processors to eliminate. 135 */ initialProcessorsToEliminate(SkPMColor4f * newPipelineInputColor)136 int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const { 137 if (fProcessorsToEliminate > 0) { 138 *newPipelineInputColor = fLastKnownOutputColor; 139 } 140 return fProcessorsToEliminate; 141 } 142 143 /** 144 * Provides known information about the last processor's output color. 145 */ outputColor()146 GrProcessorAnalysisColor outputColor() const { 147 if (fOutputColorKnown) { 148 return fLastKnownOutputColor; 149 } 150 return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes 151 : GrProcessorAnalysisColor::Opaque::kNo; 152 } 153 154 private: 155 bool fIsOpaque; 156 bool fCompatibleWithCoverageAsAlpha; 157 bool fUsesLocalCoords; 158 bool fWillReadDstColor; 159 bool fOutputColorKnown; 160 int fProcessorsToEliminate; 161 SkPMColor4f fLastKnownOutputColor; 162 }; 163 164 #endif 165