123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- /*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef GrPrimitiveProcessor_DEFINED
- #define GrPrimitiveProcessor_DEFINED
- #include "src/gpu/GrColor.h"
- #include "src/gpu/GrNonAtomicRef.h"
- #include "src/gpu/GrProcessor.h"
- #include "src/gpu/GrShaderVar.h"
- class GrCoordTransform;
- /*
- * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
- * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
- * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
- * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
- * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
- * functionality.
- *
- * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
- * 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
- * getProcessorAnalysisInputs 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.
- */
- class GrGLSLPrimitiveProcessor;
- /**
- * GrPrimitiveProcessor defines an interface which all subclasses must implement. All
- * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
- * pipelines, and they must provide some notion of equality
- *
- * TODO: This class does not really need to be ref counted. Instances should be allocated using
- * GrOpFlushState's arena and destroyed when the arena is torn down.
- */
- class GrPrimitiveProcessor : public GrProcessor, public GrNonAtomicRef<GrPrimitiveProcessor> {
- public:
- class TextureSampler;
- /** Describes a vertex or instance attribute. */
- class Attribute {
- public:
- constexpr Attribute() = default;
- constexpr Attribute(const char* name,
- GrVertexAttribType cpuType,
- GrSLType gpuType)
- : fName(name), fCPUType(cpuType), fGPUType(gpuType) {}
- constexpr Attribute(const Attribute&) = default;
- Attribute& operator=(const Attribute&) = default;
- constexpr bool isInitialized() const { return SkToBool(fName); }
- constexpr const char* name() const { return fName; }
- constexpr GrVertexAttribType cpuType() const { return fCPUType; }
- constexpr GrSLType gpuType() const { return fGPUType; }
- inline constexpr size_t size() const;
- constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
- GrShaderVar asShaderVar() const {
- return {fName, fGPUType, GrShaderVar::kIn_TypeModifier};
- }
- private:
- const char* fName = nullptr;
- GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
- GrSLType fGPUType = kFloat_GrSLType;
- };
- class Iter {
- public:
- Iter() : fCurr(nullptr), fRemaining(0) {}
- Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {}
- Iter& operator= (const Iter& iter) {
- fCurr = iter.fCurr;
- fRemaining = iter.fRemaining;
- return *this;
- }
- Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) {
- this->skipUninitialized();
- }
- bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
- const Attribute& operator*() const { return *fCurr; }
- void operator++() {
- if (fRemaining) {
- fRemaining--;
- fCurr++;
- this->skipUninitialized();
- }
- }
- private:
- void skipUninitialized() {
- if (!fRemaining) {
- fCurr = nullptr;
- } else {
- while (!fCurr->isInitialized()) {
- ++fCurr;
- }
- }
- }
- const Attribute* fCurr;
- int fRemaining;
- };
- class AttributeSet {
- public:
- Iter begin() const { return Iter(fAttributes, fCount); }
- Iter end() const { return Iter(); }
- private:
- friend class GrPrimitiveProcessor;
- void init(const Attribute* attrs, int count) {
- fAttributes = attrs;
- fRawCount = count;
- fCount = 0;
- fStride = 0;
- for (int i = 0; i < count; ++i) {
- if (attrs[i].isInitialized()) {
- fCount++;
- fStride += attrs[i].sizeAlign4();
- }
- }
- }
- const Attribute* fAttributes = nullptr;
- int fRawCount = 0;
- int fCount = 0;
- size_t fStride = 0;
- };
- GrPrimitiveProcessor(ClassID);
- int numTextureSamplers() const { return fTextureSamplerCnt; }
- const TextureSampler& textureSampler(int index) const;
- int numVertexAttributes() const { return fVertexAttributes.fCount; }
- const AttributeSet& vertexAttributes() const { return fVertexAttributes; }
- int numInstanceAttributes() const { return fInstanceAttributes.fCount; }
- const AttributeSet& instanceAttributes() const { return fInstanceAttributes; }
- bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); }
- bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); }
- /**
- * A common practice is to populate the the vertex/instance's memory using an implicit array of
- * structs. In this case, it is best to assert that:
- * stride == sizeof(struct)
- */
- size_t vertexStride() const { return fVertexAttributes.fStride; }
- size_t instanceStride() const { return fInstanceAttributes.fStride; }
- // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
- // we put these calls on the base class to prevent having to cast
- virtual bool willUseGeoShader() const = 0;
- /**
- * Computes a transformKey from an array of coord transforms. Will only look at the first
- * <numCoords> transforms in the array.
- *
- * TODO: A better name for this function would be "compute" instead of "get".
- */
- uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords,
- int numCoords) const;
- /**
- * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
- * processor's GL backend implementation.
- *
- * TODO: A better name for this function would be "compute" instead of "get".
- */
- virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
- void getAttributeKey(GrProcessorKeyBuilder* b) const {
- // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never
- // collide with the "uninitialized" value.
- static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
- static_assert(kGrSLTypeCount < (1 << 8), "");
- auto add_attributes = [=](const Attribute* attrs, int attrCount) {
- for (int i = 0; i < attrCount; ++i) {
- b->add32(attrs[i].isInitialized() ? (attrs[i].cpuType() << 16) | attrs[i].gpuType()
- : ~0);
- }
- };
- add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount);
- add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount);
- }
- /** Returns a new instance of the appropriate *GL* implementation class
- for the given GrProcessor; caller is responsible for deleting
- the object. */
- virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
- virtual bool isPathRendering() const { return false; }
- protected:
- void setVertexAttributes(const Attribute* attrs, int attrCount) {
- fVertexAttributes.init(attrs, attrCount);
- }
- void setInstanceAttributes(const Attribute* attrs, int attrCount) {
- SkASSERT(attrCount >= 0);
- fInstanceAttributes.init(attrs, attrCount);
- }
- void setTextureSamplerCnt(int cnt) {
- SkASSERT(cnt >= 0);
- fTextureSamplerCnt = cnt;
- }
- /**
- * Helper for implementing onTextureSampler(). E.g.:
- * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
- */
- template <typename... Args>
- static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
- const Args&... samps) {
- return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
- }
- inline static const TextureSampler& IthTextureSampler(int i);
- private:
- virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
- AttributeSet fVertexAttributes;
- AttributeSet fInstanceAttributes;
- int fTextureSamplerCnt = 0;
- typedef GrProcessor INHERITED;
- };
- //////////////////////////////////////////////////////////////////////////////
- /**
- * Used to represent a texture that is required by a GrPrimitiveProcessor. It holds a GrTextureProxy
- * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to
- * account for texture origin.
- */
- class GrPrimitiveProcessor::TextureSampler {
- public:
- TextureSampler() = default;
- TextureSampler(GrTextureType, GrPixelConfig, const GrSamplerState&, const GrSwizzle&,
- uint32_t extraSamplerKey);
- explicit TextureSampler(GrTextureType, GrPixelConfig, GrSamplerState::Filter,
- GrSamplerState::WrapMode wrapXAndY, const GrSwizzle&);
- TextureSampler(const TextureSampler&) = delete;
- TextureSampler& operator=(const TextureSampler&) = delete;
- void reset(GrTextureType, GrPixelConfig, const GrSamplerState&, const GrSwizzle&,
- uint32_t extraSamplerKey = 0);
- void reset(GrTextureType, GrPixelConfig,
- GrSamplerState::Filter,
- GrSamplerState::WrapMode wrapXAndY,
- const GrSwizzle& swizzle);
- GrTextureType textureType() const { return fTextureType; }
- GrPixelConfig config() const { return fConfig; }
- const GrSamplerState& samplerState() const { return fSamplerState; }
- const GrSwizzle& swizzle() const { return fSwizzle; }
- uint32_t extraSamplerKey() const { return fExtraSamplerKey; }
- bool isInitialized() const { return fConfig != kUnknown_GrPixelConfig; }
- private:
- GrSamplerState fSamplerState;
- GrSwizzle fSwizzle;
- GrTextureType fTextureType = GrTextureType::k2D;
- GrPixelConfig fConfig = kUnknown_GrPixelConfig;
- uint32_t fExtraSamplerKey = 0;
- };
- const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::IthTextureSampler(int i) {
- SK_ABORT("Illegal texture sampler index");
- static const TextureSampler kBogus;
- return kBogus;
- }
- //////////////////////////////////////////////////////////////////////////////
- /**
- * Returns the size of the attrib type in bytes.
- * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build
- * with C++11.
- */
- static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
- switch (type) {
- case kFloat_GrVertexAttribType:
- return sizeof(float);
- case kFloat2_GrVertexAttribType:
- return 2 * sizeof(float);
- case kFloat3_GrVertexAttribType:
- return 3 * sizeof(float);
- case kFloat4_GrVertexAttribType:
- return 4 * sizeof(float);
- case kHalf_GrVertexAttribType:
- return sizeof(uint16_t);
- case kHalf2_GrVertexAttribType:
- return 2 * sizeof(uint16_t);
- case kHalf3_GrVertexAttribType:
- return 3 * sizeof(uint16_t);
- case kHalf4_GrVertexAttribType:
- return 4 * sizeof(uint16_t);
- case kInt2_GrVertexAttribType:
- return 2 * sizeof(int32_t);
- case kInt3_GrVertexAttribType:
- return 3 * sizeof(int32_t);
- case kInt4_GrVertexAttribType:
- return 4 * sizeof(int32_t);
- case kByte_GrVertexAttribType:
- return 1 * sizeof(char);
- case kByte2_GrVertexAttribType:
- return 2 * sizeof(char);
- case kByte3_GrVertexAttribType:
- return 3 * sizeof(char);
- case kByte4_GrVertexAttribType:
- return 4 * sizeof(char);
- case kUByte_GrVertexAttribType:
- return 1 * sizeof(char);
- case kUByte2_GrVertexAttribType:
- return 2 * sizeof(char);
- case kUByte3_GrVertexAttribType:
- return 3 * sizeof(char);
- case kUByte4_GrVertexAttribType:
- return 4 * sizeof(char);
- case kUByte_norm_GrVertexAttribType:
- return 1 * sizeof(char);
- case kUByte4_norm_GrVertexAttribType:
- return 4 * sizeof(char);
- case kShort2_GrVertexAttribType:
- return 2 * sizeof(int16_t);
- case kShort4_GrVertexAttribType:
- return 4 * sizeof(int16_t);
- case kUShort2_GrVertexAttribType: // fall through
- case kUShort2_norm_GrVertexAttribType:
- return 2 * sizeof(uint16_t);
- case kInt_GrVertexAttribType:
- return sizeof(int32_t);
- case kUint_GrVertexAttribType:
- return sizeof(uint32_t);
- case kUShort_norm_GrVertexAttribType:
- return sizeof(uint16_t);
- // Experimental (for Y416)
- case kUShort4_norm_GrVertexAttribType:
- return 4 * sizeof(uint16_t);
- }
- // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is
- // unreachable and don't complain.
- #if defined(__clang__) || !defined(__GNUC__)
- SK_ABORT("Unsupported type conversion");
- #endif
- return 0;
- }
- constexpr size_t GrPrimitiveProcessor::Attribute::size() const {
- return GrVertexAttribTypeSize(fCPUType);
- }
- #endif
|