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