blob: a829db445ab7544bc25f69e127cba84c9b0b1ea0 [file] [log] [blame]
Brian Salomonc0b642c2017-03-27 13:09:36 -04001/*
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
Brian Salomona811b122017-03-30 08:21:32 -04008#ifndef GrProcessorAnalysis_DEFINED
9#define GrProcessorAnalysis_DEFINED
Brian Salomonc0b642c2017-03-27 13:09:36 -040010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/SkColorData.h"
Brian Salomonc0b642c2017-03-27 13:09:36 -040012
13class GrDrawOp;
14class GrFragmentProcessor;
Brian Salomonc0b642c2017-03-27 13:09:36 -040015
Brian Salomona811b122017-03-30 08:21:32 -040016class GrProcessorAnalysisColor {
Brian Salomonc0b642c2017-03-27 13:09:36 -040017public:
18 enum class Opaque {
19 kNo,
20 kYes,
21 };
22
Brian Salomon82ddc942017-07-14 12:00:13 -040023 constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo)
Brian Osman1be2b7c2018-10-29 16:07:15 -040024 : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0)
Brian Osmancf860852018-10-31 14:04:39 -040025 , fColor(SK_PMColor4fTRANSPARENT) {}
Brian Salomonc0b642c2017-03-27 13:09:36 -040026
Brian Osmancf860852018-10-31 14:04:39 -040027 GrProcessorAnalysisColor(const SkPMColor4f& color) { this->setToConstant(color); }
Brian Salomonc0b642c2017-03-27 13:09:36 -040028
Brian Osmancf860852018-10-31 14:04:39 -040029 void setToConstant(const SkPMColor4f& color) {
Brian Salomonc0b642c2017-03-27 13:09:36 -040030 fColor = color;
Brian Osman1be2b7c2018-10-29 16:07:15 -040031 if (color.isOpaque()) {
Brian Salomonc0b642c2017-03-27 13:09:36 -040032 fFlags = kColorIsKnown_Flag | kIsOpaque_Flag;
33 } else {
34 fFlags = kColorIsKnown_Flag;
35 }
36 }
37
38 void setToUnknown() { fFlags = 0; }
39
40 void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; }
41
Michael Ludwigca91e1f2018-12-10 10:44:44 -050042 bool isUnknown() const { return SkToBool(fFlags == 0); }
43
Brian Salomonc0b642c2017-03-27 13:09:36 -040044 bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
45
Brian Osmancf860852018-10-31 14:04:39 -040046 bool isConstant(SkPMColor4f* color = nullptr) const {
Brian Salomonc0b642c2017-03-27 13:09:36 -040047 if (kColorIsKnown_Flag & fFlags) {
Brian Salomon31853842017-03-28 16:32:05 -040048 if (color) {
49 *color = fColor;
50 }
Brian Salomonc0b642c2017-03-27 13:09:36 -040051 return true;
52 }
53 return false;
54 }
55
Brian Salomona811b122017-03-30 08:21:32 -040056 bool operator==(const GrProcessorAnalysisColor& that) const {
Brian Salomon1c6025c2017-03-29 14:25:04 -040057 if (fFlags != that.fFlags) {
58 return false;
59 }
60 return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
61 }
62
Brian Salomon13071c52017-03-29 21:28:20 -040063 /** The returned value reflects the common properties of the two inputs. */
Brian Salomona811b122017-03-30 08:21:32 -040064 static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a,
65 const GrProcessorAnalysisColor& b) {
66 GrProcessorAnalysisColor result;
Brian Salomon13071c52017-03-29 21:28:20 -040067 uint32_t commonFlags = a.fFlags & b.fFlags;
68 if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) {
69 result.fColor = a.fColor;
70 result.fFlags = a.fFlags;
71 } else if (kIsOpaque_Flag & commonFlags) {
72 result.fFlags = kIsOpaque_Flag;
73 }
74 return result;
75 }
76
Brian Salomonc0b642c2017-03-27 13:09:36 -040077private:
78 enum Flags {
79 kColorIsKnown_Flag = 0x1,
80 kIsOpaque_Flag = 0x2,
81 };
82 uint32_t fFlags;
Brian Osmancf860852018-10-31 14:04:39 -040083 SkPMColor4f fColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -040084};
85
Brian Salomona811b122017-03-30 08:21:32 -040086enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD };
Brian Salomonc0b642c2017-03-27 13:09:36 -040087
88/**
John Stiles29d3e222020-07-21 17:28:12 -040089 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processors.
Brian Salomonc0b642c2017-03-27 13:09:36 -040090 * It is used to recognize optimizations that can simplify the generated shader or make blending
91 * more effecient.
92 */
93class GrColorFragmentProcessorAnalysis {
94public:
Brian Salomon650ced02017-07-20 16:46:46 -040095 GrColorFragmentProcessorAnalysis() = delete;
Brian Salomonc0b642c2017-03-27 13:09:36 -040096
Brian Salomon650ced02017-07-20 16:46:46 -040097 GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input,
Brian Salomon64f42062020-02-14 10:42:45 -050098 std::unique_ptr<GrFragmentProcessor> const fps[],
John Stiles053eb1b2021-06-03 12:19:39 -040099 int count);
Brian Salomonc0b642c2017-03-27 13:09:36 -0400100
101 bool isOpaque() const { return fIsOpaque; }
102
103 /**
104 * Are all the fragment processors compatible with conflating coverage with color prior to the
Brian Salomon28207df2017-06-05 12:25:13 -0400105 * the first fragment processor. This result assumes that processors that should be eliminated
106 * as indicated by initialProcessorsToEliminate() are in fact eliminated.
Brian Salomonc0b642c2017-03-27 13:09:36 -0400107 */
108 bool allProcessorsCompatibleWithCoverageAsAlpha() const {
Brian Salomon650ced02017-07-20 16:46:46 -0400109 return fCompatibleWithCoverageAsAlpha;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400110 }
111
112 /**
Brian Salomon28207df2017-06-05 12:25:13 -0400113 * Do any of the fragment processors require local coords. This result assumes that
114 * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in
115 * fact eliminated.
Brian Salomonc0b642c2017-03-27 13:09:36 -0400116 */
117 bool usesLocalCoords() const { return fUsesLocalCoords; }
118
119 /**
John Stilese69f25f2021-06-03 12:23:33 -0400120 * Do any of the fragment processors read back the destination color?
121 */
122 bool willReadDstColor() const { return fWillReadDstColor; }
123
124 /**
125 * Will we require a destination-surface texture?
126 */
127 bool requiresDstTexture(const GrCaps& caps) const;
128
129 /**
Brian Salomonc0b642c2017-03-27 13:09:36 -0400130 * If we detected that the result after the first N processors is a known color then we
131 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with
132 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if
133 * there are only N processors) sees its expected input. If this returns 0 then there are no
134 * processors to eliminate.
135 */
Brian Osman1be2b7c2018-10-29 16:07:15 -0400136 int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const {
Brian Salomon650ced02017-07-20 16:46:46 -0400137 if (fProcessorsToEliminate > 0) {
Brian Osman1be2b7c2018-10-29 16:07:15 -0400138 *newPipelineInputColor = fLastKnownOutputColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400139 }
Brian Salomon650ced02017-07-20 16:46:46 -0400140 return fProcessorsToEliminate;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400141 }
142
Brian Salomon650ced02017-07-20 16:46:46 -0400143 /**
144 * Provides known information about the last processor's output color.
145 */
Brian Salomona811b122017-03-30 08:21:32 -0400146 GrProcessorAnalysisColor outputColor() const {
John Stiles053eb1b2021-06-03 12:19:39 -0400147 if (fOutputColorKnown) {
Brian Osmancf860852018-10-31 14:04:39 -0400148 return fLastKnownOutputColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400149 }
Brian Salomon650ced02017-07-20 16:46:46 -0400150 return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes
151 : GrProcessorAnalysisColor::Opaque::kNo;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400152 }
153
154private:
Brian Salomon650ced02017-07-20 16:46:46 -0400155 bool fIsOpaque;
156 bool fCompatibleWithCoverageAsAlpha;
157 bool fUsesLocalCoords;
John Stilese69f25f2021-06-03 12:23:33 -0400158 bool fWillReadDstColor;
John Stiles053eb1b2021-06-03 12:19:39 -0400159 bool fOutputColorKnown;
Brian Salomon650ced02017-07-20 16:46:46 -0400160 int fProcessorsToEliminate;
Brian Osman1d5b5982018-10-01 13:41:39 -0400161 SkPMColor4f fLastKnownOutputColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400162};
163
164#endif