Allow Tessellator to operate on provided GrQuads
To facilitate this, the GrQuadBuffer::Iter's local GrQuads that are modified on each next() are now allowed to be operated on for the AA inset/outsetting. Previously this required additional GrQuads on the stack to hold the results, and additional guards for accessing localQuad() when the entry didn't have actual coords. With this change, a 2D op should have its device and src GrQuads' Ws set to 1 once, and then they are completely ignored for all iteration and tessellation, without any more redundant initialization. In all likelihood we won't see the needle move on powerful platforms, but may help lower end devices. Change-Id: I457205786766403a760918e779d36ba056d69cde Reviewed-on: https://skia-review.googlesource.com/c/skia/+/256097 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
849f4d6571
commit
704d5408db
@ -422,7 +422,7 @@ private:
|
||||
|
||||
float vertices[56]; // 2 quads, with x, y, coverage, and geometry domain (7 floats x 8 vert)
|
||||
GrQuadPerEdgeAA::Tessellator tessellator(kSpec, (char*) vertices);
|
||||
tessellator.append(quad, GrQuad(SkRect::MakeEmpty()), {1.f, 1.f, 1.f, 1.f},
|
||||
tessellator.append(&quad, nullptr, {1.f, 1.f, 1.f, 1.f},
|
||||
SkRect::MakeEmpty(), flags);
|
||||
|
||||
// The first quad in vertices is the inset, then the outset, but they
|
||||
|
@ -71,14 +71,16 @@ public:
|
||||
|
||||
const T& metadata() const { this->validate(); return *(fBuffer->metadata(fCurrentEntry)); }
|
||||
|
||||
const GrQuad& deviceQuad() const { this->validate(); return fDeviceQuad; }
|
||||
// The returned pointer is mutable so that the object can be used for scratch calculations
|
||||
// during op preparation. However, any changes are not persisted in the GrQuadBuffer and
|
||||
// subsequent calls to next() will overwrite the state of the GrQuad.
|
||||
GrQuad* deviceQuad() { this->validate(); return &fDeviceQuad; }
|
||||
|
||||
// If isLocalValid() returns false, this returns an empty quad (all 0s) so that localQuad()
|
||||
// can be called without triggering any sanitizers, for convenience when some other state
|
||||
// ensures that the quad will eventually not be used.
|
||||
const GrQuad& localQuad() const {
|
||||
// If isLocalValid() returns false, this returns nullptr. Otherwise, the returned pointer
|
||||
// is mutable in the same manner as deviceQuad().
|
||||
GrQuad* localQuad() {
|
||||
this->validate();
|
||||
return fLocalQuad;
|
||||
return this->isLocalValid() ? &fLocalQuad : nullptr;
|
||||
}
|
||||
|
||||
bool isLocalValid() const {
|
||||
@ -341,10 +343,8 @@ bool GrQuadBuffer<T>::Iter::next() {
|
||||
coords = fBuffer->unpackQuad(static_cast<GrQuad::Type>(h->fDeviceType), coords, &fDeviceQuad);
|
||||
if (h->fHasLocals) {
|
||||
coords = fBuffer->unpackQuad(static_cast<GrQuad::Type>(h->fLocalType), coords, &fLocalQuad);
|
||||
} else {
|
||||
static const GrQuad kEmptyLocal(SkRect::MakeEmpty());
|
||||
fLocalQuad = kEmptyLocal;
|
||||
}
|
||||
} // else localQuad() will return a nullptr so no need to reset fLocalQuad
|
||||
|
||||
// At this point, coords points to the start of the next entry
|
||||
fNextEntry = static_cast<const char*>(static_cast<const void*>(coords));
|
||||
SkASSERT((fNextEntry - fCurrentEntry) == fBuffer->entrySize(h));
|
||||
|
@ -29,9 +29,10 @@ using VertexSpec = GrQuadPerEdgeAA::VertexSpec;
|
||||
using ColorType = GrQuadPerEdgeAA::ColorType;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
static SkString dump_quad_info(int index, const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad, const SkPMColor4f& color,
|
||||
static SkString dump_quad_info(int index, const GrQuad* deviceQuad,
|
||||
const GrQuad* localQuad, const SkPMColor4f& color,
|
||||
GrQuadAAFlags aaFlags) {
|
||||
GrQuad safeLocal = localQuad ? *localQuad : GrQuad();
|
||||
SkString str;
|
||||
str.appendf("%d: Color: [%.2f, %.2f, %.2f, %.2f], Edge AA: l%u_t%u_r%u_b%u, \n"
|
||||
" device quad: [(%.2f, %2.f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), "
|
||||
@ -43,14 +44,14 @@ static SkString dump_quad_info(int index, const GrQuad& deviceQuad,
|
||||
(uint32_t) (aaFlags & GrQuadAAFlags::kTop),
|
||||
(uint32_t) (aaFlags & GrQuadAAFlags::kRight),
|
||||
(uint32_t) (aaFlags & GrQuadAAFlags::kBottom),
|
||||
deviceQuad.x(0), deviceQuad.y(0), deviceQuad.w(0),
|
||||
deviceQuad.x(1), deviceQuad.y(1), deviceQuad.w(1),
|
||||
deviceQuad.x(2), deviceQuad.y(2), deviceQuad.w(2),
|
||||
deviceQuad.x(3), deviceQuad.y(3), deviceQuad.w(3),
|
||||
localQuad.x(0), localQuad.y(0), localQuad.w(0),
|
||||
localQuad.x(1), localQuad.y(1), localQuad.w(1),
|
||||
localQuad.x(2), localQuad.y(2), localQuad.w(2),
|
||||
localQuad.x(3), localQuad.y(3), localQuad.w(3));
|
||||
deviceQuad->x(0), deviceQuad->y(0), deviceQuad->w(0),
|
||||
deviceQuad->x(1), deviceQuad->y(1), deviceQuad->w(1),
|
||||
deviceQuad->x(2), deviceQuad->y(2), deviceQuad->w(2),
|
||||
deviceQuad->x(3), deviceQuad->y(3), deviceQuad->w(3),
|
||||
safeLocal.x(0), safeLocal.y(0), safeLocal.w(0),
|
||||
safeLocal.x(1), safeLocal.y(1), safeLocal.w(1),
|
||||
safeLocal.x(2), safeLocal.y(2), safeLocal.w(2),
|
||||
safeLocal.x(3), safeLocal.y(3), safeLocal.w(3));
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
@ -23,16 +23,19 @@ namespace {
|
||||
// Generic WriteQuadProc that can handle any VertexSpec. It writes the 4 vertices in triangle strip
|
||||
// order, although the data per-vertex is dependent on the VertexSpec.
|
||||
static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
static constexpr auto If = GrVertexWriter::If<float>;
|
||||
|
||||
SkASSERT(!spec.hasLocalCoords() || localQuad);
|
||||
|
||||
GrQuadPerEdgeAA::CoverageMode mode = spec.coverageMode();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// save position, this is a float2 or float3 or float4 depending on the combination of
|
||||
// perspective and coverage mode.
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i),
|
||||
If(spec.deviceQuadType() == GrQuad::Type::kPerspective, deviceQuad.w(i)),
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i),
|
||||
If(spec.deviceQuadType() == GrQuad::Type::kPerspective, deviceQuad->w(i)),
|
||||
If(mode == GrQuadPerEdgeAA::CoverageMode::kWithPosition, coverage[i]));
|
||||
|
||||
// save color
|
||||
@ -45,8 +48,8 @@ static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::Vertex
|
||||
|
||||
// save local position
|
||||
if (spec.hasLocalCoords()) {
|
||||
vb->write(localQuad.x(i), localQuad.y(i),
|
||||
If(spec.localQuadType() == GrQuad::Type::kPerspective, localQuad.w(i)));
|
||||
vb->write(localQuad->x(i), localQuad->y(i),
|
||||
If(spec.localQuadType() == GrQuad::Type::kPerspective, localQuad->w(i)));
|
||||
}
|
||||
|
||||
// save the geometry domain
|
||||
@ -67,7 +70,7 @@ static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::Vertex
|
||||
// 2D (XY), no explicit coverage, vertex color, no locals, no geometry domain, no texture domain
|
||||
// This represents simple, solid color or shader, non-AA (or AA with cov. as alpha) rects.
|
||||
static void write_2d_color(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -78,20 +81,23 @@ static void write_2d_color(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec
|
||||
SkASSERT(spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(!spec.hasDomain());
|
||||
// We don't assert that localQuad == nullptr, since it is possible for GrFillRectOp to
|
||||
// accumulate local coords conservatively (paint not trivial), and then after analysis realize
|
||||
// the processors don't need local coordinates.
|
||||
|
||||
bool wide = spec.colorType() == GrQuadPerEdgeAA::ColorType::kHalf;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// If this is not coverage-with-alpha, make sure coverage == 1 so it doesn't do anything
|
||||
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor ||
|
||||
coverage[i] == 1.f);
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), GrVertexColor(color * coverage[i], wide));
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), GrVertexColor(color * coverage[i], wide));
|
||||
}
|
||||
}
|
||||
|
||||
// 2D (XY), no explicit coverage, UV locals, no color, no geometry domain, no texture domain
|
||||
// This represents opaque, non AA, textured rects
|
||||
static void write_2d_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -101,16 +107,17 @@ static void write_2d_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& s
|
||||
SkASSERT(!spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(!spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), localQuad.x(i), localQuad.y(i));
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), localQuad->x(i), localQuad->y(i));
|
||||
}
|
||||
}
|
||||
|
||||
// 2D (XY), no explicit coverage, UV locals, vertex color, no geometry or texture domains
|
||||
// This represents transparent, non AA (or AA with cov. as alpha), textured rects
|
||||
static void write_2d_color_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -121,21 +128,22 @@ static void write_2d_color_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexS
|
||||
SkASSERT(spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(!spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
bool wide = spec.colorType() == GrQuadPerEdgeAA::ColorType::kHalf;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// If this is not coverage-with-alpha, make sure coverage == 1 so it doesn't do anything
|
||||
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor ||
|
||||
coverage[i] == 1.f);
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), GrVertexColor(color * coverage[i], wide),
|
||||
localQuad.x(i), localQuad.y(i));
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), GrVertexColor(color * coverage[i], wide),
|
||||
localQuad->x(i), localQuad->y(i));
|
||||
}
|
||||
}
|
||||
|
||||
// 2D (XY), explicit coverage, UV locals, no color, no geometry domain, no texture domain
|
||||
// This represents opaque, AA, textured rects
|
||||
static void write_2d_cov_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -145,9 +153,11 @@ static void write_2d_cov_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpe
|
||||
SkASSERT(!spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(!spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), coverage[i], localQuad.x(i), localQuad.y(i));
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), coverage[i],
|
||||
localQuad->x(i), localQuad->y(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +170,7 @@ static void write_2d_cov_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpe
|
||||
// 2D (XY), no explicit coverage, UV locals, no color, tex domain but no geometry domain
|
||||
// This represents opaque, non AA, textured rects with strict uv sampling
|
||||
static void write_2d_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -170,16 +180,17 @@ static void write_2d_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::Vertex
|
||||
SkASSERT(!spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), localQuad.x(i), localQuad.y(i), texDomain);
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), localQuad->x(i), localQuad->y(i), texDomain);
|
||||
}
|
||||
}
|
||||
|
||||
// 2D (XY), no explicit coverage, UV locals, vertex color, tex domain but no geometry domain
|
||||
// This represents transparent, non AA (or AA with cov. as alpha), textured rects with strict sample
|
||||
static void write_2d_color_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -190,21 +201,22 @@ static void write_2d_color_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::
|
||||
SkASSERT(spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
bool wide = spec.colorType() == GrQuadPerEdgeAA::ColorType::kHalf;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// If this is not coverage-with-alpha, make sure coverage == 1 so it doesn't do anything
|
||||
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor ||
|
||||
coverage[i] == 1.f);
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), GrVertexColor(color * coverage[i], wide),
|
||||
localQuad.x(i), localQuad.y(i), texDomain);
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), GrVertexColor(color * coverage[i], wide),
|
||||
localQuad->x(i), localQuad->y(i), texDomain);
|
||||
}
|
||||
}
|
||||
|
||||
// 2D (XY), explicit coverage, UV locals, no color, tex domain but no geometry domain
|
||||
// This represents opaque, AA, textured rects with strict uv sampling
|
||||
static void write_2d_cov_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain) {
|
||||
// Assert assumptions about VertexSpec
|
||||
@ -214,10 +226,11 @@ static void write_2d_cov_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::Ve
|
||||
SkASSERT(!spec.hasVertexColors());
|
||||
SkASSERT(!spec.requiresGeometryDomain());
|
||||
SkASSERT(spec.hasDomain());
|
||||
SkASSERT(localQuad);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vb->write(deviceQuad.x(i), deviceQuad.y(i), coverage[i],
|
||||
localQuad.x(i), localQuad.y(i), texDomain);
|
||||
vb->write(deviceQuad->x(i), deviceQuad->y(i), coverage[i],
|
||||
localQuad->x(i), localQuad->y(i), texDomain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,13 +302,14 @@ Tessellator::Tessellator(const VertexSpec& spec, char* vertices)
|
||||
, fVertexWriter{vertices}
|
||||
, fWriteProc(Tessellator::GetWriteQuadProc(spec)) {}
|
||||
|
||||
void Tessellator::append(const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
void Tessellator::append(GrQuad* deviceQuad, 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());
|
||||
SkASSERT(deviceQuad->quadType() <= fVertexSpec.deviceQuadType());
|
||||
SkASSERT(localQuad || !fVertexSpec.hasLocalCoords());
|
||||
SkASSERT(!fVertexSpec.hasLocalCoords() || localQuad->quadType() <= fVertexSpec.localQuadType());
|
||||
|
||||
static const float kFullCoverage[4] = {1.f, 1.f, 1.f, 1.f};
|
||||
static const float kZeroCoverage[4] = {0.f, 0.f, 0.f, 0.f};
|
||||
@ -308,7 +322,7 @@ void Tessellator::append(const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
// a geometry domain if corners are not right angles
|
||||
SkRect geomDomain;
|
||||
if (fVertexSpec.requiresGeometryDomain()) {
|
||||
geomDomain = deviceQuad.bounds();
|
||||
geomDomain = deviceQuad->bounds();
|
||||
geomDomain.outset(0.5f, 0.5f); // account for AA expansion
|
||||
}
|
||||
|
||||
@ -323,7 +337,7 @@ void Tessellator::append(const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
geomDomain, uvDomain);
|
||||
} else {
|
||||
// Reset the tessellation helper to match the current geometry
|
||||
fAAHelper.reset(deviceQuad, fVertexSpec.hasLocalCoords() ? &localQuad : nullptr);
|
||||
fAAHelper.reset(*deviceQuad, localQuad);
|
||||
|
||||
// Edge inset/outset distance ordered LBTR, set to 0.5 for a half pixel if the AA flag
|
||||
// is turned on, or 0.0 if the edge is not anti-aliased.
|
||||
@ -337,17 +351,15 @@ void Tessellator::append(const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
(aaFlags & GrQuadAAFlags::kRight) ? 0.5f : 0.f };
|
||||
}
|
||||
|
||||
GrQuad aaDeviceQuad, aaLocalQuad;
|
||||
|
||||
// Write inner vertices first
|
||||
float coverage[4];
|
||||
fAAHelper.inset(edgeDistances, &aaDeviceQuad, &aaLocalQuad).store(coverage);
|
||||
fWriteProc(&fVertexWriter, fVertexSpec, aaDeviceQuad, aaLocalQuad, coverage, color,
|
||||
fAAHelper.inset(edgeDistances, deviceQuad, localQuad).store(coverage);
|
||||
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, coverage, color,
|
||||
geomDomain, uvDomain);
|
||||
|
||||
// Then outer vertices, which use 0.f for their coverage
|
||||
fAAHelper.outset(edgeDistances, &aaDeviceQuad, &aaLocalQuad);
|
||||
fWriteProc(&fVertexWriter, fVertexSpec, aaDeviceQuad, aaLocalQuad, kZeroCoverage, color,
|
||||
fAAHelper.outset(edgeDistances, deviceQuad, localQuad);
|
||||
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
|
||||
geomDomain, uvDomain);
|
||||
}
|
||||
} else {
|
||||
|
@ -139,8 +139,10 @@ namespace GrQuadPerEdgeAA {
|
||||
|
||||
// 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,
|
||||
// the 'vertices' the Tessellator was called with. The insetting and outsetting may
|
||||
// damage the provided GrQuads (as this is intended to work with GrQuadBuffer::Iter).
|
||||
// 'localQuad' can be null if the VertexSpec does not use local coords.
|
||||
void append(GrQuad* deviceQuad, GrQuad* localQuad,
|
||||
const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags);
|
||||
|
||||
SkDEBUGCODE(char* vertices() const { return (char*) fVertexWriter.fPtr; })
|
||||
@ -151,7 +153,7 @@ namespace GrQuadPerEdgeAA {
|
||||
// specs that appear in the wild far more frequently, so they use explicit WriteQuadProcs
|
||||
// that have no branches.
|
||||
typedef void (*WriteQuadProc)(GrVertexWriter* vertices, const VertexSpec& spec,
|
||||
const GrQuad& deviceQuad, const GrQuad& localQuad,
|
||||
const GrQuad* deviceQuad, const GrQuad* localQuad,
|
||||
const float coverage[4], const SkPMColor4f& color,
|
||||
const SkRect& geomDomain, const SkRect& texDomain);
|
||||
static WriteQuadProc GetWriteQuadProc(const VertexSpec& spec);
|
||||
|
@ -238,8 +238,8 @@ public:
|
||||
static_cast<int>(fFilter));
|
||||
int i = 0;
|
||||
while(i < fViewCountPairs[p].fQuadCnt && iter.next()) {
|
||||
const GrQuad& quad = iter.deviceQuad();
|
||||
const GrQuad& uv = iter.localQuad();
|
||||
const GrQuad* quad = iter.deviceQuad();
|
||||
GrQuad uv = iter.isLocalValid() ? *(iter.localQuad()) : GrQuad();
|
||||
const ColorDomainAndAA& info = iter.metadata();
|
||||
str.appendf(
|
||||
"%d: Color: 0x%08x, Domain(%d): [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n"
|
||||
@ -247,8 +247,8 @@ public:
|
||||
" Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n",
|
||||
i, info.fColor.toBytes_RGBA(), fDomain, info.fDomainRect.fLeft,
|
||||
info.fDomainRect.fTop, info.fDomainRect.fRight, info.fDomainRect.fBottom,
|
||||
quad.point(0).fX, quad.point(0).fY, quad.point(1).fX, quad.point(1).fY,
|
||||
quad.point(2).fX, quad.point(2).fY, quad.point(3).fX, quad.point(3).fY,
|
||||
quad->point(0).fX, quad->point(0).fY, quad->point(1).fX, quad->point(1).fY,
|
||||
quad->point(2).fX, quad->point(2).fY, quad->point(3).fX, quad->point(3).fY,
|
||||
uv.point(0).fX, uv.point(0).fY, uv.point(1).fX, uv.point(1).fY,
|
||||
uv.point(2).fX, uv.point(2).fY, uv.point(3).fX, uv.point(3).fY);
|
||||
|
||||
|
@ -112,16 +112,17 @@ TEST(Append) {
|
||||
auto iter = buffer.iterator();
|
||||
while(iter.next()) {
|
||||
// Each entry always has the device quad
|
||||
assert_quad_eq(r, expectedDeviceQuads[i], iter.deviceQuad());
|
||||
assert_quad_eq(r, expectedDeviceQuads[i], *iter.deviceQuad());
|
||||
assert_metadata_eq(r, {2 * i, 3.f * i}, iter.metadata());
|
||||
|
||||
if (i % 2 == 0) {
|
||||
// Confirm local quads included on even entries
|
||||
ASSERT(iter.isLocalValid());
|
||||
assert_quad_eq(r, expectedLocalQuads[i], iter.localQuad());
|
||||
assert_quad_eq(r, expectedLocalQuads[i], *iter.localQuad());
|
||||
} else {
|
||||
// Should not have locals
|
||||
ASSERT(!iter.isLocalValid());
|
||||
ASSERT(!iter.localQuad());
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -161,25 +162,27 @@ TEST(Concat) {
|
||||
while(iter.next()) {
|
||||
if (i < kQuadCount) {
|
||||
// First half should match original buffer1
|
||||
assert_quad_eq(r, quadsA[i], iter.deviceQuad());
|
||||
assert_quad_eq(r, quadsA[i], *iter.deviceQuad());
|
||||
assert_metadata_eq(r, {i, 2.f * i}, iter.metadata());
|
||||
if (i % 2 == 0) {
|
||||
ASSERT(iter.isLocalValid());
|
||||
assert_quad_eq(r, quadsB[i], iter.localQuad());
|
||||
assert_quad_eq(r, quadsB[i], *iter.localQuad());
|
||||
} else {
|
||||
ASSERT(!iter.isLocalValid());
|
||||
ASSERT(!iter.localQuad());
|
||||
}
|
||||
|
||||
} else {
|
||||
// Second half should match buffer2
|
||||
int j = i - kQuadCount;
|
||||
assert_quad_eq(r, quadsB[j], iter.deviceQuad());
|
||||
assert_quad_eq(r, quadsB[j], *iter.deviceQuad());
|
||||
assert_metadata_eq(r, {2 * j, 0.5f * j}, iter.metadata());
|
||||
if (j % 2 == 0) {
|
||||
ASSERT(!iter.isLocalValid());
|
||||
ASSERT(!iter.localQuad());
|
||||
} else {
|
||||
ASSERT(iter.isLocalValid());
|
||||
assert_quad_eq(r, quadsA[j], iter.localQuad());
|
||||
assert_quad_eq(r, quadsA[j], *iter.localQuad());
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,12 +224,13 @@ TEST(Metadata) {
|
||||
assert_metadata_eq(r, {2 * i, 0.5f * i}, iter.metadata());
|
||||
|
||||
// Quad coordinates are unchanged
|
||||
assert_quad_eq(r, quad, iter.deviceQuad());
|
||||
assert_quad_eq(r, quad, *iter.deviceQuad());
|
||||
if (i % 2 == 0) {
|
||||
ASSERT(iter.isLocalValid());
|
||||
assert_quad_eq(r, quad, iter.localQuad());
|
||||
assert_quad_eq(r, quad, *iter.localQuad());
|
||||
} else {
|
||||
ASSERT(!iter.isLocalValid());
|
||||
ASSERT(!iter.localQuad());
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user