blob: bfad769a1881fd5ea877f3ae8d72a13a3a8aee29 [file] [log] [blame]
Brian Salomon92ce5942017-01-18 11:01:10 -05001/*
2 * Copyright 2017 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 GrProcessorSet_DEFINED
9#define GrProcessorSet_DEFINED
10
11#include "GrFragmentProcessor.h"
12#include "GrPaint.h"
Brian Salomonc0b642c2017-03-27 13:09:36 -040013#include "GrPipelineAnalysis.h"
Brian Salomon92ce5942017-01-18 11:01:10 -050014#include "SkTemplates.h"
15
Brian Salomon5298dc82017-02-22 11:52:03 -050016class GrAppliedClip;
Brian Salomon92ce5942017-01-18 11:01:10 -050017class GrXPFactory;
18
19class GrProcessorSet : private SkNoncopyable {
20public:
21 GrProcessorSet(GrPaint&& paint);
22
Brian Salomon54d212e2017-03-21 14:22:38 -040023 ~GrProcessorSet();
24
25 /**
26 * If an op is recorded with this processor set then this must be called to ensure pending
27 * reads and writes are propagated to resources referred to by the processors. Otherwise,
28 * data hazards may occur.
29 */
30 void makePendingExecution();
31 bool isPendingExecution() const { return SkToBool(kPendingExecution_Flag & fFlags); }
Brian Salomon92ce5942017-01-18 11:01:10 -050032
33 int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
34 int numCoverageFragmentProcessors() const {
Brian Salomon70288c02017-03-24 12:27:17 -040035 return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
Brian Salomon92ce5942017-01-18 11:01:10 -050036 }
Brian Salomon70288c02017-03-24 12:27:17 -040037 int numFragmentProcessors() const {
38 return fFragmentProcessors.count() - fFragmentProcessorOffset;
39 }
Brian Salomon92ce5942017-01-18 11:01:10 -050040
41 const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
42 SkASSERT(idx < fColorFragmentProcessorCnt);
Brian Salomon70288c02017-03-24 12:27:17 -040043 return fFragmentProcessors[idx + fFragmentProcessorOffset];
Brian Salomon92ce5942017-01-18 11:01:10 -050044 }
45 const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
Brian Salomon70288c02017-03-24 12:27:17 -040046 return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset];
Brian Salomon92ce5942017-01-18 11:01:10 -050047 }
48
49 const GrXPFactory* xpFactory() const { return fXPFactory; }
50
Brian Salomonf87e2b92017-01-19 11:31:50 -050051 bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
52 bool disableOutputConversionToSRGB() const {
53 return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
54 }
55 bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
Brian Salomon189098e72017-01-19 09:55:19 -050056
Brian Salomon54d212e2017-03-21 14:22:38 -040057 bool operator==(const GrProcessorSet& that) const;
58 bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
59
Brian Salomon5298dc82017-02-22 11:52:03 -050060 /**
61 * This is used to track analysis of color and coverage values through the fragment processors.
62 */
63 class FragmentProcessorAnalysis {
64 public:
Brian Salomon8d2f90b2017-03-13 09:11:58 -040065 /**
66 * This constructor allows an op to record its initial color in a FragmentProcessorAnalysis
67 * member and then run analysis later when the analysis inputs are available. If the
68 * analysis produces color fragment processor elimination then the input color is replaced
69 * by the expected input to the first non-eliminated processor. Otherwise, the original
70 * input color is preserved. The only reason to use this is to save space on the op by not
71 * separately storing the initial color.
72 */
73 explicit FragmentProcessorAnalysis(GrColor initialColor) : FragmentProcessorAnalysis() {
74 fInputColor = initialColor;
75 fValidInputColor = true;
76 }
77
78 FragmentProcessorAnalysis()
79 : fIsInitializedWithProcessorSet(false)
80 , fCompatibleWithCoverageAsAlpha(true)
81 , fValidInputColor(false)
Brian Salomonc0b642c2017-03-27 13:09:36 -040082 , fOutputCoverageType(static_cast<unsigned>(GrPipelineAnalysisCoverage::kNone))
Brian Salomon8d2f90b2017-03-13 09:11:58 -040083 , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
84 , fInitialColorProcessorsToEliminate(0) {}
85
86 // This version is used by a unit test that assumes no clip, no processors, and no PLS.
Brian Salomonc0b642c2017-03-27 13:09:36 -040087 FragmentProcessorAnalysis(const GrPipelineAnalysisColor&, GrPipelineAnalysisCoverage,
88 const GrCaps&);
Brian Salomon5298dc82017-02-22 11:52:03 -050089
Brian Salomonc0b642c2017-03-27 13:09:36 -040090 void init(const GrPipelineAnalysisColor&, GrPipelineAnalysisCoverage, const GrProcessorSet&,
91 const GrAppliedClip*, const GrCaps&);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040092
93 bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
Brian Salomon5298dc82017-02-22 11:52:03 -050094
Brian Salomon70288c02017-03-24 12:27:17 -040095 /**
96 * If the return is greater than or equal to zero then 'newInputColor' should be used as the
97 * input color to the GrPipeline derived from this processor set, replacing the GrDrawOp's
98 * initial color. If the return is less than zero then newInputColor has not been
99 * modified and no modification need be made to the pipeline's input color by the op.
100 */
101 int getInputColorOverrideAndColorProcessorEliminationCount(GrColor* newInputColor) const {
102 if (fValidInputColor) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400103 *newInputColor = fInputColor;
Brian Salomon70288c02017-03-24 12:27:17 -0400104 return fInitialColorProcessorsToEliminate;
Brian Salomon5298dc82017-02-22 11:52:03 -0500105 }
Brian Salomon70288c02017-03-24 12:27:17 -0400106 SkASSERT(!fInitialColorProcessorsToEliminate);
107 return -1;
Brian Salomon5298dc82017-02-22 11:52:03 -0500108 }
109
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400110 /**
111 * Valid if initialProcessorsToEliminate returns true or this analysis was initialized with
112 * a known color via constructor or init(). If color fragment processors are eliminated then
113 * this returns the expected input to the first non-eliminated processors. Otherwise it is
114 * the color passed to the constructor or init().
115 */
116 GrColor inputColor() const {
117 SkASSERT(fValidInputColor);
118 return fInputColor;
119 }
120
Brian Salomonbfafcba2017-03-02 08:49:19 -0500121 bool usesLocalCoords() const { return fUsesLocalCoords; }
Brian Salomon5298dc82017-02-22 11:52:03 -0500122 bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
123 bool isOutputColorOpaque() const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400124 return ColorType::kOpaque == this->outputColorType() ||
125 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500126 }
127 bool hasKnownOutputColor(GrColor* color = nullptr) const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400128 bool constant = ColorType::kConstant == this->outputColorType() ||
129 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500130 if (constant && color) {
131 *color = fKnownOutputColor;
132 }
133 return constant;
134 }
Brian Salomonc0b642c2017-03-27 13:09:36 -0400135 GrPipelineAnalysisCoverage outputCoverageType() const {
136 return static_cast<GrPipelineAnalysisCoverage>(fOutputCoverageType);
137 }
138 bool hasCoverage() const {
139 return this->outputCoverageType() != GrPipelineAnalysisCoverage::kNone;
140 }
Brian Salomon5298dc82017-02-22 11:52:03 -0500141
142 private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400143 enum class ColorType : unsigned { kUnknown, kOpaqueConstant, kConstant, kOpaque };
Brian Salomon5298dc82017-02-22 11:52:03 -0500144
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400145 ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500146
Brian Salomonc0b642c2017-03-27 13:09:36 -0400147 void internalInit(const GrPipelineAnalysisColor&, const GrPipelineAnalysisCoverage,
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400148 const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
149
150 // MSVS 2015 won't pack a bool with an unsigned.
151 using PackedBool = unsigned;
152
153 PackedBool fIsInitializedWithProcessorSet : 1;
154 PackedBool fUsesLocalCoords : 1;
155 PackedBool fCompatibleWithCoverageAsAlpha : 1;
156 PackedBool fValidInputColor : 1;
157 unsigned fOutputCoverageType : 2;
158 unsigned fOutputColorType : 2;
159 unsigned fInitialColorProcessorsToEliminate : 32 - 8;
160
161 GrColor fInputColor;
Brian Salomon5298dc82017-02-22 11:52:03 -0500162 GrColor fKnownOutputColor;
Brian Salomon70288c02017-03-24 12:27:17 -0400163
164 friend class GrProcessorSet;
Brian Salomon5298dc82017-02-22 11:52:03 -0500165 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400166 GR_STATIC_ASSERT(sizeof(FragmentProcessorAnalysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
Brian Salomon5298dc82017-02-22 11:52:03 -0500167
Brian Salomon70288c02017-03-24 12:27:17 -0400168 void analyzeAndEliminateFragmentProcessors(FragmentProcessorAnalysis*,
Brian Salomonc0b642c2017-03-27 13:09:36 -0400169 const GrPipelineAnalysisColor& colorInput,
170 const GrPipelineAnalysisCoverage coverageInput,
Brian Salomon70288c02017-03-24 12:27:17 -0400171 const GrAppliedClip*, const GrCaps&);
172
Brian Salomon92ce5942017-01-18 11:01:10 -0500173private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400174 // This absurdly large limit allows FragmentProcessorAnalysis and this to pack fields together.
Brian Salomon70288c02017-03-24 12:27:17 -0400175 static constexpr int kMaxColorProcessors = UINT8_MAX;
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400176
177 enum Flags : uint16_t {
Brian Salomonf87e2b92017-01-19 11:31:50 -0500178 kUseDistanceVectorField_Flag = 0x1,
179 kDisableOutputConversionToSRGB_Flag = 0x2,
Brian Salomon54d212e2017-03-21 14:22:38 -0400180 kAllowSRGBInputs_Flag = 0x4,
181 kPendingExecution_Flag = 0x8
Brian Salomonf87e2b92017-01-19 11:31:50 -0500182 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400183
184 const GrXPFactory* fXPFactory = nullptr;
185 SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
Brian Salomon70288c02017-03-24 12:27:17 -0400186 uint8_t fColorFragmentProcessorCnt;
187 uint8_t fFragmentProcessorOffset = 0;
188 uint8_t fFlags;
Brian Salomon92ce5942017-01-18 11:01:10 -0500189};
190
191#endif