1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef tessellate_PatchWriter_DEFINED 9cb93a386Sopenharmony_ci#define tessellate_PatchWriter_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "src/gpu/GrVertexChunkArray.h" 12cb93a386Sopenharmony_ci#include "src/gpu/tessellate/MiddleOutPolygonTriangulator.h" 13cb93a386Sopenharmony_ci#include "src/gpu/tessellate/Tessellation.h" 14cb93a386Sopenharmony_ci#include "src/gpu/tessellate/shaders/GrTessellationShader.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cinamespace skgpu { 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#if SK_GPU_V1 19cb93a386Sopenharmony_ciclass PathTessellator; 20cb93a386Sopenharmony_ci#endif 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci// Writes out tessellation patches, formatted with their specific attribs, to a GPU buffer. 23cb93a386Sopenharmony_ciclass PatchWriter { 24cb93a386Sopenharmony_cipublic: 25cb93a386Sopenharmony_ci PatchWriter(GrMeshDrawTarget* target, 26cb93a386Sopenharmony_ci GrVertexChunkArray* vertexChunkArray, 27cb93a386Sopenharmony_ci PatchAttribs attribs, 28cb93a386Sopenharmony_ci size_t patchStride, 29cb93a386Sopenharmony_ci int initialAllocCount) 30cb93a386Sopenharmony_ci : fPatchAttribs(attribs) 31cb93a386Sopenharmony_ci , fChunker(target, vertexChunkArray, patchStride, initialAllocCount) { 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci#if SK_GPU_V1 35cb93a386Sopenharmony_ci // Creates a PatchWriter that writes directly to the GrVertexChunkArray stored on the provided 36cb93a386Sopenharmony_ci // PathTessellator. 37cb93a386Sopenharmony_ci PatchWriter(GrMeshDrawTarget*, PathTessellator* tessellator, int initialPatchAllocCount); 38cb93a386Sopenharmony_ci#endif 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci // Updates the fan point that will be written out with each patch (i.e., the point that wedges 41cb93a386Sopenharmony_ci // fan around). 42cb93a386Sopenharmony_ci // PathPatchAttrib::kFanPoint must be enabled. 43cb93a386Sopenharmony_ci void updateFanPointAttrib(SkPoint fanPoint) { 44cb93a386Sopenharmony_ci SkASSERT(fPatchAttribs & PatchAttribs::kFanPoint); 45cb93a386Sopenharmony_ci fFanPointAttrib = fanPoint; 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci // Updates the color that will be written out with each patch. 49cb93a386Sopenharmony_ci // PathPatchAttrib::kColor must be enabled. 50cb93a386Sopenharmony_ci void updateColorAttrib(const SkPMColor4f& color) { 51cb93a386Sopenharmony_ci SkASSERT(fPatchAttribs & PatchAttribs::kColor); 52cb93a386Sopenharmony_ci fColorAttrib.set(color, fPatchAttribs & PatchAttribs::kWideColorIfEnabled); 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci // RAII. Appends a patch during construction and writes the remaining data for a cubic during 56cb93a386Sopenharmony_ci // destruction. The caller outputs p0,p1,p2,p3 (8 floats): 57cb93a386Sopenharmony_ci // 58cb93a386Sopenharmony_ci // CubicPatch(patchWriter) << p0 << p1 << p2 << p3; 59cb93a386Sopenharmony_ci // 60cb93a386Sopenharmony_ci struct CubicPatch { 61cb93a386Sopenharmony_ci CubicPatch(PatchWriter& w) : fPatchWriter(w), fVertexWriter(w.appendPatch()) {} 62cb93a386Sopenharmony_ci ~CubicPatch() { 63cb93a386Sopenharmony_ci fPatchWriter.outputPatchAttribs(std::move(fVertexWriter), 64cb93a386Sopenharmony_ci GrTessellationShader::kCubicCurveType); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci operator VertexWriter&() { return fVertexWriter; } 67cb93a386Sopenharmony_ci PatchWriter& fPatchWriter; 68cb93a386Sopenharmony_ci VertexWriter fVertexWriter; 69cb93a386Sopenharmony_ci }; 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // RAII. Appends a patch during construction and writes the remaining data for a conic during 72cb93a386Sopenharmony_ci // destruction. The caller outputs p0,p1,p2,w (7 floats): 73cb93a386Sopenharmony_ci // 74cb93a386Sopenharmony_ci // ConicPatch(patchWriter) << p0 << p1 << p2 << w; 75cb93a386Sopenharmony_ci // 76cb93a386Sopenharmony_ci struct ConicPatch { 77cb93a386Sopenharmony_ci ConicPatch(PatchWriter& w) : fPatchWriter(w), fVertexWriter(w.appendPatch()) {} 78cb93a386Sopenharmony_ci ~ConicPatch() { 79cb93a386Sopenharmony_ci fVertexWriter << VertexWriter::kIEEE_32_infinity; // p3.y=Inf indicates a conic. 80cb93a386Sopenharmony_ci fPatchWriter.outputPatchAttribs(std::move(fVertexWriter), 81cb93a386Sopenharmony_ci GrTessellationShader::kConicCurveType); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci operator VertexWriter&() { return fVertexWriter; } 84cb93a386Sopenharmony_ci PatchWriter& fPatchWriter; 85cb93a386Sopenharmony_ci VertexWriter fVertexWriter; 86cb93a386Sopenharmony_ci }; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci // RAII. Appends a patch during construction and writes the remaining data for a triangle during 89cb93a386Sopenharmony_ci // destruction. The caller outputs p0,p1,p2 (6 floats): 90cb93a386Sopenharmony_ci // 91cb93a386Sopenharmony_ci // TrianglePatch(patchWriter) << p0 << p1 << p2; 92cb93a386Sopenharmony_ci // 93cb93a386Sopenharmony_ci struct TrianglePatch { 94cb93a386Sopenharmony_ci TrianglePatch(PatchWriter& w) : fPatchWriter(w), fVertexWriter(w.appendPatch()) {} 95cb93a386Sopenharmony_ci ~TrianglePatch() { 96cb93a386Sopenharmony_ci // Mark this patch as a triangle by setting it to a conic with w=Inf. 97cb93a386Sopenharmony_ci fVertexWriter.fill(VertexWriter::kIEEE_32_infinity, 2); 98cb93a386Sopenharmony_ci fPatchWriter.outputPatchAttribs(std::move(fVertexWriter), 99cb93a386Sopenharmony_ci GrTessellationShader::kTriangularConicCurveType); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci operator VertexWriter&() { return fVertexWriter; } 102cb93a386Sopenharmony_ci PatchWriter& fPatchWriter; 103cb93a386Sopenharmony_ci VertexWriter fVertexWriter; 104cb93a386Sopenharmony_ci }; 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci // Chops the given quadratic into 'numPatches' equal segments (in the parametric sense) and 107cb93a386Sopenharmony_ci // writes them to the GPU buffer. 108cb93a386Sopenharmony_ci // 109cb93a386Sopenharmony_ci // Fills space between chops with triangles if PathPatchAttrib::kFanPoint is not enabled. 110cb93a386Sopenharmony_ci void chopAndWriteQuads(float2 p0, float2 p1, float2 p2, int numPatches); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci // Chops the given conic into 'numPatches' equal segments (in the parametric sense) and 113cb93a386Sopenharmony_ci // writes them to the GPU buffer. 114cb93a386Sopenharmony_ci // 115cb93a386Sopenharmony_ci // Fills space between chops with triangles if PathPatchAttrib::kFanPoint is not enabled. 116cb93a386Sopenharmony_ci void chopAndWriteConics(float2 p0, float2 p1, float2 p2, float w, int numPatches); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci // Chops the given cubic into 'numPatches' equal segments (in the parametric sense) and 119cb93a386Sopenharmony_ci // writes them to the GPU buffer. 120cb93a386Sopenharmony_ci // 121cb93a386Sopenharmony_ci // Fills space between chops with triangles if PathPatchAttrib::kFanPoint is not enabled. 122cb93a386Sopenharmony_ci void chopAndWriteCubics(float2 p0, float2 p1, float2 p2, float2 p3, int numPatches); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ciprivate: 125cb93a386Sopenharmony_ci VertexWriter appendPatch() { 126cb93a386Sopenharmony_ci VertexWriter vertexWriter = fChunker.appendVertex(); 127cb93a386Sopenharmony_ci if (!vertexWriter) { 128cb93a386Sopenharmony_ci // Failed to allocate GPU storage for the patch. Write to a throwaway location so the 129cb93a386Sopenharmony_ci // callsites don't have to do null checks. 130cb93a386Sopenharmony_ci if (!fFallbackPatchStorage) { 131cb93a386Sopenharmony_ci fFallbackPatchStorage.reset(fChunker.stride()); 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci vertexWriter = fFallbackPatchStorage.data(); 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci return vertexWriter; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci template <typename T> 139cb93a386Sopenharmony_ci static VertexWriter::Conditional<T> If(bool c, const T& v) { return VertexWriter::If(c,v); } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci void outputPatchAttribs(VertexWriter vertexWriter, float explicitCurveType) { 142cb93a386Sopenharmony_ci vertexWriter << If((fPatchAttribs & PatchAttribs::kFanPoint), fFanPointAttrib) 143cb93a386Sopenharmony_ci << If((fPatchAttribs & PatchAttribs::kColor), fColorAttrib) 144cb93a386Sopenharmony_ci << If((fPatchAttribs & PatchAttribs::kExplicitCurveType), explicitCurveType); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci const PatchAttribs fPatchAttribs; 148cb93a386Sopenharmony_ci SkPoint fFanPointAttrib; 149cb93a386Sopenharmony_ci GrVertexColor fColorAttrib; 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci GrVertexChunkBuilder fChunker; 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci // For when fChunker fails to allocate a patch in GPU memory. 154cb93a386Sopenharmony_ci SkAutoTMalloc<char> fFallbackPatchStorage; 155cb93a386Sopenharmony_ci}; 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci// Converts a line to a cubic when being output via '<<' to a VertexWriter. 158cb93a386Sopenharmony_cistruct LineToCubic { 159cb93a386Sopenharmony_ci float4 fP0P1; 160cb93a386Sopenharmony_ci}; 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ciSK_MAYBE_UNUSED SK_ALWAYS_INLINE VertexWriter& operator<<(VertexWriter& vertexWriter, 163cb93a386Sopenharmony_ci const LineToCubic& line) { 164cb93a386Sopenharmony_ci float4 p0p1 = line.fP0P1; 165cb93a386Sopenharmony_ci float4 v = p0p1.zwxy() - p0p1; 166cb93a386Sopenharmony_ci return vertexWriter << p0p1.lo << (v * (1/3.f) + p0p1) << p0p1.hi; 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci// Converts a quadratic to a cubic when being output via '<<' to a VertexWriter. 170cb93a386Sopenharmony_cistruct QuadToCubic { 171cb93a386Sopenharmony_ci float2 fP0, fP1, fP2; 172cb93a386Sopenharmony_ci}; 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ciSK_MAYBE_UNUSED SK_ALWAYS_INLINE VertexWriter& operator<<(VertexWriter& vertexWriter, 175cb93a386Sopenharmony_ci const QuadToCubic& quadratic) { 176cb93a386Sopenharmony_ci auto [p0, p1, p2] = quadratic; 177cb93a386Sopenharmony_ci return vertexWriter << p0 << mix(float4(p0,p2), p1.xyxy(), 2/3.f) << p2; 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ciSK_MAYBE_UNUSED SK_ALWAYS_INLINE void operator<<( 181cb93a386Sopenharmony_ci PatchWriter& w, MiddleOutPolygonTriangulator::PoppedTriangleStack&& stack) { 182cb93a386Sopenharmony_ci for (auto [p0, p1, p2] : stack) { 183cb93a386Sopenharmony_ci PatchWriter::TrianglePatch(w) << p0 << p1 << p2; 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci} 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci} // namespace skgpu 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci#endif // tessellate_PatchWriter_DEFINED 190