blob: 8203491435e4b49102cf63292511fb8a4b4461bb [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
23 ~GrProcessorSet() {
24 // We are deliberately not using sk_sp here because this will be updated to work with
25 // "pending execution" refs.
26 for (auto fp : fFragmentProcessors) {
27 fp->unref();
28 }
29 }
30
31 int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
32 int numCoverageFragmentProcessors() const {
33 return fFragmentProcessors.count() - fColorFragmentProcessorCnt;
34 }
35 int numFragmentProcessors() const { return fFragmentProcessors.count(); }
36
37 const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
38 SkASSERT(idx < fColorFragmentProcessorCnt);
39 return fFragmentProcessors[idx];
40 }
41 const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
42 return fFragmentProcessors[idx + fColorFragmentProcessorCnt];
43 }
44
45 const GrXPFactory* xpFactory() const { return fXPFactory; }
46
Brian Salomonf87e2b92017-01-19 11:31:50 -050047 bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
48 bool disableOutputConversionToSRGB() const {
49 return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
50 }
51 bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
Brian Salomon189098e72017-01-19 09:55:19 -050052
Brian Salomon5298dc82017-02-22 11:52:03 -050053 /**
54 * This is used to track analysis of color and coverage values through the fragment processors.
55 */
56 class FragmentProcessorAnalysis {
57 public:
Brian Salomon8d2f90b2017-03-13 09:11:58 -040058 /**
59 * This constructor allows an op to record its initial color in a FragmentProcessorAnalysis
60 * member and then run analysis later when the analysis inputs are available. If the
61 * analysis produces color fragment processor elimination then the input color is replaced
62 * by the expected input to the first non-eliminated processor. Otherwise, the original
63 * input color is preserved. The only reason to use this is to save space on the op by not
64 * separately storing the initial color.
65 */
66 explicit FragmentProcessorAnalysis(GrColor initialColor) : FragmentProcessorAnalysis() {
67 fInputColor = initialColor;
68 fValidInputColor = true;
69 }
70
71 FragmentProcessorAnalysis()
72 : fIsInitializedWithProcessorSet(false)
73 , fCompatibleWithCoverageAsAlpha(true)
74 , fValidInputColor(false)
75 , fOutputCoverageType(static_cast<unsigned>(CoverageType::kNone))
76 , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
77 , fInitialColorProcessorsToEliminate(0) {}
78
79 // This version is used by a unit test that assumes no clip, no processors, and no PLS.
Brian Salomon5298dc82017-02-22 11:52:03 -050080 FragmentProcessorAnalysis(const GrPipelineInput& colorInput,
81 const GrPipelineInput coverageInput, const GrCaps&);
82
Brian Salomon8d2f90b2017-03-13 09:11:58 -040083 void init(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
84 const GrProcessorSet&, const GrAppliedClip*, const GrCaps&);
85
86 bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
Brian Salomon5298dc82017-02-22 11:52:03 -050087
88 int initialColorProcessorsToEliminate(GrColor* newInputColor) const {
89 if (fInitialColorProcessorsToEliminate > 0) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -040090 SkASSERT(fValidInputColor);
91 *newInputColor = fInputColor;
Brian Salomon5298dc82017-02-22 11:52:03 -050092 }
93 return fInitialColorProcessorsToEliminate;
94 }
95
Brian Salomon8d2f90b2017-03-13 09:11:58 -040096 /**
97 * Valid if initialProcessorsToEliminate returns true or this analysis was initialized with
98 * a known color via constructor or init(). If color fragment processors are eliminated then
99 * this returns the expected input to the first non-eliminated processors. Otherwise it is
100 * the color passed to the constructor or init().
101 */
102 GrColor inputColor() const {
103 SkASSERT(fValidInputColor);
104 return fInputColor;
105 }
106
Brian Salomonbfafcba2017-03-02 08:49:19 -0500107 bool usesLocalCoords() const { return fUsesLocalCoords; }
Brian Salomon5298dc82017-02-22 11:52:03 -0500108 bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
109 bool isOutputColorOpaque() const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400110 return ColorType::kOpaque == this->outputColorType() ||
111 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500112 }
113 bool hasKnownOutputColor(GrColor* color = nullptr) const {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400114 bool constant = ColorType::kConstant == this->outputColorType() ||
115 ColorType::kOpaqueConstant == this->outputColorType();
Brian Salomon5298dc82017-02-22 11:52:03 -0500116 if (constant && color) {
117 *color = fKnownOutputColor;
118 }
119 return constant;
120 }
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400121 bool hasCoverage() const { return CoverageType::kNone != this->outputCoverageType(); }
122 bool hasLCDCoverage() const { return CoverageType::kLCD == this->outputCoverageType(); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500123
124 private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400125 enum class ColorType : unsigned { kUnknown, kOpaqueConstant, kConstant, kOpaque };
126 enum class CoverageType : unsigned { kNone, kSingleChannel, kLCD };
Brian Salomon5298dc82017-02-22 11:52:03 -0500127
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400128 CoverageType outputCoverageType() const {
129 return static_cast<CoverageType>(fOutputCoverageType);
130 }
131 ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500132
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400133 void internalInit(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
134 const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
135
136 // MSVS 2015 won't pack a bool with an unsigned.
137 using PackedBool = unsigned;
138
139 PackedBool fIsInitializedWithProcessorSet : 1;
140 PackedBool fUsesLocalCoords : 1;
141 PackedBool fCompatibleWithCoverageAsAlpha : 1;
142 PackedBool fValidInputColor : 1;
143 unsigned fOutputCoverageType : 2;
144 unsigned fOutputColorType : 2;
145 unsigned fInitialColorProcessorsToEliminate : 32 - 8;
146
147 GrColor fInputColor;
Brian Salomon5298dc82017-02-22 11:52:03 -0500148 GrColor fKnownOutputColor;
149 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400150 GR_STATIC_ASSERT(sizeof(FragmentProcessorAnalysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
Brian Salomon5298dc82017-02-22 11:52:03 -0500151
Brian Salomon92ce5942017-01-18 11:01:10 -0500152private:
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400153 // This absurdly large limit allows FragmentProcessorAnalysis and this to pack fields together.
154 static constexpr int kMaxColorProcessors = SK_MaxU16;
155
156 enum Flags : uint16_t {
Brian Salomonf87e2b92017-01-19 11:31:50 -0500157 kUseDistanceVectorField_Flag = 0x1,
158 kDisableOutputConversionToSRGB_Flag = 0x2,
159 kAllowSRGBInputs_Flag = 0x4
160 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400161
162 const GrXPFactory* fXPFactory = nullptr;
163 SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
164 uint16_t fColorFragmentProcessorCnt;
165 uint16_t fFlags;
Brian Salomon92ce5942017-01-18 11:01:10 -0500166};
167
168#endif