Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | List of all members
skgpu::tess::PatchWriter< PatchAllocator, Traits > Class Template Reference

#include <PatchWriter.h>

Public Member Functions

template<typename... Args>
 PatchWriter (PatchAttribs attribs, Args &&... allocArgs)
 
 ~PatchWriter ()
 
PatchAttribs attribs () const
 
void setShaderTransform (const wangs_formula::VectorXform &xform, float maxScale=1.f)
 
 ENABLE_IF (kTrackJoinControlPoints) writeDeferredStrokePatch()
 
 ENABLE_IF (JoinAttrib::kEnabled) updateJoinControlPointAttrib(SkPoint lastControlPoint)
 
 ENABLE_IF (FanPointAttrib::kEnabled) updateFanPointAttrib(SkPoint fanPoint)
 
 ENABLE_IF (StrokeAttrib::kEnabled) updateStrokeParamsAttrib(StrokeParams strokeParams)
 
 ENABLE_IF (StrokeAttrib::kEnabled) updateUniformStrokeParams(StrokeParams strokeParams)
 
 ENABLE_IF (ColorAttrib::kEnabled) updateColorAttrib(const SkPMColor4f &color)
 
 ENABLE_IF (DepthAttrib::kEnabled) updatePaintDepthAttrib(float depth)
 
 updateSsboIndexAttrib (skvx::ushort2 ssboIndex)
 
AI void writeCubic (float2 p0, float2 p1, float2 p2, float2 p3)
 
AI void writeCubic (const SkPoint pts[4])
 
AI void writeConic (float2 p0, float2 p1, float2 p2, float w)
 
AI void writeConic (const SkPoint pts[3], float w)
 
AI void writeQuadratic (float2 p0, float2 p1, float2 p2)
 
AI void writeQuadratic (const SkPoint pts[3])
 
AI void writeLine (float4 p0p1)
 
AI void writeLine (float2 p0, float2 p1)
 
AI void writeLine (SkPoint p0, SkPoint p1)
 
AI void writeTriangle (float2 p0, float2 p1, float2 p2)
 
AI void writeTriangle (SkPoint p0, SkPoint p1, SkPoint p2)
 
AI void writeCircle (SkPoint p)
 

Detailed Description

template<typename PatchAllocator, typename... Traits>
class skgpu::tess::PatchWriter< PatchAllocator, Traits >

Definition at line 208 of file PatchWriter.h.

Constructor & Destructor Documentation

◆ PatchWriter()

template<typename PatchAllocator , typename... Traits>
template<typename... Args>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::PatchWriter ( PatchAttribs  attribs,
Args &&...  allocArgs 
)
inline

Definition at line 270 of file PatchWriter.h.

272 : fAttribs(attribs)
273 , fPatchAllocator(PatchStride(attribs), std::forward<Args>(allocArgs)...)
274 , fJoin(attribs)
275 , fFanPoint(attribs)
276 , fStrokeParams(attribs)
277 , fColor(attribs)
278 , fDepth(attribs)
279 , fSsboIndex(attribs) {
280 // Explicit curve types are provided on the writePatch signature, and not a field of
281 // PatchWriter, so initialize one in the ctor to validate the provided runtime attribs.
282 SkDEBUGCODE((void) CurveTypeAttrib(attribs);)
283 // Validate the kWideColorIfEnabled attribute variant flag as well
284 if constexpr (req_attrib<PatchAttribs::kWideColorIfEnabled>::value) {
286 } else if constexpr (!opt_attrib<PatchAttribs::kWideColorIfEnabled>::value) {
288 }
289 }
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
PatchAttribs attribs() const
constexpr size_t PatchStride(PatchAttribs attribs)

◆ ~PatchWriter()

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::~PatchWriter ( )
inline

Definition at line 291 of file PatchWriter.h.

291 {
292 if constexpr (kTrackJoinControlPoints) {
293 // flush any pending patch
294 this->writeDeferredStrokePatch();
295 }
296 }

Member Function Documentation

◆ attribs()

template<typename PatchAllocator , typename... Traits>
PatchAttribs skgpu::tess::PatchWriter< PatchAllocator, Traits >::attribs ( ) const
inline

Definition at line 298 of file PatchWriter.h.

298{ return fAttribs; }

◆ ENABLE_IF() [1/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( ColorAttrib::kEnabled  ) const &
inline

Definition at line 361 of file PatchWriter.h.

361 {
362 SkASSERT(fAttribs & PatchAttribs::kColor);
363 // Converts SkPMColor4f to the selected 'Color' attrib type. The always-wide and never-wide
364 // branches match what VertexColor does based on the runtime check.
365 if constexpr (req_attrib<PatchAttribs::kWideColorIfEnabled>::value) {
366 fColor = color;
367 } else if constexpr (opt_attrib<PatchAttribs::kWideColorIfEnabled>::value) {
368 fColor = VertexColor(color, fAttribs & PatchAttribs::kWideColorIfEnabled);
369 } else {
370 fColor = color.toBytes_RGBA();
371 }
372 }
SkColor4f color

◆ ENABLE_IF() [2/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( DepthAttrib::kEnabled  )
inline

Definition at line 375 of file PatchWriter.h.

375 {
377 fDepth = depth;
378 }

◆ ENABLE_IF() [3/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( FanPointAttrib::kEnabled  )
inline

Definition at line 342 of file PatchWriter.h.

342 {
344 fFanPoint = fanPoint;
345 }

◆ ENABLE_IF() [4/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( JoinAttrib::kEnabled  )
inline

Definition at line 332 of file PatchWriter.h.

332 {
333 SkASSERT(fAttribs & PatchAttribs::kJoinControlPoint); // must be runtime enabled as well
334 fJoin = lastControlPoint;
335 if constexpr (kTrackJoinControlPoints) {
336 fDeferredPatch.fMustDefer = false;
337 }
338 }

◆ ENABLE_IF() [5/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( kTrackJoinControlPoints  )
inline

Definition at line 310 of file PatchWriter.h.

310 {
311 if (fDeferredPatch.hasPending()) {
312 SkASSERT(!fDeferredPatch.fMustDefer);
313 // Overwrite join control point with updated value, which is the first attribute
314 // after the 4 control points.
315 memcpy(SkTAddOffset<void>(fDeferredPatch.fData, 4 * sizeof(SkPoint)),
316 &fJoin, sizeof(SkPoint));
317 // Assuming that the stroke parameters aren't changing within a contour, we only have
318 // to set the parametric segments in order to recover the LinearTolerances state at the
319 // time the deferred patch was recorded.
320 fTolerances.setParametricSegments(fDeferredPatch.fN_p4);
321 if (VertexWriter vw = fPatchAllocator.append(fTolerances)) {
322 vw << VertexWriter::Array<char>(fDeferredPatch.fData, PatchStride(fAttribs));
323 }
324 }
325
326 fDeferredPatch.reset();
327 }

◆ ENABLE_IF() [6/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( StrokeAttrib::kEnabled  )
inline

Definition at line 348 of file PatchWriter.h.

348 {
350 fStrokeParams = strokeParams;
351 fTolerances.setStroke(strokeParams, fMaxScale);
352 }
void setStroke(const StrokeParams &strokeParams, float maxScale)

◆ ENABLE_IF() [7/7]

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::ENABLE_IF ( StrokeAttrib::kEnabled  )
inline

Definition at line 355 of file PatchWriter.h.

355 {
357 fTolerances.setStroke(strokeParams, fMaxScale);
358 }

◆ setShaderTransform()

template<typename PatchAllocator , typename... Traits>
void skgpu::tess::PatchWriter< PatchAllocator, Traits >::setShaderTransform ( const wangs_formula::VectorXform xform,
float  maxScale = 1.f 
)
inline

Definition at line 302 of file PatchWriter.h.

303 {
304 fApproxTransform = xform;
305 fMaxScale = maxScale;
306 }

◆ updateSsboIndexAttrib()

template<typename PatchAllocator , typename... Traits>
skgpu::tess::PatchWriter< PatchAllocator, Traits >::updateSsboIndexAttrib ( skvx::ushort2  ssboIndex)
inline

Definition at line 382 of file PatchWriter.h.

382 {
384 fSsboIndex = ssboIndex;
385 }

◆ writeCircle()

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeCircle ( SkPoint  p)
inline

Definition at line 502 of file PatchWriter.h.

502 {
503 // This does not use writePatch() because it uses its own location as the join attribute
504 // value instead of fJoin and never defers.
505 fTolerances.setParametricSegments(0.f);
506 if (VertexWriter vw = fPatchAllocator.append(fTolerances)) {
507 vw << VertexWriter::Repeat<4>(p); // p0,p1,p2,p3 = p -> 4 copies
508 this->emitPatchAttribs(std::move(vw), {fAttribs, p}, kCubicCurveType);
509 }
510 }
static constexpr float kCubicCurveType

◆ writeConic() [1/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeConic ( const SkPoint  pts[3],
float  w 
)
inline

Definition at line 433 of file PatchWriter.h.

433 {
434 this->writeConic(sk_bit_cast<float2>(pts[0]),
435 sk_bit_cast<float2>(pts[1]),
436 sk_bit_cast<float2>(pts[2]),
437 w);
438 }
AI void writeConic(float2 p0, float2 p1, float2 p2, float w)
SkScalar w

◆ writeConic() [2/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeConic ( float2  p0,
float2  p1,
float2  p2,
float  w 
)
inline

Definition at line 418 of file PatchWriter.h.

418 {
419 float n2 = wangs_formula::conic_p2(kPrecision, p0, p1, p2, w, fApproxTransform);
420 if constexpr (kDiscardFlatCurves) {
421 if (n2 <= 1.f) {
422 // This conic only needs one segment (e.g. a line) but we're not filling space with
423 // fans or stroking, so nothing actually needs to be drawn.
424 return;
425 }
426 }
427 if (int numPatches = this->accountForCurve(n2 * n2)) {
428 this->chopAndWriteConics(p0, p1, p2, w, numPatches);
429 } else {
430 this->writeConicPatch(p0, p1, p2, w);
431 }
432 }
static constexpr float kPrecision
AI float conic_p2(float precision, skvx::float2 p0, skvx::float2 p1, skvx::float2 p2, float w, const VectorXform &vectorXform=VectorXform())

◆ writeCubic() [1/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeCubic ( const SkPoint  pts[4])
inline

Definition at line 410 of file PatchWriter.h.

410 {
411 float4 p0p1 = float4::Load(pts);
412 float4 p2p3 = float4::Load(pts + 2);
413 this->writeCubic(p0p1.lo, p0p1.hi, p2p3.lo, p2p3.hi);
414 }
AI void writeCubic(float2 p0, float2 p1, float2 p2, float2 p3)
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition SkVx.h:109
Vec< N/2, T > hi
Definition SkVx.h:117
Vec< N/2, T > lo
Definition SkVx.h:117

◆ writeCubic() [2/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeCubic ( float2  p0,
float2  p1,
float2  p2,
float2  p3 
)
inline

writeX functions for supported patch geometry types. Every geometric type is converted to an equivalent cubic or conic, so this will always write at minimum 8 floats for the four control points (cubic) or three control points and {w, inf} (conics). The PatchWriter additionally writes the current values of all attributes enabled in its PatchAttribs flags.

Definition at line 395 of file PatchWriter.h.

395 {
396 float n4 = wangs_formula::cubic_p4(kPrecision, p0, p1, p2, p3, fApproxTransform);
397 if constexpr (kDiscardFlatCurves) {
398 if (n4 <= 1.f) {
399 // This cubic only needs one segment (e.g. a line) but we're not filling space with
400 // fans or stroking, so nothing actually needs to be drawn.
401 return;
402 }
403 }
404 if (int numPatches = this->accountForCurve(n4)) {
405 this->chopAndWriteCubics(p0, p1, p2, p3, numPatches);
406 } else {
407 this->writeCubicPatch(p0, p1, p2, p3);
408 }
409 }
AI float cubic_p4(float precision, skvx::float2 p0, skvx::float2 p1, skvx::float2 p2, skvx::float2 p3, const VectorXform &vectorXform=VectorXform())

◆ writeLine() [1/3]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeLine ( float2  p0,
float2  p1 
)
inline

Definition at line 479 of file PatchWriter.h.

479{ this->writeLine({p0, p1}); }
AI void writeLine(float4 p0p1)

◆ writeLine() [2/3]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeLine ( float4  p0p1)
inline

Definition at line 464 of file PatchWriter.h.

464 {
465 // No chopping needed, a line only ever requires one segment (the minimum required already).
466 fTolerances.setParametricSegments(1.f);
467 if constexpr (kReplicateLineEndPoints) {
468 // Visually this cubic is still a line, but 't' does not move linearly over the line,
469 // so Wang's formula is more pessimistic. Shaders should avoid evaluating Wang's
470 // formula when a patch has control points in this arrangement.
471 this->writeCubicPatch(p0p1.lo, p0p1.lo, p0p1.hi, p0p1.hi);
472 } else {
473 // In exact math, this cubic structure should have Wang's formula return 0. Due to
474 // floating point math, this isn't always the case, so shaders need some way to restrict
475 // the number of parametric segments if Wang's formula numerically blows up.
476 this->writeCubicPatch(p0p1.lo, (p0p1.zwxy() - p0p1) * (1/3.f) + p0p1, p0p1.hi);
477 }
478 }

◆ writeLine() [3/3]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeLine ( SkPoint  p0,
SkPoint  p1 
)
inline

Definition at line 480 of file PatchWriter.h.

480 {
481 this->writeLine(sk_bit_cast<float2>(p0), sk_bit_cast<float2>(p1));
482 }

◆ writeQuadratic() [1/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeQuadratic ( const SkPoint  pts[3])
inline

Definition at line 457 of file PatchWriter.h.

457 {
458 this->writeQuadratic(sk_bit_cast<float2>(pts[0]),
459 sk_bit_cast<float2>(pts[1]),
460 sk_bit_cast<float2>(pts[2]));
461 }
AI void writeQuadratic(float2 p0, float2 p1, float2 p2)

◆ writeQuadratic() [2/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeQuadratic ( float2  p0,
float2  p1,
float2  p2 
)
inline

Definition at line 442 of file PatchWriter.h.

442 {
443 float n4 = wangs_formula::quadratic_p4(kPrecision, p0, p1, p2, fApproxTransform);
444 if constexpr (kDiscardFlatCurves) {
445 if (n4 <= 1.f) {
446 // This quad only needs one segment (e.g. a line) but we're not filling space with
447 // fans or stroking, so nothing actually needs to be drawn.
448 return;
449 }
450 }
451 if (int numPatches = this->accountForCurve(n4)) {
452 this->chopAndWriteQuads(p0, p1, p2, numPatches);
453 } else {
454 this->writeQuadPatch(p0, p1, p2);
455 }
456 }
AI float quadratic_p4(float precision, skvx::float2 p0, skvx::float2 p1, skvx::float2 p2, const VectorXform &vectorXform=VectorXform())

◆ writeTriangle() [1/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeTriangle ( float2  p0,
float2  p1,
float2  p2 
)
inline

Definition at line 486 of file PatchWriter.h.

486 {
487 // No chopping needed, the max supported segment count should always support 2 lines
488 // (which form a triangle when implicitly closed).
489 static constexpr float kTriangleSegments_p4 = 2.f * 2.f * 2.f * 2.f;
490 fTolerances.setParametricSegments(kTriangleSegments_p4);
491 this->writePatch(p0, p1, p2, {SK_FloatInfinity, SK_FloatInfinity},
493 }
constexpr float SK_FloatInfinity
static constexpr float kTriangularConicCurveType

◆ writeTriangle() [2/2]

template<typename PatchAllocator , typename... Traits>
AI void skgpu::tess::PatchWriter< PatchAllocator, Traits >::writeTriangle ( SkPoint  p0,
SkPoint  p1,
SkPoint  p2 
)
inline

Definition at line 494 of file PatchWriter.h.

494 {
495 this->writeTriangle(sk_bit_cast<float2>(p0),
496 sk_bit_cast<float2>(p1),
497 sk_bit_cast<float2>(p2));
498 }
AI void writeTriangle(float2 p0, float2 p1, float2 p2)

The documentation for this class was generated from the following file: