|  | /* | 
|  | * Copyright 2014 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef GrProcessorAnalysis_DEFINED | 
|  | #define GrProcessorAnalysis_DEFINED | 
|  |  | 
|  | #include "include/private/SkColorData.h" | 
|  |  | 
|  | class GrDrawOp; | 
|  | class GrFragmentProcessor; | 
|  |  | 
|  | class GrProcessorAnalysisColor { | 
|  | public: | 
|  | enum class Opaque { | 
|  | kNo, | 
|  | kYes, | 
|  | }; | 
|  |  | 
|  | constexpr GrProcessorAnalysisColor(Opaque opaque = Opaque::kNo) | 
|  | : fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0) | 
|  | , fColor(SK_PMColor4fTRANSPARENT) {} | 
|  |  | 
|  | GrProcessorAnalysisColor(const SkPMColor4f& color) { this->setToConstant(color); } | 
|  |  | 
|  | void setToConstant(const SkPMColor4f& color) { | 
|  | fColor = color; | 
|  | if (color.isOpaque()) { | 
|  | fFlags = kColorIsKnown_Flag | kIsOpaque_Flag; | 
|  | } else { | 
|  | fFlags = kColorIsKnown_Flag; | 
|  | } | 
|  | } | 
|  |  | 
|  | void setToUnknown() { fFlags = 0; } | 
|  |  | 
|  | void setToUnknownOpaque() { fFlags = kIsOpaque_Flag; } | 
|  |  | 
|  | bool isUnknown() const { return SkToBool(fFlags == 0); } | 
|  |  | 
|  | bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); } | 
|  |  | 
|  | bool isConstant(SkPMColor4f* color = nullptr) const { | 
|  | if (kColorIsKnown_Flag & fFlags) { | 
|  | if (color) { | 
|  | *color = fColor; | 
|  | } | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool operator==(const GrProcessorAnalysisColor& that) const { | 
|  | if (fFlags != that.fFlags) { | 
|  | return false; | 
|  | } | 
|  | return (kColorIsKnown_Flag & fFlags) ? fColor == that.fColor : true; | 
|  | } | 
|  |  | 
|  | /** The returned value reflects the common properties of the two inputs. */ | 
|  | static GrProcessorAnalysisColor Combine(const GrProcessorAnalysisColor& a, | 
|  | const GrProcessorAnalysisColor& b) { | 
|  | GrProcessorAnalysisColor result; | 
|  | uint32_t commonFlags = a.fFlags & b.fFlags; | 
|  | if ((kColorIsKnown_Flag & commonFlags) && a.fColor == b.fColor) { | 
|  | result.fColor = a.fColor; | 
|  | result.fFlags = a.fFlags; | 
|  | } else if (kIsOpaque_Flag & commonFlags) { | 
|  | result.fFlags = kIsOpaque_Flag; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | private: | 
|  | enum Flags { | 
|  | kColorIsKnown_Flag = 0x1, | 
|  | kIsOpaque_Flag = 0x2, | 
|  | }; | 
|  | uint32_t fFlags; | 
|  | SkPMColor4f fColor; | 
|  | }; | 
|  |  | 
|  | enum class GrProcessorAnalysisCoverage { kNone, kSingleChannel, kLCD }; | 
|  |  | 
|  | /** | 
|  | * GrColorFragmentProcessorAnalysis gathers invariant data from a set of color fragment processors. | 
|  | * It is used to recognize optimizations that can simplify the generated shader or make blending | 
|  | * more effecient. | 
|  | */ | 
|  | class GrColorFragmentProcessorAnalysis { | 
|  | public: | 
|  | GrColorFragmentProcessorAnalysis() = delete; | 
|  |  | 
|  | GrColorFragmentProcessorAnalysis(const GrProcessorAnalysisColor& input, | 
|  | std::unique_ptr<GrFragmentProcessor> const fps[], | 
|  | int cnt); | 
|  |  | 
|  | bool isOpaque() const { return fIsOpaque; } | 
|  |  | 
|  | /** | 
|  | * Are all the fragment processors compatible with conflating coverage with color prior to the | 
|  | * the first fragment processor. This result assumes that processors that should be eliminated | 
|  | * as indicated by initialProcessorsToEliminate() are in fact eliminated. | 
|  | */ | 
|  | bool allProcessorsCompatibleWithCoverageAsAlpha() const { | 
|  | return fCompatibleWithCoverageAsAlpha; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Do any of the fragment processors require local coords. This result assumes that | 
|  | * processors that should be eliminated as indicated by initialProcessorsToEliminate() are in | 
|  | * fact eliminated. | 
|  | */ | 
|  | bool usesLocalCoords() const { return fUsesLocalCoords; } | 
|  |  | 
|  | /** | 
|  | * If we detected that the result after the first N processors is a known color then we | 
|  | * eliminate those N processors and replace the GrDrawOp's color input to the GrPipeline with | 
|  | * the known output of the Nth processor, so that the Nth+1 fragment processor (or the XP if | 
|  | * there are only N processors) sees its expected input. If this returns 0 then there are no | 
|  | * processors to eliminate. | 
|  | */ | 
|  | int initialProcessorsToEliminate(SkPMColor4f* newPipelineInputColor) const { | 
|  | if (fProcessorsToEliminate > 0) { | 
|  | *newPipelineInputColor = fLastKnownOutputColor; | 
|  | } | 
|  | return fProcessorsToEliminate; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Provides known information about the last processor's output color. | 
|  | */ | 
|  | GrProcessorAnalysisColor outputColor() const { | 
|  | if (fKnowOutputColor) { | 
|  | return fLastKnownOutputColor; | 
|  | } | 
|  | return fIsOpaque ? GrProcessorAnalysisColor::Opaque::kYes | 
|  | : GrProcessorAnalysisColor::Opaque::kNo; | 
|  | } | 
|  |  | 
|  | private: | 
|  | bool fIsOpaque; | 
|  | bool fCompatibleWithCoverageAsAlpha; | 
|  | bool fUsesLocalCoords; | 
|  | bool fKnowOutputColor; | 
|  | int fProcessorsToEliminate; | 
|  | SkPMColor4f fLastKnownOutputColor; | 
|  | }; | 
|  |  | 
|  | #endif |