blob: 1e40646db062359432e4915966eafbea43d99e72 [file] [log] [blame]
/*
* Copyright 2021 Google LLC.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef tessellate_StrokeFixedCountTessellator_DEFINED
#define tessellate_StrokeFixedCountTessellator_DEFINED
#include "src/gpu/tessellate/StrokeTessellator.h"
#if SK_GPU_V1
#include "src/gpu/GrGpuBuffer.h"
#endif
namespace skgpu {
// Renders strokes as fixed-count triangle strip instances. Any extra triangles not needed by the
// instance are emitted as degenerate triangles.
class StrokeFixedCountTessellator final : public StrokeTessellator {
public:
constexpr static float kMaxParametricSegments_pow4 = 32*32*32*32; // 32^4
constexpr static int8_t kMaxParametricSegments_log2 = 5; // log2(32)
StrokeFixedCountTessellator(PatchAttribs attribs) : StrokeTessellator(attribs) {}
int patchPreallocCount(int totalCombinedStrokeVerbCnt) const final;
int writePatches(PatchWriter&,
const SkMatrix& shaderMatrix,
std::array<float,2> matrixMinMaxScales,
PathStrokeList*) final;
#if SK_GPU_V1
int prepare(GrMeshDrawTarget*,
const SkMatrix& shaderMatrix,
std::array<float,2> matrixMinMaxScales,
PathStrokeList*,
int totalCombinedStrokeVerbCnt) final;
void draw(GrOpFlushState*) const final;
#endif
// Initializes the fallback vertex buffer that should be bound when sk_VertexID is not
// supported. Each vertex is a single float and each edge is composed of two vertices, so the
// desired edge count in the buffer is presumed to be "bufferSize / (sizeof(float) * 2)". The
// caller cannot draw more vertices than edgeCount * 2.
static void InitializeVertexIDFallbackBuffer(VertexWriter vertexWriter, size_t bufferSize);
// Returns the fixed number of edges that are always emitted with the given join type. If the
// join is round, the caller needs to account for the additional radial edges on their own.
// Specifically, each join always emits:
//
// * Two colocated edges at the beginning (a full-width edge to seam with the preceding stroke
// and a half-width edge to begin the join).
//
// * An extra edge in the middle for miter joins, or else a variable number of radial edges
// for round joins (the caller is responsible for counting radial edges from round joins).
//
// * A half-width edge at the end of the join that will be colocated with the first
// (full-width) edge of the stroke.
//
constexpr static int NumFixedEdgesInJoin(SkPaint::Join joinType) {
switch (joinType) {
case SkPaint::kMiter_Join:
return 4;
case SkPaint::kRound_Join:
// The caller is responsible for counting the variable number of middle, radial
// segments on round joins.
[[fallthrough]];
case SkPaint::kBevel_Join:
return 3;
}
SkUNREACHABLE;
}
private:
#if SK_GPU_V1
int fFixedEdgeCount = 0;
// Only used if sk_VertexID is not supported.
sk_sp<const GrGpuBuffer> fVertexBufferIfNoIDSupport;
#endif
};
} // namespace skgpu
#endif // tessellate_StrokeFixedCountTessellator_DEFINED