blob: 072d2388c9b8cdb8d33d3399c380fb589b5bba65 [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrProcessorSet_DEFINED
#define GrProcessorSet_DEFINED
#include "GrFragmentProcessor.h"
#include "GrPaint.h"
#include "GrProcessorAnalysis.h"
#include "SkTemplates.h"
class GrAppliedClip;
class GrXferProcessor;
class GrXPFactory;
class GrProcessorSet : private SkNoncopyable {
public:
GrProcessorSet(GrPaint&& paint);
~GrProcessorSet();
int numColorFragmentProcessors() const { return fColorFragmentProcessorCnt; }
int numCoverageFragmentProcessors() const {
return this->numFragmentProcessors() - fColorFragmentProcessorCnt;
}
int numFragmentProcessors() const {
return fFragmentProcessors.count() - fFragmentProcessorOffset;
}
const GrFragmentProcessor* colorFragmentProcessor(int idx) const {
SkASSERT(idx < fColorFragmentProcessorCnt);
return fFragmentProcessors[idx + fFragmentProcessorOffset];
}
const GrFragmentProcessor* coverageFragmentProcessor(int idx) const {
return fFragmentProcessors[idx + fColorFragmentProcessorCnt + fFragmentProcessorOffset];
}
const GrXferProcessor* xferProcessor() const {
SkASSERT(this->isFinalized());
return fXP.fProcessor;
}
bool usesDistanceVectorField() const { return SkToBool(fFlags & kUseDistanceVectorField_Flag); }
bool disableOutputConversionToSRGB() const {
return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag);
}
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
/** Comparisons are only legal on finalized processor sets. */
bool operator==(const GrProcessorSet& that) const;
bool operator!=(const GrProcessorSet& that) const { return !(*this == that); }
/**
* This is used to report results of processor analysis when a processor set is finalized (see
* below).
*/
class Analysis {
public:
Analysis(const Analysis&) = default;
Analysis() { *reinterpret_cast<uint32_t*>(this) = 0; }
bool isInitialized() const { return fIsInitialized; }
bool usesLocalCoords() const { return fUsesLocalCoords; }
bool requiresDstTexture() const { return fRequiresDstTexture; }
bool canCombineOverlappedStencilAndCover() const {
return fCanCombineOverlappedStencilAndCover;
}
bool requiresBarrierBetweenOverlappingDraws() const {
return fRequiresBarrierBetweenOverlappingDraws;
}
bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
bool inputColorIsIgnored() const { return fInputColorType == kIgnored_InputColorType; }
bool inputColorIsOverridden() const {
return fInputColorType == kOverridden_InputColorType;
}
private:
enum InputColorType : uint32_t {
kOriginal_InputColorType,
kOverridden_InputColorType,
kIgnored_InputColorType
};
// MSVS 2015 won't pack different underlying types
using PackedBool = uint32_t;
using PackedInputColorType = uint32_t;
PackedBool fUsesLocalCoords : 1;
PackedBool fCompatibleWithCoverageAsAlpha : 1;
PackedBool fRequiresDstTexture : 1;
PackedBool fCanCombineOverlappedStencilAndCover : 1;
PackedBool fRequiresBarrierBetweenOverlappingDraws : 1;
PackedBool fIsInitialized : 1;
PackedInputColorType fInputColorType : 2;
friend class GrProcessorSet;
};
GR_STATIC_ASSERT(sizeof(Analysis) <= sizeof(uint32_t));
/**
* This analyzes the processors given an op's input color and coverage as well as a clip. The
* state of the processor set may change to an equivalent but more optimal set of processors.
* This new state requires that the caller respect the returned 'inputColorOverride'. This is
* indicated by the returned Analysis's inputColorIsOverriden(). 'inputColorOverride' will not
* be written if the analysis does not override the input color.
*
* This must be called before the processor set is used to construct a GrPipeline and may only
* be called once.
*
* This also puts the processors in "pending execution" state and must be called when an op
* that owns a processor set is recorded to ensure pending and writes are propagated to
* resources referred to by the processors. Otherwise, data hazards may occur.
*/
Analysis finalize(const GrProcessorAnalysisColor& colorInput,
const GrProcessorAnalysisCoverage coverageInput, const GrAppliedClip*,
bool isMixedSamples, const GrCaps&, GrColor* inputColorOverride);
bool isFinalized() const { return SkToBool(kFinalized_Flag & fFlags); }
private:
// This absurdly large limit allows Analysis and this to pack fields together.
static constexpr int kMaxColorProcessors = UINT8_MAX;
enum Flags : uint16_t {
kUseDistanceVectorField_Flag = 0x1,
kDisableOutputConversionToSRGB_Flag = 0x2,
kAllowSRGBInputs_Flag = 0x4,
kFinalized_Flag = 0x8
};
union XP {
XP(const GrXPFactory* factory) : fFactory(factory) {}
const GrXPFactory* fFactory;
const GrXferProcessor* fProcessor;
};
const GrXPFactory* xpFactory() const {
SkASSERT(!this->isFinalized());
return fXP.fFactory;
}
SkAutoSTArray<4, const GrFragmentProcessor*> fFragmentProcessors;
XP fXP;
uint8_t fColorFragmentProcessorCnt;
uint8_t fFragmentProcessorOffset = 0;
uint8_t fFlags;
};
#endif