| /* |
| * 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 "GrColor.h" |
| #include "GrProcessor.h" |
| #include "GrShaderVar.h" |
| |
| /* |
| * 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 |
| */ |
| class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement { |
| public: |
| struct Attribute { |
| enum class InputRate : bool { |
| kPerVertex, |
| kPerInstance |
| }; |
| GrShaderVar asShaderVar() const { |
| return GrShaderVar(fName, GrVertexAttribTypeToSLType(fType), |
| GrShaderVar::kIn_TypeModifier); |
| } |
| bool isInitialized() const { return SkToBool(fName); } |
| Attribute() = default; |
| Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate) |
| : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {} |
| const char* fName = nullptr; |
| GrVertexAttribType fType; |
| int fOffsetInRecord; |
| InputRate fInputRate; |
| }; |
| |
| GrPrimitiveProcessor(ClassID classID) |
| : GrResourceIOProcessor(classID) {} |
| |
| int numAttribs() const { return fAttribs.count(); } |
| const Attribute& getAttrib(int index) const { return fAttribs[index]; } |
| |
| bool hasVertexAttribs() const { return SkToBool(fVertexStride); } |
| bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); } |
| |
| /** |
| * These return the strides of the vertex and instance buffers. Attributes are expected to be |
| * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord |
| * indicates an attribute's location in bytes relative to the first attribute. (These are padded |
| * to the nearest 4 bytes for performance reasons.) |
| * |
| * A common practice is to populate the buffer's memory using an implicit array of structs. In |
| * this case, it is best to assert: |
| * |
| * stride == sizeof(struct) and |
| * offsetof(struct, field[i]) == attrib[i].fOffsetInRecord |
| * |
| * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses. |
| */ |
| int getVertexStride() const { return fVertexStride; } |
| int getInstanceStride() const { return fInstanceStride; } |
| |
| // 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; |
| |
| bool willUsePrimitiveRestart() const { return fWillUsePrimitiveRestart; } |
| |
| /** |
| * 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; |
| |
| |
| /** 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; } |
| |
| /** |
| * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor(). |
| */ |
| virtual const char* getDestColorOverride() const { return nullptr; } |
| |
| virtual float getSampleShading() const { |
| return 0.0; |
| } |
| |
| protected: |
| /** |
| * Subclasses call these from their constructor to register vertex and instance attributes. |
| */ |
| const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) { |
| fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex}; |
| fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type))); |
| return fAttribs.back(); |
| } |
| const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) { |
| fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance}; |
| fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type))); |
| return fAttribs.back(); |
| } |
| |
| void setWillUsePrimitiveRestart() { fWillUsePrimitiveRestart = true; } |
| |
| private: |
| void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); } |
| void removeRefs() const override { GrResourceIOProcessor::removeRefs(); } |
| void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); } |
| void notifyRefCntIsZero() const final {} |
| virtual bool hasExplicitLocalCoords() const = 0; |
| |
| SkSTArray<8, Attribute> fAttribs; |
| int fVertexStride = 0; |
| int fInstanceStride = 0; |
| bool fWillUsePrimitiveRestart = false; |
| |
| typedef GrProcessor INHERITED; |
| }; |
| |
| #endif |