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