Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
skgpu::ganesh::QuadPerEdgeAA::Tessellator Class Reference

#include <QuadPerEdgeAA.h>

Public Member Functions

 Tessellator (const VertexSpec &spec, char *vertices)
 
void append (GrQuad *deviceQuad, GrQuad *localQuad, const SkPMColor4f &color, const SkRect &uvSubset, GrQuadAAFlags aaFlags)
 

Static Public Member Functions

static SkDEBUGCODE(skgpu::BufferWriter::Mark vertexMark() const { return fVertexWriter.mark();}) private WriteQuadProc GetWriteQuadProc (const VertexSpec &spec)
 

Public Attributes

GrQuadUtils::TessellationHelper fAAHelper
 
VertexSpec fVertexSpec
 
VertexWriter fVertexWriter
 
WriteQuadProc fWriteProc
 

Detailed Description

Definition at line 146 of file QuadPerEdgeAA.h.

Constructor & Destructor Documentation

◆ Tessellator()

skgpu::ganesh::QuadPerEdgeAA::Tessellator::Tessellator ( const VertexSpec spec,
char *  vertices 
)
explicit

Definition at line 363 of file QuadPerEdgeAA.cpp.

364 : fVertexSpec(spec)
365 , fVertexWriter{vertices}
static SkDEBUGCODE(skgpu::BufferWriter::Mark vertexMark() const { return fVertexWriter.mark();}) private WriteQuadProc GetWriteQuadProc(const VertexSpec &spec)

Member Function Documentation

◆ append()

void skgpu::ganesh::QuadPerEdgeAA::Tessellator::append ( GrQuad deviceQuad,
GrQuad localQuad,
const SkPMColor4f color,
const SkRect uvSubset,
GrQuadAAFlags  aaFlags 
)

Definition at line 368 of file QuadPerEdgeAA.cpp.

369 {
370 // We allow Tessellator to be created with a null vertices pointer for convenience, but it is
371 // assumed it will never actually be used in those cases.
373 SkASSERT(deviceQuad->quadType() <= fVertexSpec.deviceQuadType());
374 SkASSERT(localQuad || !fVertexSpec.hasLocalCoords());
376
377 static const float kFullCoverage[4] = {1.f, 1.f, 1.f, 1.f};
378 static const float kZeroCoverage[4] = {0.f, 0.f, 0.f, 0.f};
379 static const SkRect kIgnoredSubset = SkRect::MakeEmpty();
380
384 // Must calculate inner and outer quadrilaterals for the vertex coverage ramps, and possibly
385 // a geometry subset if corners are not right angles
386 SkRect geomSubset;
388 // Our GP code expects a 0.5 outset rect (coverage is computed as 0 at the values of
389 // the uniform). However, if we have quad edges that aren't supposed to be antialiased
390 // they may lie close to the bounds. So in that case we outset by an additional 0.5.
391 // This is a sort of backup clipping mechanism for cases where quad outsetting of nearly
392 // parallel edges produces long thin extrusions from the original geometry.
393 float outset = aaFlags == GrQuadAAFlags::kAll ? 0.5f : 1.f;
394 geomSubset = deviceQuad->bounds().makeOutset(outset, outset);
395 }
396
397 if (aaFlags == GrQuadAAFlags::kNone) {
398 // Have to write the coverage AA vertex structure, but there's no math to be done for a
399 // non-aa quad batched into a coverage AA op.
400 fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
401 geomSubset, uvSubset);
402 // Since we pass the same corners in, the outer vertex structure will have 0 area and
403 // the coverage interpolation from 1 to 0 will not be visible.
404 fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
405 geomSubset, uvSubset);
406 } else {
407 // Reset the tessellation helper to match the current geometry
408 fAAHelper.reset(*deviceQuad, localQuad);
409
410 // Edge inset/outset distance ordered LBTR, set to 0.5 for a half pixel if the AA flag
411 // is turned on, or 0.0 if the edge is not anti-aliased.
412 skvx::Vec<4, float> edgeDistances;
413 if (aaFlags == GrQuadAAFlags::kAll) {
414 edgeDistances = 0.5f;
415 } else {
416 edgeDistances = { (aaFlags & GrQuadAAFlags::kLeft) ? 0.5f : 0.f,
417 (aaFlags & GrQuadAAFlags::kBottom) ? 0.5f : 0.f,
418 (aaFlags & GrQuadAAFlags::kTop) ? 0.5f : 0.f,
419 (aaFlags & GrQuadAAFlags::kRight) ? 0.5f : 0.f };
420 }
421
422 // Write inner vertices first
423 float coverage[4];
424 fAAHelper.inset(edgeDistances, deviceQuad, localQuad).store(coverage);
425 fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, coverage, color,
426 geomSubset, uvSubset);
427
428 // Then outer vertices, which use 0.f for their coverage. If the inset was degenerate
429 // to a line (had all coverages < 1), tweak the outset distance so the outer frame's
430 // narrow axis reaches out to 2px, which gives better animation under translation.
431 const bool hairline = aaFlags == GrQuadAAFlags::kAll &&
432 coverage[0] < 1.f &&
433 coverage[1] < 1.f &&
434 coverage[2] < 1.f &&
435 coverage[3] < 1.f;
436 if (hairline) {
438 // Using max guards us against trying to scale a degenerate triangle edge of 0 len
439 // up to 2px. The shuffles are so that edge 0's adjustment is based on the lengths
440 // of its connecting edges (1 and 2), and so forth.
441 skvx::Vec<4, float> maxWH = max(skvx::shuffle<1, 0, 3, 2>(len),
442 skvx::shuffle<2, 3, 0, 1>(len));
443 // wh + 2e' = 2, so e' = (2 - wh) / 2 => e' = e * (2 - wh). But if w or h > 1, then
444 // 2 - wh < 1 and represents the non-narrow axis so clamp to 1.
445 edgeDistances *= max(1.f, 2.f - maxWH);
446 }
447 fAAHelper.outset(edgeDistances, deviceQuad, localQuad);
448 fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
449 geomSubset, uvSubset);
450 }
451 } else {
452 // No outsetting needed, just write a single quad with full coverage
455 fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
456 kIgnoredSubset, uvSubset);
457 }
458}
static const int outset
Definition BlurTest.cpp:58
GrQuadAAFlags
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
void reset(const GrQuad &deviceQuad, const GrQuad *localQuad)
void outset(const skvx::float4 &edgeDistances, GrQuad *deviceOutset, GrQuad *localOutset)
skvx::float4 inset(const skvx::float4 &edgeDistances, GrQuad *deviceInset, GrQuad *localInset)
Type quadType() const
Definition GrQuad.h:118
SkRect bounds() const
Definition GrQuad.h:81
GrQuadUtils::TessellationHelper fAAHelper
static float max(float r, float g, float b)
Definition hsl.cpp:49
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
SkRect makeOutset(float dx, float dy) const
Definition SkRect.h:1002
SKVX_ALWAYS_INLINE void store(void *ptr) const
Definition SkVx.h:112

◆ GetWriteQuadProc()

Tessellator::WriteQuadProc skgpu::ganesh::QuadPerEdgeAA::Tessellator::GetWriteQuadProc ( const VertexSpec spec)
static

Definition at line 326 of file QuadPerEdgeAA.cpp.

326 {
327 // All specialized writing functions requires 2D geometry and no geometry subset. This is not
328 // the same as just checking device type vs. kRectilinear since non-AA general 2D quads do not
329 // require a geometry subset and could then go through a fast path.
332 if (spec.hasVertexColors()) {
333 if (mode != CoverageMode::kWithPosition) {
334 // Vertex colors, but no explicit coverage
335 if (!spec.hasLocalCoords()) {
336 // Non-UV with vertex colors (possibly with coverage folded into alpha)
337 return write_2d_color;
338 } else if (spec.localQuadType() != GrQuad::Type::kPerspective) {
339 // UV locals with vertex colors (possibly with coverage-as-alpha)
340 return spec.hasSubset() ? write_2d_color_uv_strict : write_2d_color_uv;
341 }
342 }
343 // Else fall through; this is a spec that requires vertex colors and explicit coverage,
344 // which means it's anti-aliased and the FPs don't support coverage as alpha, or
345 // it uses 3D local coordinates.
346 } else if (spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective) {
347 if (mode == CoverageMode::kWithPosition) {
348 // UV locals with explicit coverage
349 return spec.hasSubset() ? write_2d_cov_uv_strict : write_2d_cov_uv;
350 } else {
352 return spec.hasSubset() ? write_2d_uv_strict : write_2d_uv;
353 }
354 }
355 // Else fall through to generic vertex function; this is a spec that has no vertex colors
356 // and [no|uvr] local coords, which doesn't happen often enough to warrant specialization.
357 }
358
359 // Arbitrary spec hits the slow path
360 return write_quad_generic;
361}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition switches.h:228

Member Data Documentation

◆ fAAHelper

GrQuadUtils::TessellationHelper skgpu::ganesh::QuadPerEdgeAA::Tessellator::fAAHelper

Definition at line 171 of file QuadPerEdgeAA.h.

◆ fVertexSpec

VertexSpec skgpu::ganesh::QuadPerEdgeAA::Tessellator::fVertexSpec

Definition at line 172 of file QuadPerEdgeAA.h.

◆ fVertexWriter

VertexWriter skgpu::ganesh::QuadPerEdgeAA::Tessellator::fVertexWriter

Definition at line 173 of file QuadPerEdgeAA.h.

◆ fWriteProc

WriteQuadProc skgpu::ganesh::QuadPerEdgeAA::Tessellator::fWriteProc

Definition at line 174 of file QuadPerEdgeAA.h.


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