blob: 6767941d671e208f9f372f655bacaaff6d2a3825 [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
11#include "GrColor.h"
Brian Osman1d5b5982018-10-01 13:41:39 -040012#include "SkPM4f.h"
Brian Salomonc0b642c2017-03-27 13:09:36 -040013
14class GrDrawOp;
15class GrFragmentProcessor;
16class GrPrimitiveProcessor;
17
Brian Salomona811b122017-03-30 08:21:32 -040018class GrProcessorAnalysisColor {
Brian Salomonc0b642c2017-03-27 13:09:36 -040019public:
20 enum class Opaque {
21 kNo,
22 kYes,
23 };
24
Brian Salomon82ddc942017-07-14 12:00:13 -040025 constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo)
26 : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0), fColor(0) {}
Brian Salomonc0b642c2017-03-27 13:09:36 -040027
Brian Salomona811b122017-03-30 08:21:32 -040028 GrProcessorAnalysisColor(GrColor color) { this->setToConstant(color); }
Brian Salomonc0b642c2017-03-27 13:09:36 -040029
30 void setToConstant(GrColor color) {
31 fColor = color;
32 if (GrColorIsOpaque(color)) {
33 fFlags = kColorIsKnown_Flag | kIsOpaque_Flag;
34 } else {
35 fFlags = kColorIsKnown_Flag;
36 }
37 }
38
39 void setToUnknown() { fFlags = 0; }
40
41 void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; }
42
43 bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
44
Brian Salomon31853842017-03-28 16:32:05 -040045 bool isConstant(GrColor* color = nullptr) const {
Brian Salomonc0b642c2017-03-27 13:09:36 -040046 if (kColorIsKnown_Flag & fFlags) {
Brian Salomon31853842017-03-28 16:32:05 -040047 if (color) {
48 *color = fColor;
49 }
Brian Salomonc0b642c2017-03-27 13:09:36 -040050 return true;
51 }
52 return false;
53 }
54
Brian Salomona811b122017-03-30 08:21:32 -040055 bool operator==(const GrProcessorAnalysisColor& that) const {
Brian Salomon1c6025c2017-03-29 14:25:04 -040056 if (fFlags != that.fFlags) {
57 return false;
58 }
59 return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true;
60 }
61
Brian Salomon13071c52017-03-29 21:28:20 -040062 /** The returned value reflects the common properties of the two inputs. */
Brian Salomona811b122017-03-30 08:21:32 -040063 static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a,
64 const GrProcessorAnalysisColor& b) {
65 GrProcessorAnalysisColor result;
Brian Salomon13071c52017-03-29 21:28:20 -040066 uint32_t commonFlags = a.fFlags & b.fFlags;
67 if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) {
68 result.fColor = a.fColor;
69 result.fFlags = a.fFlags;
70 } else if (kIsOpaque_Flag & commonFlags) {
71 result.fFlags = kIsOpaque_Flag;
72 }
73 return result;
74 }
75
Brian Salomonc0b642c2017-03-27 13:09:36 -040076private:
77 enum Flags {
78 kColorIsKnown_Flag = 0x1,
79 kIsOpaque_Flag = 0x2,
80 };
81 uint32_t fFlags;
82 GrColor fColor;
83};
84
Brian Salomona811b122017-03-30 08:21:32 -040085enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD };
Brian Salomonc0b642c2017-03-27 13:09:36 -040086
87/**
88 * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processor.
89 * It is used to recognize optimizations that can simplify the generated shader or make blending
90 * more effecient.
91 */
92class GrColorFragmentProcessorAnalysis {
93public:
Brian Salomon650ced02017-07-20 16:46:46 -040094 GrColorFragmentProcessorAnalysis() = delete;
Brian Salomonc0b642c2017-03-27 13:09:36 -040095
Brian Salomon650ced02017-07-20 16:46:46 -040096 GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input,
97 const GrFragmentProcessor* const* processors,
98 int cnt);
Brian Salomonc0b642c2017-03-27 13:09:36 -040099
100 bool isOpaque() const { return fIsOpaque; }
101
102 /**
103 * Are all the fragment processors compatible with conflating coverage with color prior to the
Brian Salomon28207df2017-06-05 12:25:13 -0400104 * the first fragment processor. This result assumes that processors that should be eliminated
105 * as indicated by initialProcessorsToEliminate() are in fact eliminated.
Brian Salomonc0b642c2017-03-27 13:09:36 -0400106 */
107 bool allProcessorsCompatibleWithCoverageAsAlpha() const {
Brian Salomon650ced02017-07-20 16:46:46 -0400108 return fCompatibleWithCoverageAsAlpha;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400109 }
110
111 /**
Brian Salomon28207df2017-06-05 12:25:13 -0400112 * Do any of the fragment processors require local coords. This result assumes that
113 * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in
114 * fact eliminated.
Brian Salomonc0b642c2017-03-27 13:09:36 -0400115 */
116 bool usesLocalCoords() const { return fUsesLocalCoords; }
117
118 /**
119 * If we detected that the result after the first N processors is a known color then we
120 * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with
121 * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if
122 * there are only N processors) sees its expected input. If this returns 0 then there are no
123 * processors to eliminate.
124 */
125 int initialProcessorsToEliminate(GrColor* newPipelineInputColor) const {
Brian Salomon650ced02017-07-20 16:46:46 -0400126 if (fProcessorsToEliminate > 0) {
Brian Osmancb3d0872018-10-16 15:19:28 -0400127 *newPipelineInputColor = fLastKnownOutputColor.toBytes_RGBA();
Brian Salomonc0b642c2017-03-27 13:09:36 -0400128 }
Brian Salomon650ced02017-07-20 16:46:46 -0400129 return fProcessorsToEliminate;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400130 }
131
Brian Osmanf28e55d2018-10-03 16:35:54 -0400132 int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const {
Brian Salomon650ced02017-07-20 16:46:46 -0400133 if (fProcessorsToEliminate > 0) {
Brian Osmanf28e55d2018-10-03 16:35:54 -0400134 *newPipelineInputColor = fLastKnownOutputColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400135 }
Brian Salomon650ced02017-07-20 16:46:46 -0400136 return fProcessorsToEliminate;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400137 }
138
Brian Salomon650ced02017-07-20 16:46:46 -0400139 /**
140 * Provides known information about the last processor's output color.
141 */
Brian Salomona811b122017-03-30 08:21:32 -0400142 GrProcessorAnalysisColor outputColor() const {
Brian Salomon650ced02017-07-20 16:46:46 -0400143 if (fKnowOutputColor) {
Brian Osmancb3d0872018-10-16 15:19:28 -0400144 return fLastKnownOutputColor.toBytes_RGBA();
Brian Salomonc0b642c2017-03-27 13:09:36 -0400145 }
Brian Salomon650ced02017-07-20 16:46:46 -0400146 return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes
147 : GrProcessorAnalysisColor::Opaque::kNo;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400148 }
149
150private:
Brian Salomon650ced02017-07-20 16:46:46 -0400151 bool fIsOpaque;
152 bool fCompatibleWithCoverageAsAlpha;
153 bool fUsesLocalCoords;
154 bool fKnowOutputColor;
155 int fProcessorsToEliminate;
Brian Osman1d5b5982018-10-01 13:41:39 -0400156 SkPMColor4f fLastKnownOutputColor;
Brian Salomonc0b642c2017-03-27 13:09:36 -0400157};
158
159#endif