Rename domain types and vars to subset.

Makes nomenclature more conistent across different classes.

Change-Id: I9f052bbd38082d95714702b2ae960c4e15fdc181
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/284718
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Brian Salomon 2020-04-16 20:48:09 -04:00 committed by Skia Commit-Bot
parent d8f611dff1
commit 2432d061ed
8 changed files with 198 additions and 197 deletions

View File

@ -408,7 +408,7 @@ private:
// Fixed vertex spec for extracting the picture frame geometry
static const GrQuadPerEdgeAA::VertexSpec kSpec =
{GrQuad::Type::kGeneral, GrQuadPerEdgeAA::ColorType::kNone,
GrQuad::Type::kAxisAligned, false, GrQuadPerEdgeAA::Domain::kNo,
GrQuad::Type::kAxisAligned, false, GrQuadPerEdgeAA::Subset::kNo,
GrAAType::kCoverage, false, GrQuadPerEdgeAA::IndexBufferOption::kPictureFramed};
static const GrQuad kIgnored(SkRect::MakeEmpty());

View File

@ -829,7 +829,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
SkBlendMode blendMode,
GrAA aa,
DrawQuad* quad,
const SkRect* domain) {
const SkRect* subset) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
@ -851,12 +851,12 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
: GrTextureOp::Saturate::kNo;
// Use the provided domain, although hypothetically we could detect that the cropped local
// quad is sufficiently inside the domain and the constraint could be dropped.
// Use the provided subset, although hypothetically we could detect that the cropped local
// quad is sufficiently inside the subset and the constraint could be dropped.
this->addDrawOp(finalClip,
GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
std::move(textureXform), filter, color, saturate,
blendMode, aaType, quad, domain));
blendMode, aaType, quad, subset));
}
}

View File

@ -280,30 +280,30 @@ public:
const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> texXform) {
const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint ?
const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
&srcRect : nullptr;
DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
filter, color, mode, aa, &quad, domain);
filter, color, mode, aa, &quad, subset);
}
/**
* Variant of drawTexture that instead draws the texture applied to 'dstQuad' transformed by
* 'viewMatrix', using the 'srcQuad' texture coordinates clamped to the optional 'domain'. If
* 'domain' is null, it's equivalent to using the fast src rect constraint. If 'domain' is
* provided, the strict src rect constraint is applied using 'domain'.
* 'viewMatrix', using the 'srcQuad' texture coordinates clamped to the optional 'subset'. If
* 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
* provided, the strict src rect constraint is applied using 'subset'.
*/
void drawTextureQuad(const GrClip& clip, GrSurfaceProxyView view, GrColorType srcColorType,
SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode,
const SkPMColor4f& color, const SkPoint srcQuad[4],
const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA,
const SkRect* domain, const SkMatrix& viewMatrix,
const SkRect* subset, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> texXform) {
DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform),
filter, color, mode, aa, &quad, domain);
filter, color, mode, aa, &quad, subset);
}
/** Used with drawTextureSet */
@ -669,7 +669,7 @@ private:
SkBlendMode blendMode,
GrAA aa,
DrawQuad* quad,
const SkRect* domain = nullptr);
const SkRect* subset = nullptr);
void drawShapeUsingPathRenderer(const GrClip&, GrPaint&&, GrAA, const SkMatrix&,
const GrStyledShape&);

View File

@ -212,7 +212,7 @@ private:
fQuads.count());
return VertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
fHelper.usesLocalCoords(), GrQuadPerEdgeAA::Domain::kNo,
fHelper.usesLocalCoords(), GrQuadPerEdgeAA::Subset::kNo,
fHelper.aaType(),
fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
}

View File

@ -31,7 +31,7 @@ namespace {
static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& spec,
const GrQuad* deviceQuad, const GrQuad* localQuad,
const float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
static constexpr auto If = GrVertexWriter::If<float>;
SkASSERT(!spec.hasLocalCoords() || localQuad);
@ -58,14 +58,14 @@ static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::Vertex
If(spec.localQuadType() == GrQuad::Type::kPerspective, localQuad->w(i)));
}
// save the geometry domain
if (spec.requiresGeometryDomain()) {
vb->write(geomDomain);
// save the geometry subset
if (spec.requiresGeometrySubset()) {
vb->write(geomSubset);
}
// save the texture domain
if (spec.hasDomain()) {
vb->write(texDomain);
// save the texture subset
if (spec.hasSubset()) {
vb->write(texSubset);
}
}
}
@ -73,20 +73,20 @@ static void write_quad_generic(GrVertexWriter* vb, const GrQuadPerEdgeAA::Vertex
// Specialized WriteQuadProcs for particular VertexSpecs that show up frequently (determined
// experimentally through recorded GMs, SKPs, and SVGs, as well as SkiaRenderer's usage patterns):
// 2D (XY), no explicit coverage, vertex color, no locals, no geometry domain, no texture domain
// 2D (XY), no explicit coverage, vertex color, no locals, no geometry subset, no texture subsetn
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(!spec.hasLocalCoords());
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kNone ||
spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor);
SkASSERT(spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(!spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(!spec.hasSubset());
// 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.
@ -100,19 +100,19 @@ static void write_2d_color(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec
}
}
// 2D (XY), no explicit coverage, UV locals, no color, no geometry domain, no texture domain
// 2D (XY), no explicit coverage, UV locals, no color, no geometry subset, no texture subset
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kNone);
SkASSERT(!spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(!spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(!spec.hasSubset());
SkASSERT(localQuad);
for (int i = 0; i < 4; ++i) {
@ -120,20 +120,20 @@ static void write_2d_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpec& s
}
}
// 2D (XY), no explicit coverage, UV locals, vertex color, no geometry or texture domains
// 2D (XY), no explicit coverage, UV locals, vertex color, no geometry or texture subsets
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kNone ||
spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor);
SkASSERT(spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(!spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(!spec.hasSubset());
SkASSERT(localQuad);
bool wide = spec.colorType() == GrQuadPerEdgeAA::ColorType::kFloat;
@ -146,19 +146,19 @@ static void write_2d_color_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexS
}
}
// 2D (XY), explicit coverage, UV locals, no color, no geometry domain, no texture domain
// 2D (XY), explicit coverage, UV locals, no color, no geometry subset, no texture subset
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithPosition);
SkASSERT(!spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(!spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(!spec.hasSubset());
SkASSERT(localQuad);
for (int i = 0; i < 4; ++i) {
@ -168,45 +168,45 @@ static void write_2d_cov_uv(GrVertexWriter* vb, const GrQuadPerEdgeAA::VertexSpe
}
// NOTE: The three _strict specializations below match the non-strict uv functions above, except
// that they also write the UV domain. These are included to benefit SkiaRenderer, which must make
// use of both fast and strict constrained domains. When testing _strict was not that common across
// that they also write the UV subset. These are included to benefit SkiaRenderer, which must make
// use of both fast and strict constrained subsets. When testing _strict was not that common across
// GMS, SKPs, and SVGs but we have little visibility into actual SkiaRenderer statistics. If
// SkiaRenderer can avoid domains more, these 3 functions should probably be removed for simplicity.
// SkiaRenderer can avoid subsets more, these 3 functions should probably be removed for simplicity.
// 2D (XY), no explicit coverage, UV locals, no color, tex domain but no geometry domain
// 2D (XY), no explicit coverage, UV locals, no color, tex subset but no geometry subset
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kNone);
SkASSERT(!spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(spec.hasSubset());
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), texSubset);
}
}
// 2D (XY), no explicit coverage, UV locals, vertex color, tex domain but no geometry domain
// 2D (XY), no explicit coverage, UV locals, vertex color, tex subset but no geometry subset
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kNone ||
spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithColor);
SkASSERT(spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(spec.hasSubset());
SkASSERT(localQuad);
bool wide = spec.colorType() == GrQuadPerEdgeAA::ColorType::kFloat;
@ -215,28 +215,28 @@ static void write_2d_color_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::
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);
localQuad->x(i), localQuad->y(i), texSubset);
}
}
// 2D (XY), explicit coverage, UV locals, no color, tex domain but no geometry domain
// 2D (XY), explicit coverage, UV locals, no color, tex subset but no geometry subset
// 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 float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain) {
const SkRect& geomSubset, const SkRect& texSubset) {
// Assert assumptions about VertexSpec
SkASSERT(spec.deviceQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective);
SkASSERT(spec.coverageMode() == GrQuadPerEdgeAA::CoverageMode::kWithPosition);
SkASSERT(!spec.hasVertexColors());
SkASSERT(!spec.requiresGeometryDomain());
SkASSERT(spec.hasDomain());
SkASSERT(!spec.requiresGeometrySubset());
SkASSERT(spec.hasSubset());
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);
localQuad->x(i), localQuad->y(i), texSubset);
}
}
@ -266,10 +266,10 @@ ColorType MinColorType(SkPMColor4f color) {
////////////////// Tessellator Implementation
Tessellator::WriteQuadProc Tessellator::GetWriteQuadProc(const VertexSpec& spec) {
// All specialized writing functions requires 2D geometry and no geometry domain. This is not
// All specialized writing functions requires 2D geometry and no geometry subset. This is not
// the same as just checking device type vs. kRectilinear since non-AA general 2D quads do not
// require a geometry domain and could then go through a fast path.
if (spec.deviceQuadType() != GrQuad::Type::kPerspective && !spec.requiresGeometryDomain()) {
// require a geometry subset and could then go through a fast path.
if (spec.deviceQuadType() != GrQuad::Type::kPerspective && !spec.requiresGeometrySubset()) {
CoverageMode mode = spec.coverageMode();
if (spec.hasVertexColors()) {
if (mode != CoverageMode::kWithPosition) {
@ -279,7 +279,7 @@ Tessellator::WriteQuadProc Tessellator::GetWriteQuadProc(const VertexSpec& spec)
return write_2d_color;
} else if (spec.localQuadType() != GrQuad::Type::kPerspective) {
// UV locals with vertex colors (possibly with coverage-as-alpha)
return spec.hasDomain() ? write_2d_color_uv_strict : write_2d_color_uv;
return spec.hasSubset() ? write_2d_color_uv_strict : write_2d_color_uv;
}
}
// Else fall through; this is a spec that requires vertex colors and explicit coverage,
@ -288,10 +288,10 @@ Tessellator::WriteQuadProc Tessellator::GetWriteQuadProc(const VertexSpec& spec)
} else if (spec.hasLocalCoords() && spec.localQuadType() != GrQuad::Type::kPerspective) {
if (mode == CoverageMode::kWithPosition) {
// UV locals with explicit coverage
return spec.hasDomain() ? write_2d_cov_uv_strict : write_2d_cov_uv;
return spec.hasSubset() ? write_2d_cov_uv_strict : write_2d_cov_uv;
} else {
SkASSERT(mode == CoverageMode::kNone);
return spec.hasDomain() ? write_2d_uv_strict : write_2d_uv;
return spec.hasSubset() ? write_2d_uv_strict : write_2d_uv;
}
}
// Else fall through to generic vertex function; this is a spec that has no vertex colors
@ -308,7 +308,7 @@ Tessellator::Tessellator(const VertexSpec& spec, char* vertices)
, fWriteProc(Tessellator::GetWriteQuadProc(spec)) {}
void Tessellator::append(GrQuad* deviceQuad, GrQuad* localQuad,
const SkPMColor4f& color, const SkRect& uvDomain, GrQuadAAFlags aaFlags) {
const SkPMColor4f& color, const SkRect& uvSubset, 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);
@ -318,28 +318,28 @@ void Tessellator::append(GrQuad* deviceQuad, GrQuad* localQuad,
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};
static const SkRect kIgnoredDomain = SkRect::MakeEmpty();
static const SkRect kIgnoredSubset = SkRect::MakeEmpty();
if (fVertexSpec.usesCoverageAA()) {
SkASSERT(fVertexSpec.coverageMode() == CoverageMode::kWithColor ||
fVertexSpec.coverageMode() == CoverageMode::kWithPosition);
// Must calculate inner and outer quadrilaterals for the vertex coverage ramps, and possibly
// a geometry domain if corners are not right angles
SkRect geomDomain;
if (fVertexSpec.requiresGeometryDomain()) {
geomDomain = deviceQuad->bounds();
geomDomain.outset(0.5f, 0.5f); // account for AA expansion
// a geometry subset if corners are not right angles
SkRect geomSubset;
if (fVertexSpec.requiresGeometrySubset()) {
geomSubset = deviceQuad->bounds();
geomSubset.outset(0.5f, 0.5f); // account for AA expansion
}
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(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
geomDomain, uvDomain);
geomSubset, uvSubset);
// 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(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
geomDomain, uvDomain);
geomSubset, uvSubset);
} else {
// Reset the tessellation helper to match the current geometry
fAAHelper.reset(*deviceQuad, localQuad);
@ -360,19 +360,19 @@ void Tessellator::append(GrQuad* deviceQuad, GrQuad* localQuad,
float coverage[4];
fAAHelper.inset(edgeDistances, deviceQuad, localQuad).store(coverage);
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, coverage, color,
geomDomain, uvDomain);
geomSubset, uvSubset);
// Then outer vertices, which use 0.f for their coverage
fAAHelper.outset(edgeDistances, deviceQuad, localQuad);
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kZeroCoverage, color,
geomDomain, uvDomain);
geomSubset, uvSubset);
}
} else {
// No outsetting needed, just write a single quad with full coverage
SkASSERT(fVertexSpec.coverageMode() == CoverageMode::kNone &&
!fVertexSpec.requiresGeometryDomain());
!fVertexSpec.requiresGeometrySubset());
fWriteProc(&fVertexWriter, fVertexSpec, deviceQuad, localQuad, kFullCoverage, color,
kIgnoredDomain, uvDomain);
kIgnoredSubset, uvSubset);
}
}
@ -459,10 +459,10 @@ int VertexSpec::localDimensionality() const {
CoverageMode VertexSpec::coverageMode() const {
if (this->usesCoverageAA()) {
if (this->compatibleWithCoverageAsAlpha() && this->hasVertexColors() &&
!this->requiresGeometryDomain()) {
// Using a geometric domain acts as a second source of coverage and folding
!this->requiresGeometrySubset()) {
// Using a geometric subset acts as a second source of coverage and folding
// the original coverage into color makes it impossible to apply the color's
// alpha to the geometric domain's coverage when the original shape is clipped.
// alpha to the geometric subset's coverage when the original shape is clipped.
return CoverageMode::kWithColor;
} else {
return CoverageMode::kWithPosition;
@ -494,7 +494,7 @@ size_t VertexSpec::vertexSize() const {
}
}
if (this->requiresGeometryDomain()) {
if (this->requiresGeometrySubset()) {
count += GrVertexAttribTypeSize(kFloat4_GrVertexAttribType);
}
@ -506,7 +506,7 @@ size_t VertexSpec::vertexSize() const {
count += GrVertexAttribTypeSize(kFloat4_GrVertexAttribType);
}
if (this->hasDomain()) {
if (this->hasSubset()) {
count += GrVertexAttribTypeSize(kFloat4_GrVertexAttribType);
}
@ -540,7 +540,7 @@ public:
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
// texturing, device-dimensions are single bit flags
uint32_t x = (fTexDomain.isInitialized() ? 0 : 0x1)
uint32_t x = (fTexSubset.isInitialized() ? 0 : 0x1)
| (fSampler.isInitialized() ? 0 : 0x2)
| (fNeedsPerspective ? 0 : 0x4)
| (fSaturate == Saturate::kNo ? 0 : 0x8);
@ -553,10 +553,10 @@ public:
x |= kUByte4_norm_GrVertexAttribType == fColor.cpuType() ? 0x40 : 0x80;
}
// and coverage mode, 00 for none, 01 for withposition, 10 for withcolor, 11 for
// position+geomdomain
SkASSERT(!fGeomDomain.isInitialized() || fCoverageMode == CoverageMode::kWithPosition);
// position+geomsubset
SkASSERT(!fGeomSubset.isInitialized() || fCoverageMode == CoverageMode::kWithPosition);
if (fCoverageMode != CoverageMode::kNone) {
x |= fGeomDomain.isInitialized()
x |= fGeomSubset.isInitialized()
? 0x300
: (CoverageMode::kWithPosition == fCoverageMode ? 0x100 : 0x200);
}
@ -632,7 +632,7 @@ public:
// If there is a texture, must also handle texture coordinates and reading from
// the texture in the fragment shader before continuing to fragment processors.
if (gp.fSampler.isInitialized()) {
// Texture coordinates clamped by the domain on the fragment shader; if the GP
// Texture coordinates clamped by the subset on the fragment shader; if the GP
// has a texture, it's guaranteed to have local coordinates
args.fFragBuilder->codeAppend("float2 texCoord;");
if (gp.fLocalCoord.cpuType() == kFloat3_GrVertexAttribType) {
@ -647,13 +647,13 @@ public:
args.fVaryingHandler->addPassThroughAttribute(gp.fLocalCoord, "texCoord");
}
// Clamp the now 2D localCoordName variable by the domain if it is provided
if (gp.fTexDomain.isInitialized()) {
args.fFragBuilder->codeAppend("float4 domain;");
args.fVaryingHandler->addPassThroughAttribute(gp.fTexDomain, "domain",
// Clamp the now 2D localCoordName variable by the subset if it is provided
if (gp.fTexSubset.isInitialized()) {
args.fFragBuilder->codeAppend("float4 subset;");
args.fVaryingHandler->addPassThroughAttribute(gp.fTexSubset, "subset",
Interpolation::kCanBeFlat);
args.fFragBuilder->codeAppend(
"texCoord = clamp(texCoord, domain.xy, domain.zw);");
"texCoord = clamp(texCoord, subset.xy, subset.zw);");
}
// Now modulate the starting output color by the texture lookup
@ -690,18 +690,18 @@ public:
args.fFragBuilder->codeAppendf("float coverage = %s;", coverage.fsIn());
}
if (gp.fGeomDomain.isInitialized()) {
// Calculate distance from sk_FragCoord to the 4 edges of the domain
if (gp.fGeomSubset.isInitialized()) {
// Calculate distance from sk_FragCoord to the 4 edges of the subset
// and clamp them to (0, 1). Use the minimum of these and the original
// coverage. This only has to be done in the exterior triangles, the
// interior of the quad geometry can never be clipped by the domain box.
args.fFragBuilder->codeAppend("float4 geoDomain;");
args.fVaryingHandler->addPassThroughAttribute(gp.fGeomDomain, "geoDomain",
// interior of the quad geometry can never be clipped by the subset box.
args.fFragBuilder->codeAppend("float4 geoSubset;");
args.fVaryingHandler->addPassThroughAttribute(gp.fGeomSubset, "geoSubset",
Interpolation::kCanBeFlat);
args.fFragBuilder->codeAppend(
"if (coverage < 0.5) {"
" float4 dists4 = clamp(float4(1, 1, -1, -1) * "
"(sk_FragCoord.xyxy - geoDomain), 0, 1);"
"(sk_FragCoord.xyxy - geoSubset), 0, 1);"
" float2 dists2 = dists4.xy * dists4.zw;"
" coverage = min(coverage, dists2.x * dists2.y);"
"}");
@ -712,7 +712,7 @@ public:
} else {
// Set coverage to 1, since it's either non-AA or the coverage was already
// folded into the output color
SkASSERT(!gp.fGeomDomain.isInitialized());
SkASSERT(!gp.fGeomSubset.isInitialized());
args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
}
}
@ -727,7 +727,7 @@ private:
QuadPerEdgeAAGeometryProcessor(const VertexSpec& spec)
: INHERITED(kQuadPerEdgeAAGeometryProcessor_ClassID)
, fTextureColorSpaceXform(nullptr) {
SkASSERT(!spec.hasDomain());
SkASSERT(!spec.hasSubset());
this->initializeAttrs(spec);
this->setTextureSamplerCnt(0);
}
@ -768,10 +768,10 @@ private:
}
}
// Need a geometry domain when the quads are AA and not rectilinear, since their AA
// Need a geometry subset when the quads are AA and not rectilinear, since their AA
// outsetting can go beyond a half pixel.
if (spec.requiresGeometryDomain()) {
fGeomDomain = {"geomDomain", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
if (spec.requiresGeometrySubset()) {
fGeomSubset = {"geomSubset", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
}
int localDim = spec.localDimensionality();
@ -785,8 +785,8 @@ private:
fColor = MakeColorAttribute("color", ColorType::kFloat == spec.colorType());
}
if (spec.hasDomain()) {
fTexDomain = {"texDomain", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
if (spec.hasSubset()) {
fTexSubset = {"texSubset", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
}
this->setVertexAttributes(&fPosition, 6);
@ -798,8 +798,8 @@ private:
Attribute fCoverage; // Used for non-perspective position to avoid Intel Metal issues
Attribute fColor; // May have coverage modulated in if the FPs support it
Attribute fLocalCoord;
Attribute fGeomDomain; // Screen-space bounding box on geometry+aa outset
Attribute fTexDomain; // Texture-space bounding box on local coords
Attribute fGeomSubset; // Screen-space bounding box on geometry+aa outset
Attribute fTexSubset; // Texture-space bounding box on local coords
// The positions attribute may have coverage built into it, so float3 is an ambiguous type
// and may mean 2d with coverage, or 3d with no coverage

View File

@ -29,7 +29,7 @@ namespace GrQuadPerEdgeAA {
using Saturate = GrTextureOp::Saturate;
enum class CoverageMode { kNone, kWithPosition, kWithColor };
enum class Domain : bool { kNo = false, kYes = true };
enum class Subset : bool { kNo = false, kYes = true };
enum class ColorType { kNone, kByte, kFloat, kLast = kFloat };
static const int kColorTypeCount = static_cast<int>(ColorType::kLast) + 1;
@ -47,7 +47,7 @@ namespace GrQuadPerEdgeAA {
ColorType MinColorType(SkPMColor4f);
// Specifies the vertex configuration for an op that renders per-edge AA quads. The vertex
// order (when enabled) is device position, color, local position, domain, aa edge equations.
// order (when enabled) is device position, color, local position, subset, aa edge equations.
// This order matches the constructor argument order of VertexSpec and is the order that
// GPAttributes maintains. If hasLocalCoords is false, then the local quad type can be ignored.
struct VertexSpec {
@ -58,23 +58,24 @@ namespace GrQuadPerEdgeAA {
, fIndexBufferOption(0) // kPictureFramed
, fHasLocalCoords(false)
, fColorType(0) // kNone
, fHasDomain(false)
, fHasSubset(false)
, fUsesCoverageAA(false)
, fCompatibleWithCoverageAsAlpha(false)
, fRequiresGeometryDomain(false) {}
, fRequiresGeometrySubset(false) {}
VertexSpec(GrQuad::Type deviceQuadType, ColorType colorType, GrQuad::Type localQuadType,
bool hasLocalCoords, Domain domain, GrAAType aa, bool coverageAsAlpha,
bool hasLocalCoords,
Subset subset, GrAAType aa, bool coverageAsAlpha,
IndexBufferOption indexBufferOption)
: fDeviceQuadType(static_cast<unsigned>(deviceQuadType))
, fLocalQuadType(static_cast<unsigned>(localQuadType))
, fIndexBufferOption(static_cast<unsigned>(indexBufferOption))
, fHasLocalCoords(hasLocalCoords)
, fColorType(static_cast<unsigned>(colorType))
, fHasDomain(static_cast<unsigned>(domain))
, fHasSubset(static_cast<unsigned>(subset))
, fUsesCoverageAA(aa == GrAAType::kCoverage)
, fCompatibleWithCoverageAsAlpha(coverageAsAlpha)
, fRequiresGeometryDomain(aa == GrAAType::kCoverage &&
, fRequiresGeometrySubset(aa == GrAAType::kCoverage &&
deviceQuadType > GrQuad::Type::kRectilinear) { }
GrQuad::Type deviceQuadType() const { return static_cast<GrQuad::Type>(fDeviceQuadType); }
@ -85,10 +86,10 @@ namespace GrQuadPerEdgeAA {
bool hasLocalCoords() const { return fHasLocalCoords; }
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
bool hasVertexColors() const { return ColorType::kNone != this->colorType(); }
bool hasDomain() const { return fHasDomain; }
bool hasSubset() const { return fHasSubset; }
bool usesCoverageAA() const { return fUsesCoverageAA; }
bool compatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
bool requiresGeometryDomain() const { return fRequiresGeometryDomain; }
bool requiresGeometrySubset() const { return fRequiresGeometrySubset; }
// Will always be 2 or 3
int deviceDimensionality() const;
// Will always be 0 if hasLocalCoords is false, otherwise will be 2 or 3
@ -122,12 +123,12 @@ namespace GrQuadPerEdgeAA {
unsigned fIndexBufferOption: 2;
unsigned fHasLocalCoords: 1;
unsigned fColorType : 2;
unsigned fHasDomain: 1;
unsigned fHasSubset : 1;
unsigned fUsesCoverageAA: 1;
unsigned fCompatibleWithCoverageAsAlpha: 1;
// The geometry domain serves to clip off pixels touched by quads with sharp corners that
// The geometry subset serves to clip off pixels touched by quads with sharp corners that
// would otherwise exceed the miter limit for the AA-outset geometry.
unsigned fRequiresGeometryDomain: 1;
unsigned fRequiresGeometrySubset : 1;
};
// A Tessellator is responsible for processing a series of device+local GrQuads into a VBO,
@ -143,7 +144,7 @@ namespace GrQuadPerEdgeAA {
// 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);
const SkPMColor4f& color, const SkRect& uvSubset, GrQuadAAFlags aaFlags);
SkDEBUGCODE(char* vertices() const { return (char*) fVertexWriter.fPtr; })
@ -155,7 +156,7 @@ namespace GrQuadPerEdgeAA {
typedef void (*WriteQuadProc)(GrVertexWriter* vertices, const VertexSpec& spec,
const GrQuad* deviceQuad, const GrQuad* localQuad,
const float coverage[4], const SkPMColor4f& color,
const SkRect& geomDomain, const SkRect& texDomain);
const SkRect& geomSubset, const SkRect& texSubset);
static WriteQuadProc GetWriteQuadProc(const VertexSpec& spec);
GrQuadUtils::TessellationHelper fAAHelper;

View File

@ -43,7 +43,7 @@
namespace {
using Domain = GrQuadPerEdgeAA::Domain;
using Subset = GrQuadPerEdgeAA::Subset;
using VertexSpec = GrQuadPerEdgeAA::VertexSpec;
using ColorType = GrQuadPerEdgeAA::ColorType;
@ -120,30 +120,30 @@ static NormalizationParams proxy_normalization_params(const GrSurfaceProxy* prox
}
}
static SkRect inset_domain_for_bilerp(const NormalizationParams& params, const SkRect& domainRect) {
static SkRect inset_subset_for_bilerp(const NormalizationParams& params, const SkRect& subsetRect) {
// Normalized pixel size is also equal to iw and ih, so the insets for bilerp are just
// in those units and can be applied safely after normalization. However, if the domain is
// in those units and can be applied safely after normalization. However, if the subset is
// smaller than a texel, it should clamp to the center of that axis.
float dw = domainRect.width() < params.fIW ? domainRect.width() : params.fIW;
float dh = domainRect.height() < params.fIH ? domainRect.height() : params.fIH;
return domainRect.makeInset(0.5f * dw, 0.5f * dh);
float dw = subsetRect.width() < params.fIW ? subsetRect.width() : params.fIW;
float dh = subsetRect.height() < params.fIH ? subsetRect.height() : params.fIH;
return subsetRect.makeInset(0.5f * dw, 0.5f * dh);
}
// Normalize the domain. If 'domainRect' is null, it is assumed no domain constraint is desired,
// Normalize the subset. If 'subsetRect' is null, it is assumed no subset constraint is desired,
// so a sufficiently large rect is returned even if the quad ends up batched with an op that uses
// domains overall.
static SkRect normalize_domain(GrSamplerState::Filter filter,
// subsets overall.
static SkRect normalize_subset(GrSamplerState::Filter filter,
const NormalizationParams& params,
const SkRect* domainRect) {
const SkRect* subsetRect) {
static constexpr SkRect kLargeRect = {-100000, -100000, 1000000, 1000000};
if (!domainRect) {
// Either the quad has no domain constraint and is batched with a domain constrained op
// (in which case we want a domain that doesn't restrict normalized tex coords), or the
// entire op doesn't use the domain, in which case the returned value is ignored.
if (!subsetRect) {
// Either the quad has no subset constraint and is batched with a subset constrained op
// (in which case we want a subset that doesn't restrict normalized tex coords), or the
// entire op doesn't use the subset, in which case the returned value is ignored.
return kLargeRect;
}
auto ltrb = skvx::Vec<4, float>::Load(domainRect);
auto ltrb = skvx::Vec<4, float>::Load(subsetRect);
// Normalize and offset
ltrb = mad(ltrb, {params.fIW, params.fIH, params.fIW, params.fIH},
{0.f, params.fYOffset, 0.f, params.fYOffset});
@ -197,10 +197,10 @@ public:
GrTextureOp::Saturate saturate,
GrAAType aaType,
DrawQuad* quad,
const SkRect* domain) {
const SkRect* subset) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<TextureOp>(std::move(proxyView), std::move(textureXform), filter,
color, saturate, aaType, quad, domain);
color, saturate, aaType, quad, subset);
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
@ -255,13 +255,13 @@ public:
while(i < fViewCountPairs[p].fQuadCnt && iter.next()) {
const GrQuad* quad = iter.deviceQuad();
GrQuad uv = iter.isLocalValid() ? *(iter.localQuad()) : GrQuad();
const ColorDomainAndAA& info = iter.metadata();
const ColorSubsetAndAA& info = iter.metadata();
str.appendf(
"%d: Color: 0x%08x, Domain(%d): [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n"
"%d: Color: 0x%08x, Subset(%d): [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n"
" UVs [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n"
" Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n",
i, info.fColor.toBytes_RGBA(), fMetadata.fDomain, info.fDomainRect.fLeft,
info.fDomainRect.fTop, info.fDomainRect.fRight, info.fDomainRect.fBottom,
i, info.fColor.toBytes_RGBA(), fMetadata.fSubset, info.fSubsetRect.fLeft,
info.fSubsetRect.fTop, info.fSubsetRect.fRight, info.fSubsetRect.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,
uv.point(0).fX, uv.point(0).fY, uv.point(1).fX, uv.point(1).fY,
@ -309,18 +309,18 @@ public:
private:
friend class ::GrOpMemoryPool;
struct ColorDomainAndAA {
ColorDomainAndAA(const SkPMColor4f& color, const SkRect& domainRect, GrQuadAAFlags aaFlags)
struct ColorSubsetAndAA {
ColorSubsetAndAA(const SkPMColor4f& color, const SkRect& subsetRect, GrQuadAAFlags aaFlags)
: fColor(color)
, fDomainRect(domainRect)
, fSubsetRect(subsetRect)
, fAAFlags(static_cast<uint16_t>(aaFlags)) {
SkASSERT(fAAFlags == static_cast<uint16_t>(aaFlags));
}
SkPMColor4f fColor;
// If the op doesn't use domains, this is ignored. If the op uses domains and the specific
// If the op doesn't use subsets, this is ignored. If the op uses subsets and the specific
// entry does not, this rect will equal kLargeRect, so it automatically has no effect.
SkRect fDomainRect;
SkRect fSubsetRect;
unsigned fAAFlags : 4;
GrQuadAAFlags aaFlags() const { return static_cast<GrQuadAAFlags>(fAAFlags); }
@ -340,14 +340,14 @@ private:
struct Metadata {
// AAType must be filled after initialization; ColorType is determined in finalize()
Metadata(const GrSwizzle& swizzle, GrSamplerState::Filter filter,
GrQuadPerEdgeAA::Domain domain, GrTextureOp::Saturate saturate)
GrQuadPerEdgeAA::Subset subset, GrTextureOp::Saturate saturate)
: fSwizzle(swizzle)
, fProxyCount(1)
, fTotalQuadCount(1)
, fFilter(static_cast<uint16_t>(filter))
, fAAType(static_cast<uint16_t>(GrAAType::kNone))
, fColorType(static_cast<uint16_t>(ColorType::kNone))
, fDomain(static_cast<uint16_t>(domain))
, fSubset(static_cast<uint16_t>(subset))
, fSaturate(static_cast<uint16_t>(saturate)) {}
GrSwizzle fSwizzle; // sizeof(GrSwizzle) == uint16_t
@ -359,7 +359,7 @@ private:
uint16_t fFilter : 2; // GrSamplerState::Filter
uint16_t fAAType : 2; // GrAAType
uint16_t fColorType : 2; // GrQuadPerEdgeAA::ColorType
uint16_t fDomain : 1; // bool
uint16_t fSubset : 1; // bool
uint16_t fSaturate : 1; // bool
uint16_t fUnused : 8; // # of bits left before Metadata exceeds 8 bytes
@ -368,7 +368,7 @@ private:
}
GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
Domain domain() const { return static_cast<Domain>(fDomain); }
Subset subset() const { return static_cast<Subset>(fSubset); }
GrTextureOp::Saturate saturate() const {
return static_cast<GrTextureOp::Saturate>(fSaturate);
}
@ -418,7 +418,7 @@ private:
};
// If domainRect is not null it will be used to apply a strict src rect-style constraint.
// If subsetRect is not null it will be used to apply a strict src rect-style constraint.
TextureOp(GrSurfaceProxyView proxyView,
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
GrSamplerState::Filter filter,
@ -426,12 +426,12 @@ private:
GrTextureOp::Saturate saturate,
GrAAType aaType,
DrawQuad* quad,
const SkRect* domainRect)
const SkRect* subsetRect)
: INHERITED(ClassID())
, fQuads(1, true /* includes locals */)
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
, fDesc(nullptr)
, fMetadata(proxyView.swizzle(), filter, Domain(!!domainRect), saturate) {
, fMetadata(proxyView.swizzle(), filter, Subset(!!subsetRect), saturate) {
// Clean up disparities between the overall aa type and edge configuration and apply
// optimizations based on the rect and matrix when appropriate
@ -440,30 +440,30 @@ private:
fMetadata.fAAType = static_cast<uint16_t>(aaType);
// We expect our caller to have already caught this optimization.
SkASSERT(!domainRect ||
!domainRect->contains(proxyView.proxy()->backingStoreBoundsRect()));
SkASSERT(!subsetRect ||
!subsetRect->contains(proxyView.proxy()->backingStoreBoundsRect()));
// We may have had a strict constraint with nearest filter solely due to possible AA bloat.
// If we don't have (or determined we don't need) coverage AA then we can skip using a
// domain.
if (domainRect && filter == GrSamplerState::Filter::kNearest &&
// subset.
if (subsetRect && filter == GrSamplerState::Filter::kNearest &&
aaType != GrAAType::kCoverage) {
domainRect = nullptr;
fMetadata.fDomain = static_cast<uint16_t>(Domain::kNo);
subsetRect = nullptr;
fMetadata.fSubset = static_cast<uint16_t>(Subset::kNo);
}
// Normalize src coordinates and the domain (if set)
// Normalize src coordinates and the subset (if set)
NormalizationParams params = proxy_normalization_params(proxyView.proxy(),
proxyView.origin());
normalize_src_quad(params, &quad->fLocal);
SkRect domain = normalize_domain(filter, params, domainRect);
SkRect subset = normalize_subset(filter, params, subsetRect);
// Set bounds before clipping so we don't have to worry about unioning the bounds of
// the two potential quads (GrQuad::bounds() is perspective-safe).
this->setBounds(quad->fDevice.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
IsHairline::kNo);
int quadCount = this->appendQuad(quad, color, domain);
int quadCount = this->appendQuad(quad, color, subset);
fViewCountPairs[0] = {proxyView.detachProxy(), quadCount};
}
@ -481,7 +481,7 @@ private:
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
, fDesc(nullptr)
, fMetadata(set[0].fProxyView.swizzle(), GrSamplerState::Filter::kNearest,
Domain::kNo, saturate) {
Subset::kNo, saturate) {
// Update counts to reflect the batch op
fMetadata.fProxyCount = SkToUInt(proxyRunCnt);
fMetadata.fTotalQuadCount = SkToUInt(cnt);
@ -489,7 +489,7 @@ private:
SkRect bounds = SkRectPriv::MakeLargestInverted();
GrAAType netAAType = GrAAType::kNone; // aa type maximally compatible with all dst rects
Domain netDomain = Domain::kNo;
Subset netSubset = Subset::kNo;
GrSamplerState::Filter netFilter = GrSamplerState::Filter::kNearest;
const GrSurfaceProxy* curProxy = nullptr;
@ -561,7 +561,7 @@ private:
}
// Calculate metadata for the entry
const SkRect* domainForQuad = nullptr;
const SkRect* subsetForQuad = nullptr;
if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
// Check (briefly) if the strict constraint is needed for this set entry
if (!set[q].fSrcRect.contains(curProxy->backingStoreBoundsRect()) &&
@ -570,20 +570,20 @@ private:
// Can't rely on hardware clamping and the draw will access outer texels
// for AA and/or bilerp. Unlike filter quality, this op still has per-quad
// control over AA so that can check aaForQuad, not netAAType.
netDomain = Domain::kYes;
domainForQuad = &set[q].fSrcRect;
netSubset = Subset::kYes;
subsetForQuad = &set[q].fSrcRect;
}
}
// This domain may represent a no-op, otherwise it will have the origin and dimensions
// This subset may represent a no-op, otherwise it will have the origin and dimensions
// of the texture applied to it. Insetting for bilinear filtering is deferred until
// on[Pre]Prepare so that the overall filter can be lazily determined.
SkRect domain = normalize_domain(filter, proxyParams, domainForQuad);
SkRect subset = normalize_subset(filter, proxyParams, subsetForQuad);
// Always append a quad (or 2 if perspective clipped), it just may refer back to a prior
// ViewCountPair (this frequently happens when Chrome draws 9-patches).
float alpha = SkTPin(set[q].fAlpha, 0.f, 1.f);
fViewCountPairs[p].fQuadCnt += this->appendQuad(
&quad, {alpha, alpha, alpha, alpha}, domain);
&quad, {alpha, alpha, alpha, alpha}, subset);
}
// The # of proxy switches should match what was provided (+1 because we incremented p
// when a new proxy was encountered).
@ -592,12 +592,12 @@ private:
fMetadata.fAAType = static_cast<uint16_t>(netAAType);
fMetadata.fFilter = static_cast<uint16_t>(netFilter);
fMetadata.fDomain = static_cast<uint16_t>(netDomain);
fMetadata.fSubset = static_cast<uint16_t>(netSubset);
this->setBounds(bounds, HasAABloat(netAAType == GrAAType::kCoverage), IsHairline::kNo);
}
int appendQuad(DrawQuad* quad, const SkPMColor4f& color, const SkRect& domain) {
int appendQuad(DrawQuad* quad, const SkPMColor4f& color, const SkRect& subset) {
DrawQuad extra;
// Only clip when there's anti-aliasing. When non-aa, the GPU clips just fine and there's
// no inset/outset math that requires w > 0.
@ -609,9 +609,9 @@ private:
quad->fEdgeFlags = GrQuadAAFlags::kNone;
quadCount = 1;
}
fQuads.append(quad->fDevice, {color, domain, quad->fEdgeFlags}, &quad->fLocal);
fQuads.append(quad->fDevice, {color, subset, quad->fEdgeFlags}, &quad->fLocal);
if (quadCount > 1) {
fQuads.append(extra.fDevice, {color, domain, extra.fEdgeFlags}, &extra.fLocal);
fQuads.append(extra.fDevice, {color, subset, extra.fEdgeFlags}, &extra.fLocal);
fMetadata.fTotalQuadCount++;
}
return quadCount;
@ -698,11 +698,11 @@ private:
for (int i = 0; i < quadCnt && iter.next(); ++i) {
SkASSERT(iter.isLocalValid());
const ColorDomainAndAA& info = iter.metadata();
const ColorSubsetAndAA& info = iter.metadata();
tessellator.append(iter.deviceQuad(), iter.localQuad(), info.fColor,
inset ? inset_domain_for_bilerp(params, info.fDomainRect)
: info.fDomainRect,
inset ? inset_subset_for_bilerp(params, info.fSubsetRect)
: info.fSubsetRect,
info.aaFlags());
}
@ -763,7 +763,7 @@ private:
GrQuad::Type quadType = GrQuad::Type::kAxisAligned;
ColorType colorType = ColorType::kNone;
GrQuad::Type srcQuadType = GrQuad::Type::kAxisAligned;
Domain domain = Domain::kNo;
Subset subset = Subset::kNo;
GrAAType overallAAType = fMetadata.aaType();
desc->fNumProxies = 0;
@ -777,8 +777,8 @@ private:
if (op.fQuads.localQuadType() > srcQuadType) {
srcQuadType = op.fQuads.localQuadType();
}
if (op.fMetadata.domain() == Domain::kYes) {
domain = Domain::kYes;
if (op.fMetadata.subset() == Subset::kYes) {
subset = Subset::kYes;
}
colorType = std::max(colorType, op.fMetadata.colorType());
desc->fNumProxies += op.fMetadata.fProxyCount;
@ -801,7 +801,7 @@ private:
maxQuadsPerMesh);
desc->fVertexSpec = VertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true,
domain, overallAAType, /* alpha as coverage */ true,
subset, overallAAType, /* alpha as coverage */ true,
indexBufferOption);
SkASSERT(desc->fNumTotalQuads <= GrQuadPerEdgeAA::QuadLimit(indexBufferOption));
@ -922,8 +922,8 @@ private:
return CombineResult::kCannotCombine;
}
if (fMetadata.domain() != that->fMetadata.domain()) {
// It is technically possible to combine operations across domain modes, but performance
if (fMetadata.subset() != that->fMetadata.subset()) {
// It is technically possible to combine operations across subset modes, but performance
// testing suggests it's better to make more draw calls where some take advantage of
// the more optimal shader path without coordinate clamping.
return CombineResult::kCannotCombine;
@ -967,7 +967,7 @@ private:
return CombineResult::kCannotCombine;
}
fMetadata.fDomain |= that->fMetadata.fDomain;
fMetadata.fSubset |= that->fMetadata.fSubset;
fMetadata.fColorType = std::max(fMetadata.fColorType, that->fMetadata.fColorType);
if (upgradeToCoverageAAOnMerge) {
fMetadata.fAAType = static_cast<uint16_t>(GrAAType::kCoverage);
@ -981,7 +981,7 @@ private:
return CombineResult::kMerged;
}
GrQuadBuffer<ColorDomainAndAA> fQuads;
GrQuadBuffer<ColorSubsetAndAA> fQuads;
sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
// Most state of TextureOp is packed into these two field to minimize the op's size.
// Historically, increasing the size of TextureOp has caused surprising perf regressions, so
@ -1015,11 +1015,11 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
SkBlendMode blendMode,
GrAAType aaType,
DrawQuad* quad,
const SkRect* domain) {
const SkRect* subset) {
// Apply optimizations that are valid whether or not using GrTextureOp or GrFillRectOp
if (domain && domain->contains(proxyView.proxy()->backingStoreBoundsRect())) {
// No need for a shader-based domain if hardware clamping achieves the same effect
domain = nullptr;
if (subset && subset->contains(proxyView.proxy()->backingStoreBoundsRect())) {
// No need for a shader-based subset if hardware clamping achieves the same effect
subset = nullptr;
}
if (filter != GrSamplerState::Filter::kNearest &&
@ -1029,7 +1029,7 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
if (blendMode == SkBlendMode::kSrcOver) {
return TextureOp::Make(context, std::move(proxyView), std::move(textureXform), filter,
color, saturate, aaType, std::move(quad), domain);
color, saturate, aaType, std::move(quad), subset);
} else {
// Emulate complex blending using GrFillRectOp
GrPaint paint;
@ -1037,15 +1037,15 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
std::unique_ptr<GrFragmentProcessor> fp;
if (domain) {
if (subset) {
const auto& caps = *context->priv().caps();
SkRect localRect;
if (quad->fLocal.asRect(&localRect)) {
fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter,
*domain, localRect, caps);
*subset, localRect, caps);
} else {
fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter,
*domain, caps);
*subset, caps);
}
} else {
fp = GrTextureEffect::Make(std::move(proxyView), alphaType, SkMatrix::I(), filter);
@ -1160,12 +1160,12 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
quad.fLocal = GrQuad(set[i].fSrcRect);
}
const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint
const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint
? &set[i].fSrcRect : nullptr;
auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform,
filter, {alpha, alpha, alpha, alpha}, saturate, blendMode, aaType,
&quad, domain);
&quad, subset);
rtc->addDrawOp(clip, std::move(op));
}
return;
@ -1290,7 +1290,7 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
bool useDomain = random->nextBool();
bool useSubset = random->nextBool();
auto saturate = random->nextBool() ? GrTextureOp::Saturate::kYes : GrTextureOp::Saturate::kNo;
GrSurfaceProxyView proxyView(
std::move(proxy), origin,
@ -1301,7 +1301,7 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
DrawQuad quad = {GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect), aaFlags};
return GrTextureOp::Make(context, std::move(proxyView), alphaType, std::move(texXform), filter,
color, saturate, SkBlendMode::kSrcOver, aaType,
&quad, useDomain ? &srcRect : nullptr);
&quad, useSubset ? &srcRect : nullptr);
}
#endif

View File

@ -32,7 +32,7 @@ public:
/**
* Creates an op that draws a sub-quadrilateral of a texture. The passed color is modulated by
* the texture's color. 'deviceQuad' specifies the device-space coordinates to draw, using
* 'localQuad' to map into the proxy's texture space. If non-null, 'domain' represents the
* 'localQuad' to map into the proxy's texture space. If non-null, 'subset' represents the
* boundary for the strict src rect constraint. If GrAAType is kCoverage then AA is applied to
* the edges indicated by GrQuadAAFlags. Otherwise, GrQuadAAFlags is ignored.
*
@ -50,7 +50,7 @@ public:
SkBlendMode,
GrAAType,
DrawQuad*,
const SkRect* domain = nullptr);
const SkRect* subset = nullptr);
// Automatically falls back to using one GrFillRectOp per entry if dynamic states are not
// supported, or if the blend mode is not src-over. 'cnt' is the size of the entry array.