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 processor. 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 cnt); 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 * If we detected that the result after the first N processors is a known color then we 121 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with 122 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if 123 * there are only N processors) sees its expected input. If this returns 0 then there are no 124 * processors to eliminate. 125 */ initialProcessorsToEliminate(SkPMColor4f * newPipelineInputColor)126 int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const { 127 if (fProcessorsToEliminate > 0) { 128 *newPipelineInputColor = fLastKnownOutputColor; 129 } 130 return fProcessorsToEliminate; 131 } 132 133 /** 134 * Provides known information about the last processor's output color. 135 */ outputColor()136 GrProcessorAnalysisColor outputColor() const { 137 if (fKnowOutputColor) { 138 return fLastKnownOutputColor; 139 } 140 return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes 141 : GrProcessorAnalysisColor::Opaque::kNo; 142 } 143 144 private: 145 bool fIsOpaque; 146 bool fCompatibleWithCoverageAsAlpha; 147 bool fUsesLocalCoords; 148 bool fKnowOutputColor; 149 int fProcessorsToEliminate; 150 SkPMColor4f fLastKnownOutputColor; 151 }; 152 153 #endif 154