Make GrPipelineAnalysis a nested class of GrProcessorSet.

It is renamed to FragmentProcessorAnalysis since it represents the outputs of the final FPs.

It now stores the analysis results that are subsequently needed rather than exposing GrProcOptInfo.

GrProcOptInfo is now only used on color FPs (not coverage).

Miscellaneous related renamings.


Change-Id: I95c518a7a76df6dc294a9fa67c611f8f653247bc
Reviewed-on: https://skia-review.googlesource.com/8534
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2017-02-22 11:52:03 -05:00 committed by Skia Commit-Bot
parent 3661bc9976
commit 5298dc8bf3
51 changed files with 483 additions and 433 deletions

View File

@ -21,6 +21,7 @@
GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
GrPipelineOptimizations* optimizations) {
SkASSERT(args.fAnalysis);
GrRenderTarget* rt = args.fRenderTargetContext->accessRenderTarget();
if (!rt) {
return nullptr;
@ -59,8 +60,8 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
const GrXPFactory* xpFactory = args.fProcessors->xpFactory();
sk_sp<GrXferProcessor> xferProcessor;
if (xpFactory) {
xferProcessor.reset(xpFactory->createXferProcessor(
args.fAnalysis, hasMixedSamples, &args.fDstTexture, *args.fCaps));
xferProcessor.reset(xpFactory->createXferProcessor(*args.fAnalysis, hasMixedSamples,
&args.fDstTexture, *args.fCaps));
if (!xferProcessor) {
pipeline->~GrPipeline();
return nullptr;
@ -68,17 +69,17 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
} else {
// This may return nullptr in the common case of src-over implemented using hw blending.
xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
*args.fCaps, args.fAnalysis, hasMixedSamples, &args.fDstTexture));
*args.fCaps, *args.fAnalysis, hasMixedSamples, &args.fDstTexture));
}
GrColor overrideColor = GrColor_ILLEGAL;
int colorFPsToEliminate = args.fAnalysis.fColorPOI.initialProcessorsToEliminate(&overrideColor);
int colorFPsToEliminate = args.fAnalysis->initialColorProcessorsToEliminate(&overrideColor);
GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
&GrPorterDuffXPFactory::SimpleSrcOverXP();
optFlags = xpForOpts->getOptimizations(
args.fAnalysis, args.fUserStencil->doesWrite(args.fAppliedClip->hasStencilClip()),
*args.fAnalysis, args.fUserStencil->doesWrite(args.fAppliedClip->hasStencilClip()),
&overrideColor, *args.fCaps);
// When path rendering the stencil settings are not always set on the GrPipelineBuilder
@ -144,8 +145,7 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
optimizations->fFlags |= GrPipelineOptimizations::kCanTweakAlphaForCoverage_Flag;
}
if (GrXPFactory::WillReadDst(xpFactory, args.fAnalysis.fColorPOI,
args.fAnalysis.fCoveragePOI)) {
if (GrXPFactory::WillReadDst(xpFactory, *args.fAnalysis)) {
optimizations->fFlags |= GrPipelineOptimizations::kXPReadsDst_Flag;
}

View File

@ -14,13 +14,13 @@
#include "GrPendingProgramElement.h"
#include "GrPrimitiveProcessor.h"
#include "GrProcOptInfo.h"
#include "GrProcessorSet.h"
#include "GrProgramDesc.h"
#include "GrScissorState.h"
#include "GrUserStencilSettings.h"
#include "GrWindowRectsState.h"
#include "SkMatrix.h"
#include "SkRefCnt.h"
#include "effects/GrCoverageSetOpXP.h"
#include "effects/GrDisableColorXP.h"
#include "effects/GrPorterDuffXferProcessor.h"
@ -32,36 +32,6 @@ class GrOp;
class GrPipelineBuilder;
class GrRenderTargetContext;
/**
* This Describes aspects of the GrPrimitiveProcessor produced by a GrDrawOp that are used in
* pipeline analysis.
*/
class GrPipelineAnalysisDrawOpInput {
public:
GrPipelineAnalysisDrawOpInput(GrPipelineInput* color, GrPipelineInput* coverage)
: fColorInput(color), fCoverageInput(coverage) {}
GrPipelineInput* pipelineColorInput() { return fColorInput; }
GrPipelineInput* pipelineCoverageInput() { return fCoverageInput; }
void setUsesPLSDstRead() { fUsesPLSDstRead = true; }
bool usesPLSDstRead() const { return fUsesPLSDstRead; }
private:
GrPipelineInput* fColorInput;
GrPipelineInput* fCoverageInput;
bool fUsesPLSDstRead = false;
};
/** This is used to track pipeline analysis through the color and coverage fragment processors. */
struct GrPipelineAnalysis {
GrProcOptInfo fColorPOI;
GrProcOptInfo fCoveragePOI;
bool fUsesPLSDstRead = false;
};
class GrProcessorSet;
/**
* Class that holds an optimized version of a GrPipelineBuilder. It is meant to be an immutable
* class, and contains all data needed to set the state for a gpu draw.
@ -89,11 +59,11 @@ public:
uint32_t fFlags = 0;
GrDrawFace fDrawFace = GrDrawFace::kBoth;
const GrProcessorSet* fProcessors = nullptr;
const GrProcessorSet::FragmentProcessorAnalysis* fAnalysis;
const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
GrAppliedClip* fAppliedClip = nullptr;
GrRenderTargetContext* fRenderTargetContext = nullptr;
const GrCaps* fCaps = nullptr;
GrPipelineAnalysis fAnalysis;
GrXferProcessor::DstTexture fDstTexture;
};

View File

@ -18,7 +18,6 @@
class GrCaps;
class GrDrawOp;
class GrPaint;
struct GrPipelineAnalysis;
class GrTexture;
class GrPipelineBuilder : private SkNoncopyable {
@ -62,9 +61,7 @@ public:
return fProcessors.coverageFragmentProcessor(idx);
}
void analyzeFragmentProcessors(GrPipelineAnalysis* analysis) const {
fProcessors.analyzeFragmentProcessors(analysis);
}
const GrProcessorSet& processors() const { return fProcessors; }
/// @}
@ -75,11 +72,9 @@ public:
/**
* Checks whether the xp will need destination in a texture to correctly blend.
*/
bool willXPNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const {
if (fProcessors.xpFactory()) {
return fProcessors.xpFactory()->willNeedDstTexture(caps, analysis);
}
return GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(caps, analysis);
bool willXPNeedDstTexture(const GrCaps& caps,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) const {
return GrXPFactory::WillNeedDstTexture(fProcessors.xpFactory(), caps, analysis);
}
/// @}

View File

@ -20,10 +20,10 @@ struct GrPipelineInput {
kYes,
};
explicit GrPipelineInput(Opaque opaque = Opaque::kNo)
GrPipelineInput(Opaque opaque = Opaque::kNo)
: fFlags(opaque == Opaque::kYes ? kIsOpaque_Flag : 0) {}
explicit GrPipelineInput(GrColor color) : fFlags(kColorIsKnown_Flag), fColor(color) {}
GrPipelineInput(GrColor color) : fFlags(kColorIsKnown_Flag), fColor(color) {}
void setToConstant(GrColor color) {
fColor = color;
@ -53,6 +53,8 @@ struct GrPipelineInput {
bool isOpaque() const { return SkToBool(kIsOpaque_Flag & fFlags); }
bool isSolidWhite() const { return (kColorIsKnown_Flag & fFlags) && GrColor_WHITE == fColor; }
bool isConstant(GrColor* color) const {
if (kColorIsKnown_Flag & fFlags) {
*color = fColor;

View File

@ -24,7 +24,8 @@
* GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final
* color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve
* correctness. The GrDrawOp seeds these loops with initial color and coverage, in its
* getPipelineAnalysisInput implementation. These seed values are processed by the subsequent
* getFragmentProcessorAnalysisInputs implementation. These seed values are processed by the
* subsequent
* stages of the rendering pipeline and the output is then fed back into the GrDrawOp in
* the applyPipelineOptimizations call, where the op can use the information to inform decisions
* about GrPrimitiveProcessor creation.

View File

@ -25,7 +25,6 @@ public:
GrProcOptInfo() = default;
GrProcOptInfo(const GrPipelineInput& input) : GrProcOptInfo() {
fIsLCDCoverage = input.isLCDCoverage();
fAllProcessorsCompatibleWithCoverageAsAlpha = !input.isLCDCoverage();
fIsOpaque = input.isOpaque();
GrColor color;
@ -35,12 +34,6 @@ public:
}
}
void resetToLCDCoverage() {
*this = GrProcOptInfo();
fIsLCDCoverage = true;
fAllProcessorsCompatibleWithCoverageAsAlpha = false;
}
void reset(const GrPipelineInput& input) { *this = GrProcOptInfo(input); }
/**
@ -49,15 +42,10 @@ public:
*/
void analyzeProcessors(const GrFragmentProcessor* const* processors, int cnt);
bool isSolidWhite() const {
return fProcessorsVisitedWithKnownOutput == fTotalProcessorsVisited &&
fLastKnownOutputColor == GrColor4f::OpaqueWhite();
}
bool isOpaque() const { return fIsOpaque; }
bool allProcessorsCompatibleWithCoverageAsAlpha() const {
return fAllProcessorsCompatibleWithCoverageAsAlpha;
}
bool isLCDCoverage() const { return fIsLCDCoverage; }
/**
* If we detected that the result after the first N processors is a known color then we
@ -72,6 +60,7 @@ public:
}
return SkTMax(0, fProcessorsVisitedWithKnownOutput);
}
int initialProcessorsToEliminate(GrColor4f* newPipelineInputColor) const {
if (fProcessorsVisitedWithKnownOutput > 0) {
*newPipelineInputColor = fLastKnownOutputColor;
@ -93,7 +82,6 @@ private:
int fTotalProcessorsVisited = 0;
// negative one means even the color is unknown before adding the first processor.
int fProcessorsVisitedWithKnownOutput = -1;
bool fIsLCDCoverage = false;
bool fIsOpaque = false;
bool fAllProcessorsCompatibleWithCoverageAsAlpha = true;
GrColor4f fLastKnownOutputColor;

View File

@ -6,6 +6,9 @@
*/
#include "GrProcessorSet.h"
#include "GrAppliedClip.h"
#include "GrCaps.h"
#include "GrProcOptInfo.h"
GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
fXPFactory = paint.fXPFactory;
@ -29,3 +32,72 @@ GrProcessorSet::GrProcessorSet(GrPaint&& paint) {
fFlags |= kAllowSRGBInputs_Flag;
}
}
//////////////////////////////////////////////////////////////////////////////
void GrProcessorSet::FragmentProcessorAnalysis::internalReset(const GrPipelineInput& colorInput,
const GrPipelineInput coverageInput,
const GrProcessorSet& processors,
bool usesPLSDstRead,
const GrFragmentProcessor* clipFP,
const GrCaps& caps) {
GrProcOptInfo colorInfo(colorInput);
fUsesPLSDstRead = usesPLSDstRead;
fCompatibleWithCoverageAsAlpha = !coverageInput.isLCDCoverage();
const GrFragmentProcessor* const* fps = processors.fFragmentProcessors.get();
colorInfo.analyzeProcessors(fps, processors.fColorFragmentProcessorCnt);
fCompatibleWithCoverageAsAlpha &= colorInfo.allProcessorsCompatibleWithCoverageAsAlpha();
fps += processors.fColorFragmentProcessorCnt;
int n = processors.numCoverageFragmentProcessors();
bool hasCoverageFP = n > 0;
for (int i = 0; i < n && fCompatibleWithCoverageAsAlpha; ++i) {
if (!fps[i]->compatibleWithCoverageAsAlpha()) {
fCompatibleWithCoverageAsAlpha = false;
// Other than tests that exercise atypical behavior we expect all coverage FPs to be
// compatible with the coverage-as-alpha optimization.
GrCapsDebugf(&caps, "Coverage FP is not compatible with coverage as alpha.\n");
break;
}
}
if (clipFP) {
fCompatibleWithCoverageAsAlpha &= clipFP->compatibleWithCoverageAsAlpha();
hasCoverageFP = true;
}
fInitialColorProcessorsToEliminate =
colorInfo.initialProcessorsToEliminate(&fOverrideInputColor);
bool opaque = colorInfo.isOpaque();
if (colorInfo.hasKnownOutputColor(&fKnownOutputColor)) {
fColorType = opaque ? ColorType::kOpaqueConstant : ColorType::kConstant;
} else if (opaque) {
fColorType = ColorType::kOpaque;
} else {
fColorType = ColorType::kUnknown;
}
if (coverageInput.isLCDCoverage()) {
fCoverageType = CoverageType::kLCD;
} else {
fCoverageType = hasCoverageFP || !coverageInput.isSolidWhite()
? CoverageType::kSingleChannel
: CoverageType::kNone;
}
}
void GrProcessorSet::FragmentProcessorAnalysis::reset(const GrPipelineInput& colorInput,
const GrPipelineInput coverageInput,
const GrProcessorSet& processors,
bool usesPLSDstRead,
const GrAppliedClip& appliedClip,
const GrCaps& caps) {
this->internalReset(colorInput, coverageInput, processors, usesPLSDstRead,
appliedClip.clipCoverageFragmentProcessor(), caps);
}
GrProcessorSet::FragmentProcessorAnalysis::FragmentProcessorAnalysis(
const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, const GrCaps& caps)
: FragmentProcessorAnalysis() {
this->internalReset(colorInput, coverageInput, GrProcessorSet(GrPaint()), false, nullptr, caps);
}

View File

@ -10,9 +10,10 @@
#include "GrFragmentProcessor.h"
#include "GrPaint.h"
#include "GrPipeline.h"
#include "GrPipelineInput.h"
#include "SkTemplates.h"
class GrAppliedClip;
class GrXPFactory;
class GrProcessorSet : private SkNoncopyable {
@ -43,19 +44,65 @@ public:
const GrXPFactory* xpFactory() const { return fXPFactory; }
void analyzeFragmentProcessors(GrPipelineAnalysis* analysis) const {
const GrFragmentProcessor* const* fps = fFragmentProcessors.get();
analysis->fColorPOI.analyzeProcessors(fps, fColorFragmentProcessorCnt);
fps += fColorFragmentProcessorCnt;
analysis->fCoveragePOI.analyzeProcessors(fps, this->numCoverageFragmentProcessors());
}
bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
bool disableOutputConversionToSRGB() const {
return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
}
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
/**
* This is used to track analysis of color and coverage values through the fragment processors.
*/
class FragmentProcessorAnalysis {
public:
FragmentProcessorAnalysis() = default;
// This version is used by a unit test that assumes no clip, no processors, and no PLS.
FragmentProcessorAnalysis(const GrPipelineInput& colorInput,
const GrPipelineInput coverageInput, const GrCaps&);
void reset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
const GrProcessorSet&, bool usesPLSDstRead, const GrAppliedClip&, const GrCaps&);
int initialColorProcessorsToEliminate(GrColor* newInputColor) const {
if (fInitialColorProcessorsToEliminate > 0) {
*newInputColor = fOverrideInputColor;
}
return fInitialColorProcessorsToEliminate;
}
bool usesPLSDstRead() const { return fUsesPLSDstRead; }
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
bool isOutputColorOpaque() const {
return ColorType::kOpaque == fColorType || ColorType::kOpaqueConstant == fColorType;
}
bool hasKnownOutputColor(GrColor* color = nullptr) const {
bool constant =
ColorType::kConstant == fColorType || ColorType::kOpaqueConstant == fColorType;
if (constant && color) {
*color = fKnownOutputColor;
}
return constant;
}
bool hasCoverage() const { return CoverageType::kNone != fCoverageType; }
bool hasLCDCoverage() const { return CoverageType::kLCD == fCoverageType; }
private:
void internalReset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
const GrProcessorSet&, bool usesPLSDstRead,
const GrFragmentProcessor* clipFP, const GrCaps&);
enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque };
enum class CoverageType { kNone, kSingleChannel, kLCD };
bool fUsesPLSDstRead = false;
bool fCompatibleWithCoverageAsAlpha = true;
CoverageType fCoverageType = CoverageType::kNone;
ColorType fColorType = ColorType::kUnknown;
int fInitialColorProcessorsToEliminate = 0;
GrColor fOverrideInputColor;
GrColor fKnownOutputColor;
};
private:
const GrXPFactory* fXPFactory = nullptr;
SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;

View File

@ -286,13 +286,16 @@ void GrRenderTargetOpList::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
}
}
GrProcessorSet::FragmentProcessorAnalysis analysis;
op->analyzeProcessors(&analysis, pipelineBuilder.processors(), appliedClip, *this->caps());
GrPipeline::CreateArgs args;
pipelineBuilder.initPipelineCreateArgs(&args);
args.fAppliedClip = &appliedClip;
args.fRenderTargetContext = renderTargetContext;
args.fCaps = this->caps();
op->initPipelineAnalysis(&args.fAnalysis);
if (args.fAnalysis.fUsesPLSDstRead || fClipOpToBounds) {
args.fAnalysis = &analysis;
if (analysis.usesPLSDstRead() || fClipOpToBounds) {
GrGLIRect viewport;
viewport.fLeft = 0;
viewport.fBottom = 0;
@ -311,24 +314,12 @@ void GrRenderTargetOpList::addDrawOp(const GrPipelineBuilder& pipelineBuilder,
return;
}
}
pipelineBuilder.analyzeFragmentProcessors(&args.fAnalysis);
if (const GrFragmentProcessor* clipFP = appliedClip.clipCoverageFragmentProcessor()) {
args.fAnalysis.fCoveragePOI.analyzeProcessors(&clipFP, 1);
}
#ifdef SK_DEBUG
// Other than tests that exercise atypical behavior we expect all coverage FPs to be compatible
// with the coverage-as-alpha optimization.
if (!args.fAnalysis.fCoveragePOI.allProcessorsCompatibleWithCoverageAsAlpha() &&
!args.fAnalysis.fCoveragePOI.isLCDCoverage()) {
GrCapsDebugf(this->caps(), "Coverage FP is not compatible with coverage as alpha.\n");
}
#endif
if (!renderTargetContext->accessRenderTarget()) {
return;
}
if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), args.fAnalysis)) {
if (pipelineBuilder.willXPNeedDstTexture(*this->caps(), analysis)) {
this->setupDstTexture(renderTargetContext->accessRenderTarget(), clip, op->bounds(),
&args.fDstTexture);
if (!args.fDstTexture.texture()) {

View File

@ -30,10 +30,11 @@ GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture,
}
}
GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(const GrPipelineAnalysis& analysis,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const {
GrXferProcessor::OptFlags GrXferProcessor::getOptimizations(
const FragmentProcessorAnalysis& analysis,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const {
GrXferProcessor::OptFlags flags =
this->onGetOptimizations(analysis, doesStencilWrite, overrideColor, caps);
return flags;
@ -180,48 +181,36 @@ SkString GrXferProcessor::BlendInfo::dump() const {
///////////////////////////////////////////////////////////////////////////////
using ColorType = GrXPFactory::ColorType;
using CoverageType = GrXPFactory::CoverageType;
ColorType analysis_color_type(const GrPipelineAnalysis& analysis) {
if (analysis.fColorPOI.hasKnownOutputColor()) {
return analysis.fColorPOI.isOpaque() ? ColorType::kOpaqueConstant : ColorType::kConstant;
}
if (analysis.fColorPOI.isOpaque()) {
return ColorType::kOpaque;
}
return ColorType::kUnknown;
}
CoverageType analysis_coverage_type(const GrPipelineAnalysis& analysis) {
if (analysis.fCoveragePOI.isSolidWhite()) {
return CoverageType::kNone;
}
if (analysis.fCoveragePOI.isLCDCoverage()) {
return CoverageType::kLCD;
}
return CoverageType::kSingleChannel;
}
bool GrXPFactory::WillReadDst(const GrXPFactory* factory, const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput) {
bool GrXPFactory::WillReadDst(const GrXPFactory* factory,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
if (factory) {
return factory->willReadsDst(colorInput, coverageInput);
return factory->willReadsDst(analysis);
}
return GrPorterDuffXPFactory::WillSrcOverReadDst(colorInput, coverageInput);
return GrPorterDuffXPFactory::WillSrcOverReadDst(analysis);
}
bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& caps,
const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
bool result;
if (factory) {
result = !analysis.usesPLSDstRead() && !caps.shaderCaps()->dstReadInShaderSupport() &&
factory->willReadDstInShader(caps, analysis);
} else {
result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis);
}
SkASSERT(!(result && !WillReadDst(factory, analysis)));
return result;
}
bool GrXPFactory::willReadDstInShader(const GrCaps& caps,
const GrPipelineAnalysis& analysis) const {
if (analysis.fUsesPLSDstRead) {
const FragmentProcessorAnalysis& analysis) const {
if (analysis.usesPLSDstRead()) {
return true;
}
ColorType colorType = analysis_color_type(analysis);
CoverageType coverageType = analysis_coverage_type(analysis);
return this->willReadDstInShader(caps, colorType, coverageType);
return this->onWillReadDstInShader(caps, analysis);
}
GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineAnalysis& analysis,
GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture,
const GrCaps& caps) const {
@ -239,8 +228,3 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrPipelineAnalysis& anal
#endif
return this->onCreateXferProcessor(caps, analysis, hasMixedSamples, dstTexture);
}
bool GrXPFactory::willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const {
return !analysis.fUsesPLSDstRead && !caps.shaderCaps()->dstReadInShaderSupport() &&
this->willReadDstInShader(caps, analysis);
}

View File

@ -11,13 +11,13 @@
#include "GrBlend.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrProcessorSet.h"
#include "GrTexture.h"
#include "GrTypes.h"
class GrShaderCaps;
class GrGLSLXferProcessor;
class GrProcOptInfo;
struct GrPipelineAnalysis;
/**
* Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
@ -49,6 +49,8 @@ GR_STATIC_ASSERT(SkToBool(kNone_GrXferBarrierType) == false);
*/
class GrXferProcessor : public GrProcessor {
public:
using FragmentProcessorAnalysis = GrProcessorSet::FragmentProcessorAnalysis;
/**
* A texture that contains the dst pixel values and an integer coord offset from device space
* to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
@ -131,11 +133,11 @@ public:
* the draw with this xfer processor. If this function is called, the xfer processor may change
* its state to reflected the given blend optimizations. If the XP needs to see a specific input
* color to blend correctly, it will set the OverrideColor flag and the output parameter
* overrideColor will be the required value that should be passed into the XP.
* overrideColor will be the required value that should be passed into the XP.
* A caller who calls this function on a XP is required to honor the returned OptFlags
* and color values for its draw.
*/
OptFlags getOptimizations(const GrPipelineAnalysis&,
OptFlags getOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const;
@ -231,7 +233,7 @@ protected:
private:
void notifyRefCntIsZero() const final {}
virtual OptFlags onGetOptimizations(const GrPipelineAnalysis&,
virtual OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const = 0;
@ -306,18 +308,11 @@ GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
#endif
class GrXPFactory {
public:
using FragmentProcessorAnalysis = GrProcessorSet::FragmentProcessorAnalysis;
typedef GrXferProcessor::DstTexture DstTexture;
/** Describes known properties of a draw's color input to the GrXferProcessor. */
enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque };
/**
* Indicates whether a draw's coverage input to the GrXferProcessor is solid, single channel
* or LCD (four channel coverage).
*/
enum class CoverageType { kNone, kSingleChannel, kLCD };
GrXferProcessor* createXferProcessor(const GrPipelineAnalysis&,
GrXferProcessor* createXferProcessor(const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*,
const GrCaps& caps) const;
@ -325,44 +320,36 @@ public:
/**
* Is the destination color required either in the shader or fixed function blending.
*/
static bool WillReadDst(const GrXPFactory*, const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput);
static bool WillReadDst(const GrXPFactory*, const FragmentProcessorAnalysis&);
/**
* This will return true if the xfer processor needs the dst color in the shader and the way
* that the color will be made available to the xfer processor is by sampling a texture.
*/
bool willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const;
/**
* This will return true if the xfer processor needs the dst color in the shader and the way
* that the color will be made available to the xfer processor is by sampling a texture.
*/
static bool WillNeedDstTexture(const GrXPFactory*,
const GrCaps&,
const FragmentProcessorAnalysis&);
protected:
constexpr GrXPFactory() {}
static bool ColorTypeIsOpaque(ColorType type) {
return ColorType::kOpaqueConstant == type || ColorType::kOpaque == type;
}
static bool ColorTypeIsConstant(ColorType type) {
return ColorType::kOpaqueConstant == type || ColorType::kConstant == type;
}
private:
/** Subclass-specific implementation of WillReadDst(). */
virtual bool willReadsDst(const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput) const = 0;
virtual bool willReadsDst(const FragmentProcessorAnalysis& pipelineAnalysis) const = 0;
virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const = 0;
bool willReadDstInShader(const GrCaps& caps, const GrPipelineAnalysis& analysis) const;
bool willReadDstInShader(const GrCaps& caps, const FragmentProcessorAnalysis& analysis) const;
/**
* Returns true if the XP generated by this factory will explicitly read dst in the fragment
* shader. This will not be called for draws that read from PLS since the dst color is always
* available in such draws.
*/
virtual bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const = 0;
virtual bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop

View File

@ -34,7 +34,7 @@ public:
private:
CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis& analysis,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis& analysis,
bool doesStencilWrite,
GrColor* color,
const GrCaps& caps) const override;
@ -107,10 +107,11 @@ GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
return new GLCoverageSetOpXP(*this);
}
GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(const GrPipelineAnalysis& analysis,
bool doesStencilWrite,
GrColor* color,
const GrCaps& caps) const {
GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(
const FragmentProcessorAnalysis& analysis,
bool doesStencilWrite,
GrColor* color,
const GrCaps& caps) const {
// We never look at the color input
return GrXferProcessor::kIgnoreColor_OptFlag;
}
@ -167,7 +168,7 @@ public:
bool invertCoverage() const { return fInvertCoverage; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&, bool, GrColor*,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&, bool, GrColor*,
const GrCaps&) const override {
// We never look at the color input
return GrXferProcessor::kIgnoreColor_OptFlag;
@ -321,10 +322,11 @@ const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool inv
return nullptr;
}
GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
// We don't support inverting coverage with mixed samples. We don't expect to ever want this in
// the future, however we could at some point make this work using an inverted coverage
// modulation table. Note that an inverted table still won't work if there are coverage procs.
@ -333,7 +335,7 @@ GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& c
return nullptr;
}
if (analysis.fUsesPLSDstRead) {
if (analysis.usesPLSDstRead()) {
return new ShaderCSOXferProcessor(dst, hasMixedSamples, fRegionOp, fInvertCoverage);
}
return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);

View File

@ -32,16 +32,16 @@ public:
private:
constexpr GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
bool willReadsDst(const GrProcOptInfo&, const GrProcOptInfo&) const override {
bool willReadsDst(const FragmentProcessorAnalysis&) const override {
return fRegionOp != SkRegion::kReplace_Op;
}
GrXferProcessor* onCreateXferProcessor(const GrCaps&,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const override {
bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
return false;
}

View File

@ -103,7 +103,7 @@ public:
}
private:
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const override;
@ -197,7 +197,7 @@ bool CustomXP::onIsEqual(const GrXferProcessor& other) const {
return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation;
}
GrXferProcessor::OptFlags CustomXP::onGetOptimizations(const GrPipelineAnalysis& analysis,
GrXferProcessor::OptFlags CustomXP::onGetOptimizations(const FragmentProcessorAnalysis& analysis,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const {
@ -300,8 +300,7 @@ GrXferProcessor::OptFlags CustomXP::onGetOptimizations(const GrPipelineAnalysis&
*/
OptFlags flags = kNone_OptFlags;
if (analysis.fColorPOI.allProcessorsCompatibleWithCoverageAsAlpha() &&
analysis.fCoveragePOI.allProcessorsCompatibleWithCoverageAsAlpha()) {
if (analysis.isCompatibleWithCoverageAsAlpha()) {
flags |= kCanTweakAlphaForCoverage_OptFlag;
}
return flags;
@ -334,13 +333,13 @@ public:
private:
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadsDst(const GrProcOptInfo&, const GrProcOptInfo&) const override { return true; }
bool willReadsDst(const FragmentProcessorAnalysis&) const override { return true; }
bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const override;
bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
GR_DECLARE_XP_FACTORY_TEST;
@ -354,24 +353,24 @@ private:
#endif
GrXferProcessor* CustomXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis& analysis,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
if (can_use_hw_blend_equation(fHWBlendEquation, analysis.fUsesPLSDstRead,
analysis.fCoveragePOI.isLCDCoverage(), caps)) {
if (can_use_hw_blend_equation(fHWBlendEquation, analysis.usesPLSDstRead(),
analysis.hasLCDCoverage(), caps)) {
SkASSERT(!dstTexture || !dstTexture->texture());
return new CustomXP(fMode, fHWBlendEquation);
}
return new CustomXP(dstTexture, hasMixedSamples, fMode);
}
bool CustomXPFactory::willReadDstInShader(const GrCaps& caps, ColorType colorType,
CoverageType coverageType) const {
bool CustomXPFactory::onWillReadDstInShader(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) const {
// This should not be called if we're using PLS dst read.
static constexpr bool kUsesPLSRead = false;
return !can_use_hw_blend_equation(fHWBlendEquation, kUsesPLSRead,
CoverageType::kLCD == coverageType, caps);
return !can_use_hw_blend_equation(fHWBlendEquation, kUsesPLSRead, analysis.hasLCDCoverage(),
caps);
}
GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);

View File

@ -29,7 +29,7 @@ public:
private:
DisableColorXP();
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* color,
const GrCaps& caps) const override {
@ -88,11 +88,12 @@ void DisableColorXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const
}
///////////////////////////////////////////////////////////////////////////////
GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
SkASSERT(!analysis.fUsesPLSDstRead);
GrXferProcessor* GrDisableColorXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dst) const {
SkASSERT(!analysis.usesPLSDstRead());
return DisableColorXP::Create();
}

View File

@ -24,19 +24,16 @@ public:
static const GrXPFactory* Get();
private:
bool willReadsDst(const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput) const override {
return false;
}
bool willReadsDst(const FragmentProcessorAnalysis&) const override { return false; }
constexpr GrDisableColorXPFactory() {}
bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const override {
bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
return false;
}
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture* dstTexture) const override;

View File

@ -350,7 +350,7 @@ public:
BlendFormula getBlendFormula() const { return fBlendFormula; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps&) const override;
@ -450,7 +450,7 @@ GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
}
GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations(
const GrPipelineAnalysis& analysis,
const FragmentProcessorAnalysis& analysis,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const {
@ -465,8 +465,7 @@ GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations(
if (!fBlendFormula.usesInputColor()) {
optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
}
if (analysis.fColorPOI.allProcessorsCompatibleWithCoverageAsAlpha() &&
analysis.fCoveragePOI.allProcessorsCompatibleWithCoverageAsAlpha() &&
if (analysis.isCompatibleWithCoverageAsAlpha() &&
fBlendFormula.canTweakAlphaForCoverage()) {
optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
}
@ -493,7 +492,7 @@ public:
SkBlendMode getXfermode() const { return fXfermode; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&, bool, GrColor*,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&, bool, GrColor*,
const GrCaps&) const override {
return kNone_OptFlags;
}
@ -557,7 +556,7 @@ GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
class PDLCDXferProcessor : public GrXferProcessor {
public:
static GrXferProcessor* Create(SkBlendMode xfermode, const GrProcOptInfo& colorPOI);
static GrXferProcessor* Create(SkBlendMode xfermode, const FragmentProcessorAnalysis& analysis);
~PDLCDXferProcessor() override;
@ -568,7 +567,7 @@ public:
private:
PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineAnalysis&,
GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps&) const override;
@ -628,12 +627,13 @@ PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
this->initClassID<PDLCDXferProcessor>();
}
GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode, const GrProcOptInfo& colorPOI) {
GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode,
const FragmentProcessorAnalysis& analysis) {
if (SkBlendMode::kSrcOver != xfermode) {
return nullptr;
}
GrColor blendConstant;
if (!colorPOI.hasKnownOutputColor(&blendConstant)) {
if (!analysis.hasKnownOutputColor(&blendConstant)) {
return nullptr;
}
uint8_t alpha = GrColorUnpackA(blendConstant);
@ -653,7 +653,7 @@ GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
return new GLPDLCDXferProcessor(*this);
}
GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations(const GrPipelineAnalysis&,
GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations(const FragmentProcessorAnalysis&,
bool doesStencilWrite,
GrColor* overrideColor,
const GrCaps& caps) const {
@ -734,28 +734,28 @@ const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
}
}
GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
if (analysis.fUsesPLSDstRead) {
GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
const GrCaps& caps,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const DstTexture* dstTexture) const {
if (analysis.usesPLSDstRead()) {
return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
}
BlendFormula blendFormula;
if (analysis.fCoveragePOI.isLCDCoverage()) {
if (SkBlendMode::kSrcOver == fBlendMode && analysis.fColorPOI.hasKnownOutputColor() &&
if (analysis.hasLCDCoverage()) {
if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
!caps.shaderCaps()->dualSourceBlendingSupport() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
// If we don't have dual source blending or in shader dst reads, we fall back to this
// trick for rendering SrcOver LCD text instead of doing a dst copy.
SkASSERT(!dstTexture || !dstTexture->texture());
return PDLCDXferProcessor::Create(fBlendMode, analysis.fColorPOI);
return PDLCDXferProcessor::Create(fBlendMode, analysis);
}
blendFormula = get_lcd_blend_formula(fBlendMode);
} else {
blendFormula = get_blend_formula(analysis.fColorPOI.isOpaque(),
!analysis.fCoveragePOI.isSolidWhite(), hasMixedSamples,
fBlendMode);
blendFormula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
hasMixedSamples, fBlendMode);
}
if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
@ -766,15 +766,14 @@ GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps
return new PorterDuffXferProcessor(blendFormula);
}
bool GrPorterDuffXPFactory::willReadsDst(const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput) const {
BlendFormula colorFormula = gBlendTable[colorInput.isOpaque()][0][(int)fBlendMode];
bool GrPorterDuffXPFactory::willReadsDst(const FragmentProcessorAnalysis& analysis) const {
BlendFormula colorFormula = gBlendTable[analysis.isOutputColorOpaque()][0][(int)fBlendMode];
SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
return (colorFormula.usesDstColor() || !coverageInput.isSolidWhite());
return (colorFormula.usesDstColor() || analysis.hasCoverage());
}
bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps, ColorType colorType,
CoverageType coverageType) const {
bool GrPorterDuffXPFactory::onWillReadDstInShader(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) const {
if (caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
}
@ -782,8 +781,8 @@ bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps, ColorType co
// When we have four channel coverage we always need to read the dst in order to correctly
// blend. The one exception is when we are using srcover mode and we know the input color into
// the XP.
if (CoverageType::kLCD == coverageType) {
if (SkBlendMode::kSrcOver == fBlendMode && ColorTypeIsConstant(colorType) &&
if (analysis.hasLCDCoverage()) {
if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
}
@ -794,9 +793,8 @@ bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps, ColorType co
// don't have support for it.
static const bool kHasMixedSamples = false;
SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
auto formula = get_blend_formula(ColorTypeIsOpaque(colorType),
CoverageType::kSingleChannel == coverageType, kHasMixedSamples,
fBlendMode);
auto formula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
kHasMixedSamples, fBlendMode);
return formula.hasSecondaryOutput();
}
@ -833,10 +831,10 @@ const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
const GrCaps& caps,
const GrPipelineAnalysis& analysis,
const FragmentProcessorAnalysis& analysis,
bool hasMixedSamples,
const GrXferProcessor::DstTexture* dstTexture) {
if (analysis.fUsesPLSDstRead) {
if (analysis.usesPLSDstRead()) {
return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
}
@ -844,7 +842,7 @@ GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
// doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
// the general case where we convert a src-over blend that has solid coverage and an opaque
// color to src-mode, which allows disabling of blending.
if (!analysis.fCoveragePOI.isLCDCoverage()) {
if (!analysis.hasLCDCoverage()) {
// We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
// We don't simply return the address of that XP here because our caller would have to unref
// it and since it is a global object and GrProgramElement's ref-cnting system is not thread
@ -852,14 +850,13 @@ GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
return nullptr;
}
if (analysis.fColorPOI.hasKnownOutputColor() &&
!caps.shaderCaps()->dualSourceBlendingSupport() &&
if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dualSourceBlendingSupport() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
// If we don't have dual source blending or in shader dst reads, we fall
// back to this trick for rendering SrcOver LCD text instead of doing a
// dst copy.
SkASSERT(!dstTexture || !dstTexture->texture());
return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, analysis.fColorPOI);
return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, analysis);
}
BlendFormula blendFormula;
@ -877,9 +874,8 @@ sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode ble
return sk_make_sp<PorterDuffXferProcessor>(formula);
}
bool GrPorterDuffXPFactory::WillSrcOverReadDst(const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput) {
return !coverageInput.isSolidWhite() || !colorInput.isOpaque();
bool GrPorterDuffXPFactory::WillSrcOverReadDst(const FragmentProcessorAnalysis& analysis) {
return analysis.hasCoverage() || !analysis.isOutputColorOpaque();
}
bool GrPorterDuffXPFactory::IsSrcOverPreCoverageBlendedColorConstant(
@ -890,8 +886,8 @@ bool GrPorterDuffXPFactory::IsSrcOverPreCoverageBlendedColorConstant(
return colorInput.hasKnownOutputColor(color);
}
bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
const GrPipelineAnalysis& analysis) {
bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps,
const FragmentProcessorAnalysis& analysis) {
if (caps.shaderCaps()->dstReadInShaderSupport() ||
caps.shaderCaps()->dualSourceBlendingSupport()) {
return false;
@ -900,9 +896,8 @@ bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
// When we have four channel coverage we always need to read the dst in order to correctly
// blend. The one exception is when we are using srcover mode and we know the input color
// into the XP.
if (analysis.fCoveragePOI.isLCDCoverage()) {
if (analysis.fColorPOI.hasKnownOutputColor() &&
!caps.shaderCaps()->dstReadInShaderSupport()) {
if (analysis.hasLCDCoverage()) {
if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dstReadInShaderSupport()) {
return false;
}
auto formula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
@ -912,8 +907,8 @@ bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
// We fallback on the shader XP when the blend formula would use dual source blending but we
// don't have support for it.
static const bool kHasMixedSamples = false;
bool isOpaque = analysis.fColorPOI.isOpaque();
bool hasCoverage = !analysis.fCoveragePOI.isSolidWhite();
bool isOpaque = analysis.isOutputColorOpaque();
bool hasCoverage = analysis.hasCoverage();
SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
auto formula =
get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver);

View File

@ -26,7 +26,7 @@ public:
/** Because src-over is so common we special case it for performance reasons. If this returns
null then the SimpleSrcOverXP() below should be used. */
static GrXferProcessor* CreateSrcOverXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const GrXferProcessor::DstTexture*);
@ -37,24 +37,22 @@ public:
by reference because it is global and its ref-cnting methods are not thread safe. */
static const GrXferProcessor& SimpleSrcOverXP();
static bool WillSrcOverReadDst(const GrProcOptInfo& colorInput,
const GrProcOptInfo& coverageInput);
static bool WillSrcOverReadDst(const FragmentProcessorAnalysis& analysis);
static bool IsSrcOverPreCoverageBlendedColorConstant(const GrProcOptInfo& colorInput,
GrColor* color);
static bool SrcOverWillNeedDstTexture(const GrCaps&, const GrPipelineAnalysis&);
static bool WillSrcOverNeedDstTexture(const GrCaps&, const FragmentProcessorAnalysis&);
private:
constexpr GrPorterDuffXPFactory(SkBlendMode);
bool willReadsDst(const GrProcOptInfo&, const GrProcOptInfo&) const override;
bool willReadsDst(const FragmentProcessorAnalysis&) const override;
GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
const GrPipelineAnalysis&,
const FragmentProcessorAnalysis&,
bool hasMixedSamples,
const DstTexture*) const override;
bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const override;
bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
GR_DECLARE_XP_FACTORY_TEST;
static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary);

View File

@ -340,15 +340,16 @@ void InstancedRendering::Op::appendParamsTexel(SkScalar x, SkScalar y, SkScalar
fInfo.fHasParams = true;
}
void InstancedRendering::Op::getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const {
input->pipelineColorInput()->setToConstant(this->getSingleInstance().fColor);
void InstancedRendering::Op::getFragmentProcessorAnalysisInputs(
FragmentProcessorAnalysisInputs* input) const {
input->colorInput()->setToConstant(this->getSingleInstance().fColor);
if (AntialiasMode::kCoverage == fInfo.fAntialiasMode ||
(AntialiasMode::kNone == fInfo.fAntialiasMode &&
!fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
input->pipelineCoverageInput()->setToUnknown();
input->coverageInput()->setToUnknown();
} else {
input->pipelineCoverageInput()->setToSolidCoverage();
input->coverageInput()->setToSolidCoverage();
}
}

View File

@ -154,7 +154,8 @@ protected:
Draw* fTailDraw;
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override;
void getFragmentProcessorAnalysisInputs(
FragmentProcessorAnalysisInputs* input) const override;
void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
void onPrepare(GrOpFlushState*) override {}

View File

@ -747,9 +747,9 @@ private:
this->setTransformedBounds(path.getBounds(), viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -177,9 +177,9 @@ private:
this->setTransformedBounds(shape.bounds(), viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fShapes[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fShapes[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -203,9 +203,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(this->first()->color());
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(this->first()->color());
input->coverageInput()->setToUnknown();
}
void onPrepareDraws(Target* target) const override {

View File

@ -716,9 +716,9 @@ private:
IsZeroArea::kYes);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -172,9 +172,9 @@ private:
this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fPaths[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fPaths[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -166,9 +166,9 @@ public:
private:
AAStrokeRectOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fRects[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fRects[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
void onPrepareDraws(Target*) const override;

View File

@ -269,9 +269,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -45,23 +45,24 @@ SkString GrAtlasTextOp::dumpInfo() const {
return str;
}
void GrAtlasTextOp::getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const {
void GrAtlasTextOp::getFragmentProcessorAnalysisInputs(
FragmentProcessorAnalysisInputs* input) const {
if (kColorBitmapMask_MaskType == fMaskType) {
input->pipelineColorInput()->setToUnknown();
input->colorInput()->setToUnknown();
} else {
input->pipelineColorInput()->setToConstant(fColor);
input->colorInput()->setToConstant(fColor);
}
switch (fMaskType) {
case kGrayscaleDistanceField_MaskType:
case kGrayscaleCoverageMask_MaskType:
input->pipelineCoverageInput()->setToUnknown();
input->coverageInput()->setToUnknown();
break;
case kLCDCoverageMask_MaskType:
case kLCDDistanceField_MaskType:
input->pipelineCoverageInput()->setToLCDCoverage();
input->coverageInput()->setToLCDCoverage();
break;
case kColorBitmapMask_MaskType:
input->pipelineCoverageInput()->setToSolidCoverage();
input->coverageInput()->setToSolidCoverage();
}
}

View File

@ -99,7 +99,7 @@ public:
SkString dumpInfo() const override;
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput*) const override;
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs*) const override;
void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
struct FlushInfo {

View File

@ -296,9 +296,9 @@ private:
this->setTransformedBounds(bounds, combinedMatrix, aaBloat, zeroArea);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -132,9 +132,9 @@ private:
isHairline ? IsZeroArea::kYes : IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToScalar(this->coverage());
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToScalar(this->coverage());
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -39,13 +39,13 @@ private:
GrDrawAtlasOp(GrColor color, const SkMatrix& viewMatrix, int spriteCount,
const SkRSXform* xforms, const SkRect* rects, const SkColor* colors);
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
if (this->hasColors()) {
input->pipelineColorInput()->setToUnknown();
input->colorInput()->setToUnknown();
} else {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->colorInput()->setToConstant(fGeoData[0].fColor);
}
input->pipelineCoverageInput()->setToSolidCoverage();
input->coverageInput()->setToSolidCoverage();
}
void onPrepareDraws(Target*) const override;

View File

@ -15,16 +15,6 @@ GrDrawOp::~GrDrawOp() {
}
}
void GrDrawOp::initPipelineAnalysis(GrPipelineAnalysis* analysis) const {
GrPipelineInput color;
GrPipelineInput coverage;
GrPipelineAnalysisDrawOpInput input(&color, &coverage);
this->getPipelineAnalysisInput(&input);
analysis->fColorPOI.reset(color);
analysis->fCoveragePOI.reset(coverage);
analysis->fUsesPLSDstRead = input.usesPLSDstRead();
}
bool GrDrawOp::installPipeline(const GrPipeline::CreateArgs& args) {
GrPipelineOptimizations optimizations;
void* location = fPipelineStorage.get();

View File

@ -57,13 +57,22 @@ public:
GrDrawOp(uint32_t classID);
~GrDrawOp() override;
/**
* Gets the inputs to pipeline analysis from the GrDrawOp.
*/
void initPipelineAnalysis(GrPipelineAnalysis*) const;
bool installPipeline(const GrPipeline::CreateArgs&);
/**
* Performs analysis of the fragment processors in GrProcessorSet and GrAppliedClip using the
* initial color and coverage from this op's geometry processor.
*/
void analyzeProcessors(GrProcessorSet::FragmentProcessorAnalysis* analysis,
const GrProcessorSet& processors,
const GrAppliedClip& appliedClip,
const GrCaps& caps) const {
FragmentProcessorAnalysisInputs input;
this->getFragmentProcessorAnalysisInputs(&input);
analysis->reset(*input.colorInput(), *input.coverageInput(), processors,
input.usesPLSDstRead(), appliedClip, caps);
}
protected:
static SkString DumpPipelineInfo(const GrPipeline& pipeline) {
SkString string;
@ -101,12 +110,32 @@ protected:
return reinterpret_cast<const GrPipeline*>(fPipelineStorage.get());
}
/**
* This describes aspects of the GrPrimitiveProcessor produced by a GrDrawOp that are used in
* pipeline analysis.
*/
class FragmentProcessorAnalysisInputs {
public:
FragmentProcessorAnalysisInputs() = default;
GrPipelineInput* colorInput() { return &fColorInput; }
GrPipelineInput* coverageInput() { return &fCoverageInput; }
void setUsesPLSDstRead() { fUsesPLSDstRead = true; }
bool usesPLSDstRead() const { return fUsesPLSDstRead; }
private:
GrPipelineInput fColorInput;
GrPipelineInput fCoverageInput;
bool fUsesPLSDstRead = false;
};
private:
/**
* Provides information about the GrPrimitiveProccesor that will be used to issue draws by this
* op to GrPipeline analysis.
* Provides information about the GrPrimitiveProccesor color and coverage outputs which become
* inputs to the first color and coverage fragment processors.
*/
virtual void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput*) const = 0;
virtual void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs*) const = 0;
/**
* After GrPipeline analysis is complete this is called so that the op can use the analysis

View File

@ -36,9 +36,9 @@ protected:
bool xpReadsDst() const { return fXPReadsDst; }
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -105,13 +105,14 @@ GrDrawVerticesOp::GrDrawVerticesOp(sk_sp<SkVertices> vertices, GrPrimitiveType p
this->setTransformedBounds(mesh.fVertices->bounds(), viewMatrix, HasAABloat::kNo, zeroArea);
}
void GrDrawVerticesOp::getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const {
void GrDrawVerticesOp::getFragmentProcessorAnalysisInputs(
FragmentProcessorAnalysisInputs* input) const {
if (this->requiresPerVertexColors()) {
input->pipelineColorInput()->setToUnknown();
input->colorInput()->setToUnknown();
} else {
input->pipelineColorInput()->setToConstant(fMeshes[0].fColor);
input->colorInput()->setToConstant(fMeshes[0].fColor);
}
input->pipelineCoverageInput()->setToSolidCoverage();
input->coverageInput()->setToSolidCoverage();
}
void GrDrawVerticesOp::applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) {

View File

@ -65,7 +65,7 @@ private:
GrRenderTargetContext::ColorArrayType, const SkMatrix& viewMatrix,
uint32_t flags = 0);
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override;
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override;
void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
void onPrepareDraws(Target*) const override;

View File

@ -61,9 +61,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToUnknown();
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToUnknown();
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& analysioptimizations) override {

View File

@ -259,9 +259,9 @@ private:
this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fPaths[0].fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fPaths[0].fColor);
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -110,9 +110,9 @@ public:
private:
NonAAFillRectOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fRects[0].fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fRects[0].fColor);
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -130,9 +130,9 @@ public:
private:
NonAAFillRectPerspectiveOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fRects[0].fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fRects[0].fColor);
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -102,9 +102,9 @@ public:
private:
NonAAStrokeRectOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToSolidCoverage();
}
void onPrepareDraws(Target* target) const override {

View File

@ -805,9 +805,9 @@ public:
private:
CircleOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
@ -1256,9 +1256,9 @@ public:
private:
EllipseOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
@ -1470,9 +1470,9 @@ public:
private:
DIEllipseOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
@ -1785,9 +1785,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
@ -2147,9 +2147,9 @@ public:
private:
EllipticalRRectOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -781,9 +781,9 @@ private:
IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
input->setUsesPLSDstRead();
}

View File

@ -77,9 +77,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fRegions[0].fColor);
input->pipelineCoverageInput()->setToSolidCoverage();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fRegions[0].fColor);
input->coverageInput()->setToSolidCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -149,9 +149,9 @@ public:
private:
ShadowCircleOp() : INHERITED(ClassID()) {}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fCircles[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fCircles[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
@ -583,9 +583,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fGeoData[0].fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fGeoData[0].fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -180,9 +180,9 @@ public:
}
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -33,9 +33,9 @@ protected:
bool usesLocalCoords() const { return fUsesLocalCoords; }
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(fColor);
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(fColor);
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {

View File

@ -98,9 +98,11 @@ static GrPipeline* construct_dummy_pipeline(GrRenderTargetContext* dc, void* sto
GrPipelineOptimizations dummyOverrides;
GrAppliedClip dummyAppliedClip(SkRect::MakeLargest());
GrProcessorSet::FragmentProcessorAnalysis analysis;
GrPipeline::CreateArgs args;
dummyBuilder.initPipelineCreateArgs(&args);
args.fRenderTargetContext = dc;
args.fAnalysis = &analysis;
args.fCaps = dc->caps();
args.fAppliedClip = &dummyAppliedClip;
args.fDstTexture = GrXferProcessor::DstTexture();

View File

@ -9,6 +9,7 @@
#if SK_SUPPORT_GPU
#include "GrAppliedClip.h"
#include "GrContextFactory.h"
#include "GrContextOptions.h"
#include "GrGpu.h"
@ -66,11 +67,11 @@ class GrPorterDuffTest {
public:
struct XPInfo {
XPInfo(skiatest::Reporter* reporter, SkBlendMode xfermode, const GrCaps& caps,
const GrPipelineAnalysis& analysis) {
const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
fReadsDst = GrXPFactory::WillReadDst(xpf, analysis.fColorPOI, analysis.fCoveragePOI);
fReadsDst = GrXPFactory::WillReadDst(xpf, analysis);
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
TEST_ASSERT(!xpf->willNeedDstTexture(caps, analysis));
TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis));
GrColor ignoredOverrideColor;
fOptFlags = xp->getOptimizations(analysis, false, &ignoredOverrideColor, caps);
GetXPOutputTypes(xp.get(), &fPrimaryOutputType, &fSecondaryOutputType);
@ -92,14 +93,13 @@ public:
};
static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysis analysis;
// Setting the last argument to true will force covPOI to LCD coverage.
analysis.fCoveragePOI.resetToLCDCoverage();
GrPipelineInput lcdInput;
lcdInput.setToLCDCoverage();
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineInput(), lcdInput, caps);
SkASSERT(!analysis.fColorPOI.isOpaque());
SkASSERT(!analysis.fColorPOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isSolidWhite());
SkASSERT(analysis.fCoveragePOI.isLCDCoverage());
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(analysis.hasLCDCoverage());
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
@ -264,12 +264,12 @@ static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps)
}
}
static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysis analysis;
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineInput(), GrPipelineInput(), caps);
SkASSERT(!analysis.fColorPOI.isOpaque());
SkASSERT(!analysis.fColorPOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isLCDCoverage());
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(!analysis.hasLCDCoverage());
SkASSERT(analysis.hasCoverage());
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
@ -435,14 +435,12 @@ static void test_color_unknown_with_coverage(skiatest::Reporter* reporter, const
}
static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysis analysis;
analysis.fColorPOI.reset(GrPipelineInput(GrColorPackRGBA(229, 0, 154, 240)));
analysis.fCoveragePOI.reset(GrPipelineInput(GrColorPackA4(255)));
GrProcessorSet::FragmentProcessorAnalysis analysis(GrColorPackRGBA(229, 0, 154, 240),
GrColorPackA4(255), caps);
SkASSERT(!analysis.fColorPOI.isOpaque());
SkASSERT(!analysis.fColorPOI.isSolidWhite());
SkASSERT(analysis.fCoveragePOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isLCDCoverage());
SkASSERT(!analysis.isOutputColorOpaque());
SkASSERT(analysis.hasKnownOutputColor());
SkASSERT(!analysis.hasCoverage());
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
@ -608,13 +606,13 @@ static void test_color_unknown_no_coverage(skiatest::Reporter* reporter, const G
}
static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysis analysis;
analysis.fColorPOI.reset(GrPipelineInput(GrPipelineInput::Opaque::kYes));
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineInput::Opaque::kYes,
GrPipelineInput(), caps);
SkASSERT(analysis.fColorPOI.isOpaque());
SkASSERT(!analysis.fColorPOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isLCDCoverage());
SkASSERT(analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(analysis.hasCoverage());
SkASSERT(!analysis.hasLCDCoverage());
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
@ -782,14 +780,12 @@ static void test_color_opaque_with_coverage(skiatest::Reporter* reporter, const
}
static void test_color_opaque_no_coverage(skiatest::Reporter* reporter, const GrCaps& caps) {
GrPipelineAnalysis analysis;
analysis.fColorPOI.reset(GrPipelineInput(GrPipelineInput::Opaque::kYes));
analysis.fCoveragePOI.reset(GrPipelineInput(GrColorPackA4(255)));
GrProcessorSet::FragmentProcessorAnalysis analysis(GrPipelineInput::Opaque::kYes,
GrColorPackA4(255), caps);
SkASSERT(analysis.fColorPOI.isOpaque());
SkASSERT(!analysis.fColorPOI.isSolidWhite());
SkASSERT(analysis.fCoveragePOI.isSolidWhite());
SkASSERT(!analysis.fCoveragePOI.isLCDCoverage());
SkASSERT(analysis.isOutputColorOpaque());
SkASSERT(!analysis.hasKnownOutputColor());
SkASSERT(!analysis.hasCoverage());
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
@ -967,9 +963,10 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
const char* name() const override { return "Test LCD Text Op"; }
private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToConstant(GrColorPackRGBA(123, 45, 67, 221));
input->pipelineCoverageInput()->setToLCDCoverage();
void getFragmentProcessorAnalysisInputs(
FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToConstant(GrColorPackRGBA(123, 45, 67, 221));
input->coverageInput()->setToLCDCoverage();
}
void applyPipelineOptimizations(const GrPipelineOptimizations&) override {}
@ -979,19 +976,15 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
typedef GrMeshDrawOp INHERITED;
} testLCDCoverageOp;
GrPipelineAnalysis analysis;
testLCDCoverageOp.initPipelineAnalysis(&analysis);
GrProcOptInfo colorPOI = analysis.fColorPOI;
GrProcOptInfo covPOI = analysis.fCoveragePOI;
// Prevent unused var warnings in release.
(void)colorPOI;
(void)covPOI;
GrProcessorSet::FragmentProcessorAnalysis analysis;
GrAppliedClip clip(SkRect::MakeLargest());
testLCDCoverageOp.analyzeProcessors(&analysis, GrProcessorSet(GrPaint()), clip, caps);
SkASSERT(colorPOI.hasKnownOutputColor());
SkASSERT(covPOI.isLCDCoverage());
SkASSERT(analysis.hasKnownOutputColor());
SkASSERT(analysis.hasLCDCoverage());
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver);
TEST_ASSERT(!xpf->willNeedDstTexture(caps, analysis));
TEST_ASSERT(!GrXPFactory::WillNeedDstTexture(xpf, caps, analysis));
sk_sp<GrXferProcessor> xp(xpf->createXferProcessor(analysis, false, nullptr, caps));
if (!xp) {
@ -999,7 +992,7 @@ static void test_lcd_coverage_fallback_case(skiatest::Reporter* reporter, const
return;
}
TEST_ASSERT(GrXPFactory::WillReadDst(xpf, colorPOI, covPOI));
TEST_ASSERT(GrXPFactory::WillReadDst(xpf, analysis));
GrColor overrideColor;
xp->getOptimizations(analysis, false, &overrideColor, caps);
@ -1041,17 +1034,20 @@ DEF_GPUTEST(PorterDuffNoDualSourceBlending, reporter, /*factory*/) {
GrPipelineInput(GrColorPackRGBA(0, 82, 17, 255))};
for (const auto& colorInput : colorInputs) {
GrPipelineAnalysis analysis;
analysis.fColorPOI = colorInput;
GrProcessorSet::FragmentProcessorAnalysis analysis;
for (bool fractionalCoverage : {true, false}) {
if (!fractionalCoverage) {
analysis.fCoveragePOI.reset(GrPipelineInput(GrColorPackA4(255)));
if (fractionalCoverage) {
analysis = GrProcessorSet::FragmentProcessorAnalysis(colorInput, GrPipelineInput(),
caps);
} else {
analysis = GrProcessorSet::FragmentProcessorAnalysis(colorInput, GrColorPackA4(255),
caps);
}
for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
SkBlendMode xfermode = static_cast<SkBlendMode>(m);
const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
GrXferProcessor::DstTexture* dstTexture =
xpf->willNeedDstTexture(caps, analysis) ? &fakeDstTexture : 0;
GrXPFactory::WillNeedDstTexture(xpf, caps, analysis) ? &fakeDstTexture : 0;
sk_sp<GrXferProcessor> xp(
xpf->createXferProcessor(analysis, false, dstTexture, caps));
if (!xp) {

View File

@ -40,9 +40,9 @@ private:
this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsZeroArea::kNo);
}
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setToUnknown();
input->pipelineCoverageInput()->setToUnknown();
void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
input->colorInput()->setToUnknown();
input->coverageInput()->setToUnknown();
}
void applyPipelineOptimizations(const GrPipelineOptimizations&) override {}