1/*
2 * Copyright 2020 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 GrResolveLevelCounter_DEFINED
9#define GrResolveLevelCounter_DEFINED
10
11#include "src/core/SkPathPriv.h"
12#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
13#include "src/gpu/tessellate/GrWangsFormula.h"
14
15// This class helps bin cubics by log2 "resolveLevel" when we don't use hardware tessellation. It is
16// composed of simple counters that track how many cubics we intend to draw at each resolveLevel,
17// and how many resolveLevels there are that have at least one cubic.
18class GrResolveLevelCounter {
19public:
20 void reset() {
21 memset(fInstanceCounts, 0, sizeof(fInstanceCounts));
22 SkDEBUGCODE(fHasCalledReset = true;)
23 }
24
25 void reset(const SkPath& path, const SkMatrix& viewMatrix, float intolerance) {
26 this->reset();
27 GrVectorXform xform(viewMatrix);
28 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
29 switch (verb) {
30 case SkPathVerb::kQuad:
31 // Quadratics get converted to cubics before rendering.
32 this->countCubic(GrWangsFormula::quadratic_log2(intolerance, pts, xform));
33 break;
34 case SkPathVerb::kCubic:
35 this->countCubic(GrWangsFormula::cubic_log2(intolerance, pts, xform));
36 break;
37 default:
38 break;
39 }
40 }
41 }
42
43 void countCubic(int resolveLevel) {
44 SkASSERT(fHasCalledReset);
45 SkASSERT(resolveLevel >= 0);
46 if (resolveLevel == 0) {
47 // Cubics with 2^0=1 segments are empty (zero area). We ignore them completely.
48 return;
49 }
50 resolveLevel = std::min(resolveLevel, GrTessellationPathRenderer::kMaxResolveLevel);
51 if (!fInstanceCounts[resolveLevel]++) {
52 ++fTotalCubicIndirectDrawCount;
53 }
54 ++fTotalCubicInstanceCount;
55 }
56
57 int operator[](int resolveLevel) const {
58 SkASSERT(fHasCalledReset);
59 SkASSERT(resolveLevel > 0); // Empty cubics with 2^0=1 segments do not need to be drawn.
60 SkASSERT(resolveLevel <= GrTessellationPathRenderer::kMaxResolveLevel);
61 return fInstanceCounts[resolveLevel];
62 }
63 int totalCubicInstanceCount() const { return fTotalCubicInstanceCount; }
64 int totalCubicIndirectDrawCount() const { return fTotalCubicIndirectDrawCount; }
65
66private:
67 SkDEBUGCODE(bool fHasCalledReset = false;)
68 int fInstanceCounts[GrTessellationPathRenderer::kMaxResolveLevel + 1];
69 int fTotalCubicInstanceCount = 0;
70 int fTotalCubicIndirectDrawCount = 0;
71};
72
73#endif
74