1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef QuadPerEdgeAA_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define QuadPerEdgeAA_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSamplerState.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrQuad.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrQuadUtils.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/TextureOp.h" 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 23*c8dee2aaSAndroid Build Coastguard Worker 24*c8dee2aaSAndroid Build Coastguard Worker class GrBackendFormat; 25*c8dee2aaSAndroid Build Coastguard Worker class GrBuffer; 26*c8dee2aaSAndroid Build Coastguard Worker class GrCaps; 27*c8dee2aaSAndroid Build Coastguard Worker class GrColorSpaceXform; 28*c8dee2aaSAndroid Build Coastguard Worker class GrGeometryProcessor; 29*c8dee2aaSAndroid Build Coastguard Worker class GrMeshDrawTarget; 30*c8dee2aaSAndroid Build Coastguard Worker class GrOpsRenderPass; 31*c8dee2aaSAndroid Build Coastguard Worker class SkArenaAlloc; 32*c8dee2aaSAndroid Build Coastguard Worker struct GrShaderCaps; 33*c8dee2aaSAndroid Build Coastguard Worker struct SkRect; 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu { 36*c8dee2aaSAndroid Build Coastguard Worker class Swizzle; 37*c8dee2aaSAndroid Build Coastguard Worker } 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::ganesh::QuadPerEdgeAA { 40*c8dee2aaSAndroid Build Coastguard Worker using Saturate = skgpu::ganesh::TextureOp::Saturate; 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker enum class CoverageMode { kNone, kWithPosition, kWithColor }; 43*c8dee2aaSAndroid Build Coastguard Worker enum class Subset : bool { kNo = false, kYes = true }; 44*c8dee2aaSAndroid Build Coastguard Worker enum class ColorType { kNone, kByte, kFloat, kLast = kFloat }; 45*c8dee2aaSAndroid Build Coastguard Worker static const int kColorTypeCount = static_cast<int>(ColorType::kLast) + 1; 46*c8dee2aaSAndroid Build Coastguard Worker 47*c8dee2aaSAndroid Build Coastguard Worker enum class IndexBufferOption { 48*c8dee2aaSAndroid Build Coastguard Worker kPictureFramed, // geometrically AA'd -> 8 verts/quad + an index buffer 49*c8dee2aaSAndroid Build Coastguard Worker kIndexedRects, // non-AA'd but indexed -> 4 verts/quad + an index buffer 50*c8dee2aaSAndroid Build Coastguard Worker kTriStrips, // non-AA'd -> 4 verts/quad but no index buffer 51*c8dee2aaSAndroid Build Coastguard Worker kLast = kTriStrips 52*c8dee2aaSAndroid Build Coastguard Worker }; 53*c8dee2aaSAndroid Build Coastguard Worker static const int kIndexBufferOptionCount = static_cast<int>(IndexBufferOption::kLast) + 1; 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads); 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker // Gets the minimum ColorType that can represent a color. 58*c8dee2aaSAndroid Build Coastguard Worker ColorType MinColorType(SkPMColor4f); 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker // Specifies the vertex configuration for an op that renders per-edge AA quads. The vertex 61*c8dee2aaSAndroid Build Coastguard Worker // order (when enabled) is device position, color, local position, subset, aa edge equations. 62*c8dee2aaSAndroid Build Coastguard Worker // This order matches the constructor argument order of VertexSpec and is the order that 63*c8dee2aaSAndroid Build Coastguard Worker // GPAttributes maintains. If hasLocalCoords is false, then the local quad type can be ignored. 64*c8dee2aaSAndroid Build Coastguard Worker struct VertexSpec { 65*c8dee2aaSAndroid Build Coastguard Worker public: VertexSpecVertexSpec66*c8dee2aaSAndroid Build Coastguard Worker VertexSpec() 67*c8dee2aaSAndroid Build Coastguard Worker : fDeviceQuadType(0) // kAxisAligned 68*c8dee2aaSAndroid Build Coastguard Worker , fLocalQuadType(0) // kAxisAligned 69*c8dee2aaSAndroid Build Coastguard Worker , fIndexBufferOption(0) // kPictureFramed 70*c8dee2aaSAndroid Build Coastguard Worker , fHasLocalCoords(false) 71*c8dee2aaSAndroid Build Coastguard Worker , fColorType(0) // kNone 72*c8dee2aaSAndroid Build Coastguard Worker , fHasSubset(false) 73*c8dee2aaSAndroid Build Coastguard Worker , fUsesCoverageAA(false) 74*c8dee2aaSAndroid Build Coastguard Worker , fCompatibleWithCoverageAsAlpha(false) 75*c8dee2aaSAndroid Build Coastguard Worker , fRequiresGeometrySubset(false) {} 76*c8dee2aaSAndroid Build Coastguard Worker VertexSpecVertexSpec77*c8dee2aaSAndroid Build Coastguard Worker VertexSpec(GrQuad::Type deviceQuadType, 78*c8dee2aaSAndroid Build Coastguard Worker ColorType colorType, 79*c8dee2aaSAndroid Build Coastguard Worker GrQuad::Type localQuadType, 80*c8dee2aaSAndroid Build Coastguard Worker bool hasLocalCoords, 81*c8dee2aaSAndroid Build Coastguard Worker Subset subset, 82*c8dee2aaSAndroid Build Coastguard Worker GrAAType aa, 83*c8dee2aaSAndroid Build Coastguard Worker bool coverageAsAlpha, 84*c8dee2aaSAndroid Build Coastguard Worker IndexBufferOption indexBufferOption) 85*c8dee2aaSAndroid Build Coastguard Worker : fDeviceQuadType(static_cast<unsigned>(deviceQuadType)) 86*c8dee2aaSAndroid Build Coastguard Worker , fLocalQuadType(static_cast<unsigned>(localQuadType)) 87*c8dee2aaSAndroid Build Coastguard Worker , fIndexBufferOption(static_cast<unsigned>(indexBufferOption)) 88*c8dee2aaSAndroid Build Coastguard Worker , fHasLocalCoords(hasLocalCoords) 89*c8dee2aaSAndroid Build Coastguard Worker , fColorType(static_cast<unsigned>(colorType)) 90*c8dee2aaSAndroid Build Coastguard Worker , fHasSubset(static_cast<unsigned>(subset)) 91*c8dee2aaSAndroid Build Coastguard Worker , fUsesCoverageAA(aa == GrAAType::kCoverage) 92*c8dee2aaSAndroid Build Coastguard Worker , fCompatibleWithCoverageAsAlpha(coverageAsAlpha) 93*c8dee2aaSAndroid Build Coastguard Worker , fRequiresGeometrySubset(aa == GrAAType::kCoverage && 94*c8dee2aaSAndroid Build Coastguard Worker deviceQuadType > GrQuad::Type::kRectilinear) {} 95*c8dee2aaSAndroid Build Coastguard Worker deviceQuadTypeVertexSpec96*c8dee2aaSAndroid Build Coastguard Worker GrQuad::Type deviceQuadType() const { return static_cast<GrQuad::Type>(fDeviceQuadType); } localQuadTypeVertexSpec97*c8dee2aaSAndroid Build Coastguard Worker GrQuad::Type localQuadType() const { return static_cast<GrQuad::Type>(fLocalQuadType); } indexBufferOptionVertexSpec98*c8dee2aaSAndroid Build Coastguard Worker IndexBufferOption indexBufferOption() const { 99*c8dee2aaSAndroid Build Coastguard Worker return static_cast<IndexBufferOption>(fIndexBufferOption); 100*c8dee2aaSAndroid Build Coastguard Worker } hasLocalCoordsVertexSpec101*c8dee2aaSAndroid Build Coastguard Worker bool hasLocalCoords() const { return fHasLocalCoords; } colorTypeVertexSpec102*c8dee2aaSAndroid Build Coastguard Worker ColorType colorType() const { return static_cast<ColorType>(fColorType); } hasVertexColorsVertexSpec103*c8dee2aaSAndroid Build Coastguard Worker bool hasVertexColors() const { return ColorType::kNone != this->colorType(); } hasSubsetVertexSpec104*c8dee2aaSAndroid Build Coastguard Worker bool hasSubset() const { return fHasSubset; } usesCoverageAAVertexSpec105*c8dee2aaSAndroid Build Coastguard Worker bool usesCoverageAA() const { return fUsesCoverageAA; } compatibleWithCoverageAsAlphaVertexSpec106*c8dee2aaSAndroid Build Coastguard Worker bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; } requiresGeometrySubsetVertexSpec107*c8dee2aaSAndroid Build Coastguard Worker bool requiresGeometrySubset() const { return fRequiresGeometrySubset; } 108*c8dee2aaSAndroid Build Coastguard Worker // Will always be 2 or 3 109*c8dee2aaSAndroid Build Coastguard Worker int deviceDimensionality() const; 110*c8dee2aaSAndroid Build Coastguard Worker // Will always be 0 if hasLocalCoords is false, otherwise will be 2 or 3 111*c8dee2aaSAndroid Build Coastguard Worker int localDimensionality() const; 112*c8dee2aaSAndroid Build Coastguard Worker verticesPerQuadVertexSpec113*c8dee2aaSAndroid Build Coastguard Worker int verticesPerQuad() const { return fUsesCoverageAA ? 8 : 4; } 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker CoverageMode coverageMode() const; 116*c8dee2aaSAndroid Build Coastguard Worker size_t vertexSize() const; 117*c8dee2aaSAndroid Build Coastguard Worker needsIndexBufferVertexSpec118*c8dee2aaSAndroid Build Coastguard Worker bool needsIndexBuffer() const { 119*c8dee2aaSAndroid Build Coastguard Worker return this->indexBufferOption() != IndexBufferOption::kTriStrips; 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker primitiveTypeVertexSpec122*c8dee2aaSAndroid Build Coastguard Worker GrPrimitiveType primitiveType() const { 123*c8dee2aaSAndroid Build Coastguard Worker switch (this->indexBufferOption()) { 124*c8dee2aaSAndroid Build Coastguard Worker case IndexBufferOption::kPictureFramed: 125*c8dee2aaSAndroid Build Coastguard Worker return GrPrimitiveType::kTriangles; 126*c8dee2aaSAndroid Build Coastguard Worker case IndexBufferOption::kIndexedRects: 127*c8dee2aaSAndroid Build Coastguard Worker return GrPrimitiveType::kTriangles; 128*c8dee2aaSAndroid Build Coastguard Worker case IndexBufferOption::kTriStrips: 129*c8dee2aaSAndroid Build Coastguard Worker return GrPrimitiveType::kTriangleStrip; 130*c8dee2aaSAndroid Build Coastguard Worker } 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE; 133*c8dee2aaSAndroid Build Coastguard Worker } 134*c8dee2aaSAndroid Build Coastguard Worker 135*c8dee2aaSAndroid Build Coastguard Worker private: 136*c8dee2aaSAndroid Build Coastguard Worker static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type doesn't fit in 2 bits"); 137*c8dee2aaSAndroid Build Coastguard Worker static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits"); 138*c8dee2aaSAndroid Build Coastguard Worker static_assert(kIndexBufferOptionCount <= 4, "IndexBufferOption doesn't fit in 2 bits"); 139*c8dee2aaSAndroid Build Coastguard Worker 140*c8dee2aaSAndroid Build Coastguard Worker unsigned fDeviceQuadType : 2; 141*c8dee2aaSAndroid Build Coastguard Worker unsigned fLocalQuadType : 2; 142*c8dee2aaSAndroid Build Coastguard Worker unsigned fIndexBufferOption : 2; 143*c8dee2aaSAndroid Build Coastguard Worker unsigned fHasLocalCoords : 1; 144*c8dee2aaSAndroid Build Coastguard Worker unsigned fColorType : 2; 145*c8dee2aaSAndroid Build Coastguard Worker unsigned fHasSubset : 1; 146*c8dee2aaSAndroid Build Coastguard Worker unsigned fUsesCoverageAA : 1; 147*c8dee2aaSAndroid Build Coastguard Worker unsigned fCompatibleWithCoverageAsAlpha : 1; 148*c8dee2aaSAndroid Build Coastguard Worker // The geometry subset serves to clip off pixels touched by quads with sharp corners that 149*c8dee2aaSAndroid Build Coastguard Worker // would otherwise exceed the miter limit for the AA-outset geometry. 150*c8dee2aaSAndroid Build Coastguard Worker unsigned fRequiresGeometrySubset : 1; 151*c8dee2aaSAndroid Build Coastguard Worker }; 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker // A Tessellator is responsible for processing a series of device+local GrQuads into a VBO, 154*c8dee2aaSAndroid Build Coastguard Worker // as specified by a VertexSpec. This vertex data can then be processed by a GP created with 155*c8dee2aaSAndroid Build Coastguard Worker // MakeProcessor and/or MakeTexturedProcessor. 156*c8dee2aaSAndroid Build Coastguard Worker class Tessellator { 157*c8dee2aaSAndroid Build Coastguard Worker public: 158*c8dee2aaSAndroid Build Coastguard Worker explicit Tessellator(const VertexSpec& spec, char* vertices); 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker // Calculates (as needed) inset and outset geometry for anti-aliasing, and appends all 161*c8dee2aaSAndroid Build Coastguard Worker // necessary position and vertex attributes required by this Tessellator's VertexSpec into 162*c8dee2aaSAndroid Build Coastguard Worker // the 'vertices' the Tessellator was called with. The insetting and outsetting may 163*c8dee2aaSAndroid Build Coastguard Worker // damage the provided GrQuads (as this is intended to work with GrQuadBuffer::Iter). 164*c8dee2aaSAndroid Build Coastguard Worker // 'localQuad' can be null if the VertexSpec does not use local coords. 165*c8dee2aaSAndroid Build Coastguard Worker void append(GrQuad* deviceQuad, GrQuad* localQuad, 166*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor4f& color, const SkRect& uvSubset, GrQuadAAFlags aaFlags); 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(skgpu::BufferWriter::Mark vertexMark() const { return fVertexWriter.mark(); }) 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker private: 171*c8dee2aaSAndroid Build Coastguard Worker // VertexSpec defines many unique ways to write vertex attributes, which can be handled 172*c8dee2aaSAndroid Build Coastguard Worker // generically by branching per-quad based on the VertexSpec. However, there are several 173*c8dee2aaSAndroid Build Coastguard Worker // specs that appear in the wild far more frequently, so they use explicit WriteQuadProcs 174*c8dee2aaSAndroid Build Coastguard Worker // that have no branches. 175*c8dee2aaSAndroid Build Coastguard Worker typedef void (*WriteQuadProc)(VertexWriter* vertices, const VertexSpec& spec, 176*c8dee2aaSAndroid Build Coastguard Worker const GrQuad* deviceQuad, const GrQuad* localQuad, 177*c8dee2aaSAndroid Build Coastguard Worker const float coverage[4], const SkPMColor4f& color, 178*c8dee2aaSAndroid Build Coastguard Worker const SkRect& geomSubset, const SkRect& texSubset); 179*c8dee2aaSAndroid Build Coastguard Worker static WriteQuadProc GetWriteQuadProc(const VertexSpec& spec); 180*c8dee2aaSAndroid Build Coastguard Worker 181*c8dee2aaSAndroid Build Coastguard Worker GrQuadUtils::TessellationHelper fAAHelper; 182*c8dee2aaSAndroid Build Coastguard Worker VertexSpec fVertexSpec; 183*c8dee2aaSAndroid Build Coastguard Worker VertexWriter fVertexWriter; 184*c8dee2aaSAndroid Build Coastguard Worker WriteQuadProc fWriteProc; 185*c8dee2aaSAndroid Build Coastguard Worker }; 186*c8dee2aaSAndroid Build Coastguard Worker 187*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* MakeProcessor(SkArenaAlloc*, const VertexSpec&); 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* MakeTexturedProcessor(SkArenaAlloc*, 190*c8dee2aaSAndroid Build Coastguard Worker const VertexSpec&, 191*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps&, 192*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat&, 193*c8dee2aaSAndroid Build Coastguard Worker GrSamplerState, 194*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle&, 195*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrColorSpaceXform> textureColorSpaceXform, 196*c8dee2aaSAndroid Build Coastguard Worker Saturate); 197*c8dee2aaSAndroid Build Coastguard Worker 198*c8dee2aaSAndroid Build Coastguard Worker // This method will return the correct index buffer for the specified indexBufferOption. 199*c8dee2aaSAndroid Build Coastguard Worker // It will, correctly, return nullptr if the indexBufferOption is kTriStrips. 200*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawTarget*, IndexBufferOption); 201*c8dee2aaSAndroid Build Coastguard Worker 202*c8dee2aaSAndroid Build Coastguard Worker // What is the maximum number of quads allowed for the specified indexBuffer option? 203*c8dee2aaSAndroid Build Coastguard Worker int QuadLimit(IndexBufferOption); 204*c8dee2aaSAndroid Build Coastguard Worker 205*c8dee2aaSAndroid Build Coastguard Worker // This method will issue the draw call on the provided GrOpsRenderPass, as specified by the 206*c8dee2aaSAndroid Build Coastguard Worker // indexing method in vertexSpec. It is up to the calling code to allocate, fill in, and bind a 207*c8dee2aaSAndroid Build Coastguard Worker // vertex buffer, and to acquire and bind the correct index buffer (if needed) with 208*c8dee2aaSAndroid Build Coastguard Worker // GrPrimitiveRestart::kNo. 209*c8dee2aaSAndroid Build Coastguard Worker // 210*c8dee2aaSAndroid Build Coastguard Worker // @param runningQuadCount the number of quads already stored in 'vertexBuffer' and 211*c8dee2aaSAndroid Build Coastguard Worker // 'indexBuffer' e.g., different GrMeshes have already been placed in 212*c8dee2aaSAndroid Build Coastguard Worker // the buffers to allow dynamic state changes. 213*c8dee2aaSAndroid Build Coastguard Worker // @param quadCount the number of quads that will be drawn by the provided 'mesh'. 214*c8dee2aaSAndroid Build Coastguard Worker // A subsequent ConfigureMesh call would the use 215*c8dee2aaSAndroid Build Coastguard Worker // 'runningQuadCount' + 'quadCount' for its new 'runningQuadCount'. 216*c8dee2aaSAndroid Build Coastguard Worker void IssueDraw(const GrCaps&, GrOpsRenderPass*, const VertexSpec&, int runningQuadCount, 217*c8dee2aaSAndroid Build Coastguard Worker int quadCount, int maxVerts, int absVertBufferOffset); 218*c8dee2aaSAndroid Build Coastguard Worker 219*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::ganesh::QuadPerEdgeAA 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker #endif // QuadPerEdgeAA_DEFINED 222