blob: 39ba0137b8142b75ea4542a307e79554b8ed04cf [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 Salomona811b122017-03-30 08:21:32 -040013#include "GrProcessorAnalysis.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 /**
Brian Salomona811b122017-03-30 08:21:32 -040061 * This is used to track analysis of color and coverage values through the processors.
Brian Salomon5298dc82017-02-22 11:52:03 -050062 */
Brian Salomona811b122017-03-30 08:21:32 -040063 class Analysis {
Brian Salomon5298dc82017-02-22 11:52:03 -050064 public:
Brian Salomon8d2f90b2017-03-13 09:11:58 -040065 /**
Brian Salomona811b122017-03-30 08:21:32 -040066 * This constructor allows an op to record its initial color in an Analysis member and then
67 * then run analysis later when the analysis inputs are available. If the analysis produces
68 * color fragment processor elimination then the input color is replaced by the expected
69 * input to the first non-eliminated processor. Otherwise, the original input color is
70 * preserved. The only reason to use this is to save space on the op by not separately
71 * storing the initial color.
Brian Salomon8d2f90b2017-03-13 09:11:58 -040072 */
Brian Salomona811b122017-03-30 08:21:32 -040073 explicit Analysis(GrColor initialColor) : Analysis() {
Brian Salomon8d2f90b2017-03-13 09:11:58 -040074 fInputColor = initialColor;
75 fValidInputColor = true;
76 }
77
Brian Salomona811b122017-03-30 08:21:32 -040078 Analysis()
Brian Salomon8d2f90b2017-03-13 09:11:58 -040079 : fIsInitializedWithProcessorSet(false)
80 , fCompatibleWithCoverageAsAlpha(true)
81 , fValidInputColor(false)
Brian Salomon31853842017-03-28 16:32:05 -040082 , fRequiresDstTexture(false)
83 , fCanCombineOverlappedStencilAndCover(true)
84 , fIgnoresInputColor(false)
Brian Salomon4fc77402017-03-30 16:48:26 -040085 , fRequiresBarrierBetweenOverlappingDraws(false)
Brian Salomona811b122017-03-30 08:21:32 -040086 , fOutputCoverageType(static_cast<unsigned>(GrProcessorAnalysisCoverage::kNone))
Brian Salomon8d2f90b2017-03-13 09:11:58 -040087 , fOutputColorType(static_cast<unsigned>(ColorType::kUnknown))
88 , fInitialColorProcessorsToEliminate(0) {}
89
Brian Salomon31853842017-03-28 16:32:05 -040090 // This version is used by a unit test that assumes no clip and no fragment processors.
Brian Salomona811b122017-03-30 08:21:32 -040091 Analysis(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage, const GrXPFactory*,
92 const GrCaps&);
Brian Salomon5298dc82017-02-22 11:52:03 -050093
Brian Salomona811b122017-03-30 08:21:32 -040094 void init(const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage,
95 const GrProcessorSet&, const GrAppliedClip*, const GrCaps&);
Brian Salomon8d2f90b2017-03-13 09:11:58 -040096
97 bool isInitializedWithProcessorSet() const { return fIsInitializedWithProcessorSet; }
Brian Salomon5298dc82017-02-22 11:52:03 -050098
Brian Salomon70288c02017-03-24 12:27:17 -040099 /**
100 * If the return is greater than or equal to zero then 'newInputColor' should be used as the
101 * input color to the GrPipeline derived from this processor set, replacing the GrDrawOp's
102 * initial color. If the return is less than zero then newInputColor has not been
103 * modified and no modification need be made to the pipeline's input color by the op.
104 */
105 int getInputColorOverrideAndColorProcessorEliminationCount(GrColor* newInputColor) const {
106 if (fValidInputColor) {
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400107 *newInputColor = fInputColor;
Brian Salomon70288c02017-03-24 12:27:17 -0400108 return fInitialColorProcessorsToEliminate;
Brian Salomon5298dc82017-02-22 11:52:03 -0500109 }
Brian Salomon70288c02017-03-24 12:27:17 -0400110 SkASSERT(!fInitialColorProcessorsToEliminate);
111 return -1;
Brian Salomon5298dc82017-02-22 11:52:03 -0500112 }
113
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400114 /**
115 * Valid if initialProcessorsToEliminate returns true or this analysis was initialized with
116 * a known color via constructor or init(). If color fragment processors are eliminated then
117 * this returns the expected input to the first non-eliminated processors. Otherwise it is
118 * the color passed to the constructor or init().
119 */
120 GrColor inputColor() const {
121 SkASSERT(fValidInputColor);
122 return fInputColor;
123 }
124
Brian Salomonbfafcba2017-03-02 08:49:19 -0500125 bool usesLocalCoords() const { return fUsesLocalCoords; }
Brian Salomon31853842017-03-28 16:32:05 -0400126 bool requiresDstTexture() const { return fRequiresDstTexture; }
127 bool canCombineOverlappedStencilAndCover() const {
128 return fCanCombineOverlappedStencilAndCover;
129 }
Brian Salomon4fc77402017-03-30 16:48:26 -0400130 bool requiresBarrierBetweenOverlappingDraws() const {
131 return fRequiresBarrierBetweenOverlappingDraws;
132 }
Brian Salomon5298dc82017-02-22 11:52:03 -0500133 bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
Brian Salomon31853842017-03-28 16:32:05 -0400134 bool isInputColorIgnored() const { return fIgnoresInputColor; }
Brian Salomona811b122017-03-30 08:21:32 -0400135 GrProcessorAnalysisCoverage outputCoverage() const {
136 return static_cast<GrProcessorAnalysisCoverage>(fOutputCoverageType);
Brian Salomonc0b642c2017-03-27 13:09:36 -0400137 }
Brian Salomona811b122017-03-30 08:21:32 -0400138 GrProcessorAnalysisColor outputColor() const {
Brian Salomon1c6025c2017-03-29 14:25:04 -0400139 switch (this->outputColorType()) {
140 case ColorType::kConstant:
141 return fKnownOutputColor;
142 case ColorType::kOpaque:
Brian Salomona811b122017-03-30 08:21:32 -0400143 return GrProcessorAnalysisColor::Opaque::kYes;
Brian Salomon1c6025c2017-03-29 14:25:04 -0400144 case ColorType::kUnknown:
Brian Salomona811b122017-03-30 08:21:32 -0400145 return GrProcessorAnalysisColor::Opaque::kNo;
Brian Salomon1c6025c2017-03-29 14:25:04 -0400146 }
147 SkFAIL("Unexpected color type");
Brian Salomona811b122017-03-30 08:21:32 -0400148 return GrProcessorAnalysisColor::Opaque::kNo;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400149 }
Brian Salomon5298dc82017-02-22 11:52:03 -0500150
151 private:
Brian Salomon1c6025c2017-03-29 14:25:04 -0400152 enum class ColorType : unsigned { kUnknown, kConstant, kOpaque };
Brian Salomon5298dc82017-02-22 11:52:03 -0500153
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400154 ColorType outputColorType() const { return static_cast<ColorType>(fOutputColorType); }
Brian Salomon5298dc82017-02-22 11:52:03 -0500155
Brian Salomona811b122017-03-30 08:21:32 -0400156 void internalInit(const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage,
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400157 const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
158
159 // MSVS 2015 won't pack a bool with an unsigned.
160 using PackedBool = unsigned;
161
162 PackedBool fIsInitializedWithProcessorSet : 1;
163 PackedBool fUsesLocalCoords : 1;
164 PackedBool fCompatibleWithCoverageAsAlpha : 1;
165 PackedBool fValidInputColor : 1;
Brian Salomon31853842017-03-28 16:32:05 -0400166 PackedBool fRequiresDstTexture : 1;
167 PackedBool fCanCombineOverlappedStencilAndCover : 1;
168 // These could be removed if we created the XP from the XPFactory when doing analysis.
169 PackedBool fIgnoresInputColor : 1;
Brian Salomon4fc77402017-03-30 16:48:26 -0400170 PackedBool fRequiresBarrierBetweenOverlappingDraws : 1;
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400171 unsigned fOutputCoverageType : 2;
172 unsigned fOutputColorType : 2;
Brian Salomon31853842017-03-28 16:32:05 -0400173
Brian Salomon4fc77402017-03-30 16:48:26 -0400174 unsigned fInitialColorProcessorsToEliminate : 32 - 12;
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400175
176 GrColor fInputColor;
Brian Salomon31853842017-03-28 16:32:05 -0400177 // This could be removed if we created the XP from the XPFactory when doing analysis.
Brian Salomon5298dc82017-02-22 11:52:03 -0500178 GrColor fKnownOutputColor;
Brian Salomon70288c02017-03-24 12:27:17 -0400179
180 friend class GrProcessorSet;
Brian Salomon5298dc82017-02-22 11:52:03 -0500181 };
Brian Salomona811b122017-03-30 08:21:32 -0400182 GR_STATIC_ASSERT(sizeof(Analysis) == 2 * sizeof(GrColor) + sizeof(uint32_t));
Brian Salomon5298dc82017-02-22 11:52:03 -0500183
Brian Salomona811b122017-03-30 08:21:32 -0400184 void analyzeAndEliminateFragmentProcessors(Analysis*,
185 const GrProcessorAnalysisColor& colorInput,
186 const GrProcessorAnalysisCoverage coverageInput,
Brian Salomon70288c02017-03-24 12:27:17 -0400187 const GrAppliedClip*, const GrCaps&);
188
Brian Salomon92ce5942017-01-18 11:01:10 -0500189private:
Brian Salomona811b122017-03-30 08:21:32 -0400190 // This absurdly large limit allows Analysis and this to pack fields together.
Brian Salomon70288c02017-03-24 12:27:17 -0400191 static constexpr int kMaxColorProcessors = UINT8_MAX;
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400192
193 enum Flags : uint16_t {
Brian Salomonf87e2b92017-01-19 11:31:50 -0500194 kUseDistanceVectorField_Flag = 0x1,
195 kDisableOutputConversionToSRGB_Flag = 0x2,
Brian Salomon54d212e2017-03-21 14:22:38 -0400196 kAllowSRGBInputs_Flag = 0x4,
197 kPendingExecution_Flag = 0x8
Brian Salomonf87e2b92017-01-19 11:31:50 -0500198 };
Brian Salomon8d2f90b2017-03-13 09:11:58 -0400199
200 const GrXPFactory* fXPFactory = nullptr;
201 SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
Brian Salomon70288c02017-03-24 12:27:17 -0400202 uint8_t fColorFragmentProcessorCnt;
203 uint8_t fFragmentProcessorOffset = 0;
204 uint8_t fFlags;
Brian Salomon92ce5942017-01-18 11:01:10 -0500205};
206
207#endif