GrQuadPerEdgeAA::Tessellator owns GrVertexWriter

Change-Id: I3c8bf48dda061aa9d318b9f81f22608fdd68fcbd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/255786
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Michael Ludwig 2019-11-21 11:21:12 -05:00 committed by Skia Commit-Bot
parent fe13ca3e67
commit 189c98042f
5 changed files with 39 additions and 42 deletions

View File

@ -421,8 +421,8 @@ private:
GrQuad quad = GrQuad::MakeFromSkQuad(fCorners, SkMatrix::I());
float vertices[56]; // 2 quads, with x, y, coverage, and geometry domain (7 floats x 8 vert)
GrQuadPerEdgeAA::Tessellator tessellator(kSpec);
tessellator.append(vertices, quad, GrQuad(SkRect::MakeEmpty()), {1.f, 1.f, 1.f, 1.f},
GrQuadPerEdgeAA::Tessellator tessellator(kSpec, (char*) vertices);
tessellator.append(quad, GrQuad(SkRect::MakeEmpty()), {1.f, 1.f, 1.f, 1.f},
SkRect::MakeEmpty(), flags);
// The first quad in vertices is the inset, then the outset, but they

View File

@ -216,17 +216,15 @@ private:
return;
}
// vertices pointer advances through vdata based on Tessellate's return value
void* vertices = vdata;
GrQuadPerEdgeAA::Tessellator tessellator(vertexSpec);
GrQuadPerEdgeAA::Tessellator tessellator(vertexSpec, (char*) vdata);
auto iter = fQuads.iterator();
while(iter.next()) {
// All entries should have local coords, or no entries should have local coords,
// matching !helper.isTrivial() (which is more conservative than helper.usesLocalCoords)
SkASSERT(iter.isLocalValid() != fHelper.isTrivial());
auto info = iter.metadata();
vertices = tessellator.append(vertices, iter.deviceQuad(), iter.localQuad(),
info.fColor, kEmptyDomain, info.fAAFlags);
tessellator.append(iter.deviceQuad(), iter.localQuad(),
info.fColor, kEmptyDomain, info.fAAFlags);
}
sk_sp<const GrBuffer> indexBuffer;

View File

@ -8,7 +8,6 @@
#include "src/gpu/ops/GrQuadPerEdgeAA.h"
#include "include/private/SkVx.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/geometry/GrQuadUtils.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
@ -285,12 +284,16 @@ Tessellator::WriteQuadProc Tessellator::GetWriteQuadProc(const VertexSpec& spec)
return write_quad_generic;
}
Tessellator::Tessellator(const VertexSpec& spec)
Tessellator::Tessellator(const VertexSpec& spec, char* vertices)
: fVertexSpec(spec)
, fVertexWriter{vertices}
, fWriteProc(Tessellator::GetWriteQuadProc(spec)) {}
void* Tessellator::append(void* vertices, const GrQuad& deviceQuad, const GrQuad& localQuad,
const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags) {
void Tessellator::append(const GrQuad& deviceQuad, const GrQuad& localQuad,
const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags) {
// We allow Tessellator to be created with a null vertices pointer for convenience, but it is
// assumed it will never actually be used in those cases.
SkASSERT(fVertexWriter.fPtr);
SkASSERT(deviceQuad.quadType() <= fVertexSpec.deviceQuadType());
SkASSERT(!fVertexSpec.hasLocalCoords() || localQuad.quadType() <= fVertexSpec.localQuadType());
@ -298,7 +301,6 @@ void* Tessellator::append(void* vertices, const GrQuad& deviceQuad, const GrQuad
static const float kZeroCoverage[4] = {0.f, 0.f, 0.f, 0.f};
static const SkRect kIgnoredDomain = SkRect::MakeEmpty();
GrVertexWriter vb{vertices};
if (fVertexSpec.usesCoverageAA()) {
SkASSERT(fVertexSpec.coverageMode() == CoverageMode::kWithColor ||
fVertexSpec.coverageMode() == CoverageMode::kWithPosition);
@ -313,11 +315,11 @@ void* Tessellator::append(void* vertices, const GrQuad& deviceQuad, const GrQuad
if (aaFlags == GrQuadAAFlags::kNone) {
// Have to write the coverage AA vertex structure, but there's no math to be done for a
// non-aa quad batched into a coverage AA op.
fWriteProc(&vb, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
geomDomain, uvDomain);
// Since we pass the same corners in, the outer vertex structure will have 0 area and
// the coverage interpolation from 1 to 0 will not be visible.
fWriteProc(&vb, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
geomDomain, uvDomain);
} else {
// Reset the tessellation helper to match the current geometry
@ -340,23 +342,21 @@ void* Tessellator::append(void* vertices, const GrQuad& deviceQuad, const GrQuad
// Write inner vertices first
float coverage[4];
fAAHelper.inset(edgeDistances, &aaDeviceQuad, &aaLocalQuad).store(coverage);
fWriteProc(&vb, fVertexSpec, aaDeviceQuad, aaLocalQuad, coverage, color,
fWriteProc(&fVertexWriter, fVertexSpec, aaDeviceQuad, aaLocalQuad, coverage, color,
geomDomain, uvDomain);
// Then outer vertices, which use 0.f for their coverage
fAAHelper.outset(edgeDistances, &aaDeviceQuad, &aaLocalQuad);
fWriteProc(&vb, fVertexSpec, aaDeviceQuad, aaLocalQuad, kZeroCoverage, color,
fWriteProc(&fVertexWriter, fVertexSpec, aaDeviceQuad, aaLocalQuad, kZeroCoverage, color,
geomDomain, uvDomain);
}
} else {
// No outsetting needed, just write a single quad with full coverage
SkASSERT(fVertexSpec.coverageMode() == CoverageMode::kNone &&
!fVertexSpec.requiresGeometryDomain());
fWriteProc(&vb, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
kIgnoredDomain, uvDomain);
}
return vb.fPtr;
}
sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target* target,

View File

@ -14,6 +14,7 @@
#include "src/gpu/GrColor.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/geometry/GrQuad.h"
#include "src/gpu/geometry/GrQuadUtils.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
@ -134,14 +135,16 @@ namespace GrQuadPerEdgeAA {
// MakeProcessor and/or MakeTexturedProcessor.
class Tessellator {
public:
explicit Tessellator(const VertexSpec& spec);
explicit Tessellator(const VertexSpec& spec, char* vertices);
// Calculates (as needed) inset and outset geometry for anti-aliasing, and writes all
// necessary position and vertex attributes required by this Tessellator's VertexSpec.
// After appending, this will return the pointer to the next vertex in the VBO.
void* append(void* vertices, const GrQuad& deviceQuad, const GrQuad& localQuad,
// Calculates (as needed) inset and outset geometry for anti-aliasing, and appends all
// necessary position and vertex attributes required by this Tessellator's VertexSpec into
// the 'vertices' the Tessellator was called with.
void append(const GrQuad& deviceQuad, const GrQuad& localQuad,
const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags);
SkDEBUGCODE(char* vertices() const { return (char*) fVertexWriter.fPtr; })
private:
// VertexSpec defines many unique ways to write vertex attributes, which can be handled
// generically by branching per-quad based on the VertexSpec. However, there are several
@ -155,6 +158,7 @@ namespace GrQuadPerEdgeAA {
GrQuadUtils::TessellationHelper fAAHelper;
VertexSpec fVertexSpec;
GrVertexWriter fVertexWriter;
WriteQuadProc fWriteProc;
};

View File

@ -584,36 +584,30 @@ private:
sk_sp<const GrBuffer> indexBuffer) {
int totQuadsSeen = 0;
SkDEBUGCODE(int totVerticesSeen = 0;)
char* dst = pVertexData;
const size_t vertexSize = desc->fVertexSpec.vertexSize();
SkDEBUGCODE(const size_t vertexSize = desc->fVertexSpec.vertexSize());
GrQuadPerEdgeAA::Tessellator tessellator(desc->fVertexSpec);
GrQuadPerEdgeAA::Tessellator tessellator(desc->fVertexSpec, pVertexData);
int meshIndex = 0;
for (const auto& op : ChainRange<TextureOp>(texOp)) {
auto iter = op.fQuads.iterator();
for (unsigned p = 0; p < op.fProxyCnt; ++p) {
GrTextureProxy* proxy = op.fViewCountPairs[p].fProxyView.asTextureProxy();
int quadCnt = op.fViewCountPairs[p].fQuadCnt;
const int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad();
const int quadCnt = op.fViewCountPairs[p].fQuadCnt;
SkDEBUGCODE(int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad());
SkASSERT(meshIndex < desc->fNumProxies);
if (dst) {
int i = 0;
void* v = dst;
while(i < quadCnt && iter.next()) {
if (pVertexData) {
for (int i = 0; i < quadCnt && iter.next(); ++i) {
SkASSERT(iter.isLocalValid());
const ColorDomainAndAA& info = iter.metadata();
v = tessellator.append(v, iter.deviceQuad(), iter.localQuad(),
info.fColor, info.fDomainRect, info.aaFlags());
i++;
tessellator.append(iter.deviceQuad(), iter.localQuad(),
info.fColor, info.fDomainRect, info.aaFlags());
}
desc->setMeshProxy(meshIndex, proxy);
SkASSERT(totVerticesSeen * vertexSize == (size_t)(dst - pVertexData));
dst += vertexSize * meshVertexCnt;
SkASSERT((totVerticesSeen + meshVertexCnt) * vertexSize
== (size_t)(tessellator.vertices() - pVertexData));
}
if (meshes) {
@ -631,10 +625,11 @@ private:
// If quad counts per proxy were calculated correctly, the entire iterator
// should have been consumed.
SkASSERT(!dst || !iter.next());
SkASSERT(!pVertexData || !iter.next());
}
SkASSERT(!dst || (desc->totalSizeInBytes() == (size_t)(dst - pVertexData)));
SkASSERT(!pVertexData ||
(desc->totalSizeInBytes() == (size_t)(tessellator.vertices() - pVertexData)));
SkASSERT(meshIndex == desc->fNumProxies);
SkASSERT(totQuadsSeen == desc->fNumTotalQuads);
SkASSERT(totVerticesSeen == desc->totalNumVertices());