blob: 1ba92ca580cf3c589b27cef300c6e5aa6b1f274c [file] [log] [blame]
Michael Ludwig460eb5e2018-10-29 11:09:29 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrQuadPerEdgeAA_DEFINED
9#define GrQuadPerEdgeAA_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkPoint.h"
12#include "include/core/SkPoint3.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/private/GrTypesPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040014#include "src/gpu/GrColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrGeometryProcessor.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040016#include "src/gpu/GrSamplerState.h"
Michael Ludwigfd4f4df2019-05-29 09:51:09 -040017#include "src/gpu/geometry/GrQuad.h"
Michael Ludwig73dbea62019-11-19 14:55:36 -050018#include "src/gpu/geometry/GrQuadUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/ops/GrMeshDrawOp.h"
Brian Salomonf19f9ca2019-09-18 15:54:26 -040020#include "src/gpu/ops/GrTextureOp.h"
Michael Ludwig460eb5e2018-10-29 11:09:29 -040021
Brian Osman8fa7ab42019-03-18 10:22:42 -040022class GrCaps;
Michael Ludwig467994d2018-12-03 14:58:31 +000023class GrColorSpaceXform;
24class GrShaderCaps;
Michael Ludwig73dbea62019-11-19 14:55:36 -050025struct GrVertexWriter;
Michael Ludwig460eb5e2018-10-29 11:09:29 -040026
Michael Ludwigc182b942018-11-16 10:27:51 -050027namespace GrQuadPerEdgeAA {
Brian Salomonf19f9ca2019-09-18 15:54:26 -040028 using Saturate = GrTextureOp::Saturate;
Michael Ludwigc182b942018-11-16 10:27:51 -050029
Robert Phillips29f38542019-10-16 09:20:25 -040030 enum class CoverageMode { kNone, kWithPosition, kWithColor };
Michael Ludwig460eb5e2018-10-29 11:09:29 -040031 enum class Domain : bool { kNo = false, kYes = true };
Brian Osman3d139a42018-11-19 10:42:10 -050032 enum class ColorType { kNone, kByte, kHalf, kLast = kHalf };
33 static const int kColorTypeCount = static_cast<int>(ColorType::kLast) + 1;
Michael Ludwig460eb5e2018-10-29 11:09:29 -040034
Robert Phillipsc554dcf2019-10-28 11:43:55 -040035 enum class IndexBufferOption {
36 kPictureFramed, // geometrically AA'd -> 8 verts/quad + an index buffer
37 kIndexedRects, // non-AA'd but indexed -> 4 verts/quad + an index buffer
38 kTriStrips, // non-AA'd -> 4 verts/quad but no index buffer
39 kLast = kTriStrips
40 };
41 static const int kIndexBufferOptionCount = static_cast<int>(IndexBufferOption::kLast) + 1;
42
43 IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads);
44
Brian Salomon1d835422019-03-13 16:11:44 -040045 // Gets the minimum ColorType that can represent a color.
Brian Osman8fa7ab42019-03-18 10:22:42 -040046 ColorType MinColorType(SkPMColor4f, GrClampType, const GrCaps&);
Brian Salomon1d835422019-03-13 16:11:44 -040047
Michael Ludwigc182b942018-11-16 10:27:51 -050048 // Specifies the vertex configuration for an op that renders per-edge AA quads. The vertex
49 // order (when enabled) is device position, color, local position, domain, aa edge equations.
50 // This order matches the constructor argument order of VertexSpec and is the order that
51 // GPAttributes maintains. If hasLocalCoords is false, then the local quad type can be ignored.
52 struct VertexSpec {
53 public:
Robert Phillips32803ff2019-10-23 08:26:08 -040054 VertexSpec()
55 : fDeviceQuadType(0) // kAxisAligned
56 , fLocalQuadType(0) // kAxisAligned
Robert Phillipsc554dcf2019-10-28 11:43:55 -040057 , fIndexBufferOption(0) // kPictureFramed
Robert Phillips32803ff2019-10-23 08:26:08 -040058 , fHasLocalCoords(false)
59 , fColorType(0) // kNone
60 , fHasDomain(false)
61 , fUsesCoverageAA(false)
62 , fCompatibleWithCoverageAsAlpha(false)
Robert Phillipsc554dcf2019-10-28 11:43:55 -040063 , fRequiresGeometryDomain(false) {}
Robert Phillips32803ff2019-10-23 08:26:08 -040064
Michael Ludwigde4c58c2019-06-04 09:12:59 -040065 VertexSpec(GrQuad::Type deviceQuadType, ColorType colorType, GrQuad::Type localQuadType,
Robert Phillipsc554dcf2019-10-28 11:43:55 -040066 bool hasLocalCoords, Domain domain, GrAAType aa, bool coverageAsAlpha,
67 IndexBufferOption indexBufferOption)
Michael Ludwigc182b942018-11-16 10:27:51 -050068 : fDeviceQuadType(static_cast<unsigned>(deviceQuadType))
69 , fLocalQuadType(static_cast<unsigned>(localQuadType))
Robert Phillipsc554dcf2019-10-28 11:43:55 -040070 , fIndexBufferOption(static_cast<unsigned>(indexBufferOption))
Michael Ludwigc182b942018-11-16 10:27:51 -050071 , fHasLocalCoords(hasLocalCoords)
Brian Osman3d139a42018-11-19 10:42:10 -050072 , fColorType(static_cast<unsigned>(colorType))
Michael Ludwigc182b942018-11-16 10:27:51 -050073 , fHasDomain(static_cast<unsigned>(domain))
Michael Ludwig93aeba02018-12-21 09:50:31 -050074 , fUsesCoverageAA(aa == GrAAType::kCoverage)
Michael Ludwigdcfbe322019-04-01 14:55:54 -040075 , fCompatibleWithCoverageAsAlpha(coverageAsAlpha)
76 , fRequiresGeometryDomain(aa == GrAAType::kCoverage &&
Michael Ludwigde4c58c2019-06-04 09:12:59 -040077 deviceQuadType > GrQuad::Type::kRectilinear) { }
Michael Ludwig460eb5e2018-10-29 11:09:29 -040078
Michael Ludwigde4c58c2019-06-04 09:12:59 -040079 GrQuad::Type deviceQuadType() const { return static_cast<GrQuad::Type>(fDeviceQuadType); }
80 GrQuad::Type localQuadType() const { return static_cast<GrQuad::Type>(fLocalQuadType); }
Robert Phillipsc554dcf2019-10-28 11:43:55 -040081 IndexBufferOption indexBufferOption() const {
82 return static_cast<IndexBufferOption>(fIndexBufferOption);
83 }
Michael Ludwigc182b942018-11-16 10:27:51 -050084 bool hasLocalCoords() const { return fHasLocalCoords; }
Brian Osman3d139a42018-11-19 10:42:10 -050085 ColorType colorType() const { return static_cast<ColorType>(fColorType); }
86 bool hasVertexColors() const { return ColorType::kNone != this->colorType(); }
Michael Ludwigc182b942018-11-16 10:27:51 -050087 bool hasDomain() const { return fHasDomain; }
88 bool usesCoverageAA() const { return fUsesCoverageAA; }
Brian Osman605c6d52019-03-15 12:10:35 -040089 bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
Michael Ludwigdcfbe322019-04-01 14:55:54 -040090 bool requiresGeometryDomain() const { return fRequiresGeometryDomain; }
Michael Ludwigc182b942018-11-16 10:27:51 -050091 // Will always be 2 or 3
92 int deviceDimensionality() const;
93 // Will always be 0 if hasLocalCoords is false, otherwise will be 2 or 3
94 int localDimensionality() const;
Michael Ludwig460eb5e2018-10-29 11:09:29 -040095
Michael Ludwig93aeba02018-12-21 09:50:31 -050096 int verticesPerQuad() const { return fUsesCoverageAA ? 8 : 4; }
Robert Phillips29f38542019-10-16 09:20:25 -040097
98 CoverageMode coverageMode() const;
99 size_t vertexSize() const;
100
Robert Phillipsfd0c3b52019-11-01 08:44:42 -0400101 bool needsIndexBuffer() const { return this->indexBufferOption() !=
102 IndexBufferOption::kTriStrips; }
103
Robert Phillipscea290f2019-11-06 11:21:03 -0500104 GrPrimitiveType primitiveType() const {
105 switch (this->indexBufferOption()) {
106 case IndexBufferOption::kPictureFramed: return GrPrimitiveType::kTriangles;
107 case IndexBufferOption::kIndexedRects: return GrPrimitiveType::kTriangles;
108 case IndexBufferOption::kTriStrips: return GrPrimitiveType::kTriangleStrip;
109 }
110
111 SkUNREACHABLE;
112 }
113
Michael Ludwigc182b942018-11-16 10:27:51 -0500114 private:
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400115 static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type doesn't fit in 2 bits");
Brian Osman3d139a42018-11-19 10:42:10 -0500116 static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits");
Robert Phillipsc554dcf2019-10-28 11:43:55 -0400117 static_assert(kIndexBufferOptionCount <= 4, "IndexBufferOption doesn't fit in 2 bits");
Michael Ludwig460eb5e2018-10-29 11:09:29 -0400118
Michael Ludwigc182b942018-11-16 10:27:51 -0500119 unsigned fDeviceQuadType: 2;
120 unsigned fLocalQuadType: 2;
Robert Phillipsc554dcf2019-10-28 11:43:55 -0400121 unsigned fIndexBufferOption: 2;
Michael Ludwigc182b942018-11-16 10:27:51 -0500122 unsigned fHasLocalCoords: 1;
Brian Osman3d139a42018-11-19 10:42:10 -0500123 unsigned fColorType : 2;
Michael Ludwigc182b942018-11-16 10:27:51 -0500124 unsigned fHasDomain: 1;
125 unsigned fUsesCoverageAA: 1;
Brian Osman605c6d52019-03-15 12:10:35 -0400126 unsigned fCompatibleWithCoverageAsAlpha: 1;
Michael Ludwigdcfbe322019-04-01 14:55:54 -0400127 // The geometry domain serves to clip off pixels touched by quads with sharp corners that
128 // would otherwise exceed the miter limit for the AA-outset geometry.
129 unsigned fRequiresGeometryDomain: 1;
Michael Ludwig460eb5e2018-10-29 11:09:29 -0400130 };
131
Michael Ludwig73dbea62019-11-19 14:55:36 -0500132 // A Tessellator is responsible for processing a series of device+local GrQuads into a VBO,
133 // as specified by a VertexSpec. This vertex data can then be processed by a GP created with
134 // MakeProcessor and/or MakeTexturedProcessor.
135 class Tessellator {
136 public:
137 explicit Tessellator(const VertexSpec& spec);
138
139 // Calculates (as needed) inset and outset geometry for anti-aliasing, and writes all
140 // necessary position and vertex attributes required by this Tessellator's VertexSpec.
141 // After appending, this will return the pointer to the next vertex in the VBO.
142 void* append(void* vertices, const GrQuad& deviceQuad, const GrQuad& localQuad,
143 const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags);
144
145 private:
146 // VertexSpec defines many unique ways to write vertex attributes, which can be handled
147 // generically by branching per-quad based on the VertexSpec. However, there are several
148 // specs that appear in the wild far more frequently, so they use explicit WriteQuadProcs
149 // that have no branches.
150 typedef void (*WriteQuadProc)(GrVertexWriter* vertices, const VertexSpec& spec,
151 const GrQuad& deviceQuad, const GrQuad& localQuad,
152 const float coverage[4], const SkPMColor4f& color,
153 const SkRect& geomDomain, const SkRect& texDomain);
154 static WriteQuadProc GetWriteQuadProc(const VertexSpec& spec);
155
156 GrQuadUtils::TessellationHelper fAAHelper;
157 VertexSpec fVertexSpec;
158 WriteQuadProc fWriteProc;
159 };
160
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500161 GrGeometryProcessor* MakeProcessor(SkArenaAlloc*, const VertexSpec&);
Michael Ludwig20e909e2018-10-30 10:43:57 -0400162
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500163 GrGeometryProcessor* MakeTexturedProcessor(
164 SkArenaAlloc*, const VertexSpec&, const GrShaderCaps&, const GrBackendFormat&,
165 const GrSamplerState&, const GrSwizzle&,
166 sk_sp<GrColorSpaceXform> textureColorSpaceXform, Saturate);
Michael Ludwig20e909e2018-10-30 10:43:57 -0400167
Robert Phillipsfd0c3b52019-11-01 08:44:42 -0400168 // This method will return the correct index buffer for the specified indexBufferOption.
169 // It will, correctly, return nullptr if the indexBufferOption is kTriStrips.
170 sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target*, IndexBufferOption);
171
Robert Phillips438d9862019-11-14 12:46:05 -0500172 // What is the maximum number of quads allowed for the specified indexBuffer option?
173 int QuadLimit(IndexBufferOption);
174
Robert Phillipsfd0c3b52019-11-01 08:44:42 -0400175 // This method will configure the vertex and index data of the provided 'mesh' to comply
176 // with the indexing method specified in the vertexSpec. It is up to the calling code
177 // to allocate and fill in the vertex data and acquire the correct indexBuffer if it is needed.
Michael Ludwig93aeba02018-12-21 09:50:31 -0500178 //
Robert Phillipsfd0c3b52019-11-01 08:44:42 -0400179 // @param runningQuadCount the number of quads already stored in 'vertexBuffer' and
180 // 'indexBuffer' e.g., different GrMeshes have already been placed in
181 // the buffers to allow dynamic state changes.
182 // @param quadCount the number of quads that will be drawn by the provided 'mesh'.
183 // A subsequent ConfigureMesh call would the use
184 // 'runningQuadCount' + 'quadCount' for its new 'runningQuadCount'.
185 void ConfigureMesh(GrMesh* mesh, const VertexSpec&, int runningQuadCount, int quadCount,
186 int maxVerts, sk_sp<const GrBuffer> vertexBuffer,
187 sk_sp<const GrBuffer> indexBuffer, int absVertBufferOffset);
Michael Ludwig93aeba02018-12-21 09:50:31 -0500188
Michael Ludwigc182b942018-11-16 10:27:51 -0500189} // namespace GrQuadPerEdgeAA
Michael Ludwig460eb5e2018-10-29 11:09:29 -0400190
191#endif // GrQuadPerEdgeAA_DEFINED