blob: 18a52fd9b7eaae83864493075d54ef0218e764d3 [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 Salomon5298dc82017-02-22 11:52:03 -050013#include "GrPipelineInput.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 {
35 return fFragmentProcessors.count() - fColorFragmentProcessorCnt;
36 }
37 int numFragmentProcessors() const { return fFragmentProcessors.count(); }
38
39 const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
40 SkASSERT(idx < fColorFragmentProcessorCnt);
41 return fFragmentProcessors[idx];
42 }
43 const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
44 return fFragmentProcessors[idx + fColorFragmentProcessorCnt];
45 }
46
47 const GrXPFactory* xpFactory() const { return fXPFactory; }
48
Brian Salomonf87e2b92017-01-19 11:31:50 -050049 bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
50 bool disableOutputConversionToSRGB() const {
51 return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
52 }
53 bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
Brian Salomon189098e72017-01-19 09:55:19 -050054
Brian Salomon54d212e2017-03-21 14:22:38 -040055 bool operator==(const GrProcessorSet& that) const;
56 bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
57
Brian Salomon5298dc82017-02-22 11:52:03 -050058 /**
59 * This is used to track analysis of color and coverage values through the fragment processors.
60 */
61 class FragmentProcessorAnalysis {
62 public:
Brian Salomon8d2f90b2017-03-13 09:11:58 -040063 /**
64 * This constructor allows an op to record its initial color in a FragmentProcessorAnalysis
65 * member and then run analysis later when the analysis inputs are available. If the
66 * analysis produces color fragment processor elimination then the input color is replaced
67 * by the expected input to the first non-eliminated processor. Otherwise, the original
68 * input color is preserved. The only reason to use this is to save space on the op by not
69 * separately storing the initial color.
70 */
71 explicit FragmentProcessorAnalysis(GrColor initialColor) : FragmentProcessorAnalysis() {
72 fInputColor = initialColor;
73 fValidInputColor = true;
74 }
75
76 FragmentProcessorAnalysis()
77 : fIsInitializedWithProcessorSet(false)
78 , fCompatibleWithCoverageAsAlpha(true)
79 , fValidInputColor(false)
80 , fOutputCoverageType(static_cast<unsigned>(CoverageType::kNone))
81 , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
82 , fInitialColorProcessorsToEliminate(0) {}
83
84 // This version is used by a unit test that assumes no clip, no processors, and no PLS.
Brian Salomon5298dc82017-02-22 11:52:03 -050085 FragmentProcessorAnalysis(const GrPipelineInput& colorInput,
86 const GrPipelineInput coverageInput, const GrCaps&);
87
Brian Salomon8d2f90b2017-03-13 09:11:58 -040088 void init(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
89 const GrProcessorSet&, const GrAppliedClip*, const GrCaps&);
90
91 bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
Brian Salomon5298dc82017-02-22 11:52:03 -050092
93 int initialColorProcessorsToEliminate(GrColor* newInputColor) const {
94 if (fInitialColorProcessorsToEliminate > 0) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -040095 SkASSERT(fValidInputColor);
96 *newInputColor = fInputColor;
Brian Salomon5298dc82017-02-22 11:52:03 -050097 }
98 return fInitialColorProcessorsToEliminate;
99 }
100
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400101 /**
102 * Valid if initialProcessorsToEliminate returns true or this analysis was initialized with
103 * a known color via constructor or init(). If color fragment processors are eliminated then
104 * this returns the expected input to the first non-eliminated processors. Otherwise it is
105 * the color passed to the constructor or init().
106 */
107 GrColor inputColor() const {
108 SkASSERT(fValidInputColor);
109 return fInputColor;
110 }
111
Brian Salomonbfafcba2017-03-02 08:49:19 -0500112 bool usesLocalCoords() const { return fUsesLocalCoords; }
Brian Salomon5298dc82017-02-22 11:52:03 -0500113 bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
114 bool isOutputColorOpaque() const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400115 return ColorType::kOpaque == this->outputColorType() ||
116 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500117 }
118 bool hasKnownOutputColor(GrColor* color = nullptr) const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400119 bool constant = ColorType::kConstant == this->outputColorType() ||
120 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500121 if (constant && color) {
122 *color = fKnownOutputColor;
123 }
124 return constant;
125 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400126 bool hasCoverage() const { return CoverageType::kNone != this->outputCoverageType(); }
127 bool hasLCDCoverage() const { return CoverageType::kLCD == this->outputCoverageType(); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500128
129 private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400130 enum class ColorType : unsigned { kUnknown, kOpaqueConstant, kConstant, kOpaque };
131 enum class CoverageType : unsigned { kNone, kSingleChannel, kLCD };
Brian Salomon5298dc82017-02-22 11:52:03 -0500132
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400133 CoverageType outputCoverageType() const {
134 return static_cast<CoverageType>(fOutputCoverageType);
135 }
136 ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500137
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400138 void internalInit(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
139 const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
140
141 // MSVS 2015 won't pack a bool with an unsigned.
142 using PackedBool = unsigned;
143
144 PackedBool fIsInitializedWithProcessorSet : 1;
145 PackedBool fUsesLocalCoords : 1;
146 PackedBool fCompatibleWithCoverageAsAlpha : 1;
147 PackedBool fValidInputColor : 1;
148 unsigned fOutputCoverageType : 2;
149 unsigned fOutputColorType : 2;
150 unsigned fInitialColorProcessorsToEliminate : 32 - 8;
151
152 GrColor fInputColor;
Brian Salomon5298dc82017-02-22 11:52:03 -0500153 GrColor fKnownOutputColor;
154 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400155 GR_STATIC_ASSERT(sizeof(FragmentProcessorAnalysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
Brian Salomon5298dc82017-02-22 11:52:03 -0500156
Brian Salomon92ce5942017-01-18 11:01:10 -0500157private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400158 // This absurdly large limit allows FragmentProcessorAnalysis and this to pack fields together.
159 static constexpr int kMaxColorProcessors = SK_MaxU16;
160
161 enum Flags : uint16_t {
Brian Salomonf87e2b92017-01-19 11:31:50 -0500162 kUseDistanceVectorField_Flag = 0x1,
163 kDisableOutputConversionToSRGB_Flag = 0x2,
Brian Salomon54d212e2017-03-21 14:22:38 -0400164 kAllowSRGBInputs_Flag = 0x4,
165 kPendingExecution_Flag = 0x8
Brian Salomonf87e2b92017-01-19 11:31:50 -0500166 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400167
168 const GrXPFactory* fXPFactory = nullptr;
169 SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
170 uint16_t fColorFragmentProcessorCnt;
171 uint16_t fFlags;
Brian Salomon92ce5942017-01-18 11:01:10 -0500172};
173
174#endif