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