blob: c74f46cbe4f5abde80e30669457036b833267de8 [file] [log] [blame]
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrResolveLevelCounter_DEFINED
#define GrResolveLevelCounter_DEFINED
#include "src/core/SkPathPriv.h"
#include "src/gpu/tessellate/GrStencilPathShader.h"
#include "src/gpu/tessellate/GrWangsFormula.h"
// This class helps bin cubics by log2 "resolveLevel" when we don't use hardware tessellation. It is
// composed of simple counters that track how many cubics we intend to draw at each resolveLevel,
// and how many resolveLevels there are that have at least one cubic.
class GrResolveLevelCounter {
public:
void reset() {
memset(fInstanceCounts, 0, sizeof(fInstanceCounts));
SkDEBUGCODE(fHasCalledReset = true;)
}
int reset(const SkPath& path, const SkMatrix& viewMatrix, float intolerance) {
this->reset();
GrVectorXform xform(viewMatrix);
for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
switch (verb) {
case SkPathVerb::kQuad:
// Quadratics get converted to cubics before rendering.
this->countCubic(GrWangsFormula::quadratic_log2(intolerance, pts, xform));
break;
case SkPathVerb::kCubic:
this->countCubic(GrWangsFormula::cubic_log2(intolerance, pts, xform));
break;
default:
break;
}
}
return fTotalCubicInstanceCount;
}
void countCubic(int resolveLevel) {
SkASSERT(fHasCalledReset);
SkASSERT(resolveLevel >= 0);
if (resolveLevel == 0) {
// Cubics with 2^0=1 segments are empty (zero area). We ignore them completely.
return;
}
resolveLevel = std::min(resolveLevel, GrMiddleOutCubicShader::kMaxResolveLevel);
if (!fInstanceCounts[resolveLevel]++) {
++fTotalCubicIndirectDrawCount;
}
++fTotalCubicInstanceCount;
}
int operator[](int resolveLevel) const {
SkASSERT(fHasCalledReset);
SkASSERT(resolveLevel > 0); // Empty cubics with 2^0=1 segments do not need to be drawn.
SkASSERT(resolveLevel <= GrMiddleOutCubicShader::kMaxResolveLevel);
return fInstanceCounts[resolveLevel];
}
int totalCubicInstanceCount() const { return fTotalCubicInstanceCount; }
int totalCubicIndirectDrawCount() const { return fTotalCubicIndirectDrawCount; }
private:
SkDEBUGCODE(bool fHasCalledReset = false;)
int fInstanceCounts[GrMiddleOutCubicShader::kMaxResolveLevel + 1];
int fTotalCubicInstanceCount = 0;
int fTotalCubicIndirectDrawCount = 0;
};
#endif