Revert "Track quad type on GrQuad directly"
This reverts commit 85766c4cd367596268588f53631a1c43376c929d.
Reason for revert: red - so much red
Original change's description:
> Track quad type on GrQuad directly
>
> This makes subsequent higher-level drawing APIs more compact, and
> shouldn't come with a performance hit. Everywhere we used to need
> a GrPerspQuad, we'd also take the GrQuadType as a second argument.
> The quad list types already deconstruct the quad so there's no
> extra overhead in the op's memory usage.
>
> It also improves usability and decreases the likelihood that an
> incorrect quad type is ever associated with the quad.
>
> Bug: skia:
> Change-Id: Iba908fb133ad664744a5788a7088d90de0d3a1c2
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/214820
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
TBR=bsalomon@google.com,robertphillips@google.com,michaelludwig@google.com
Change-Id: Ied594673116fb901287b334fea41da3c71494fb1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/215607
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrQuad.cpp b/src/gpu/GrQuad.cpp
index bd01a68..379d1f6 100644
--- a/src/gpu/GrQuad.cpp
+++ b/src/gpu/GrQuad.cpp
@@ -69,39 +69,10 @@
*ys = V4f{skQuadPts[0].fY, skQuadPts[3].fY, skQuadPts[1].fY, skQuadPts[2].fY};
}
-// If an SkRect is transformed by this matrix, what class of quad is required to represent it.
-static GrQuadType quad_type_for_transformed_rect(const SkMatrix& matrix) {
- if (matrix.rectStaysRect()) {
- return GrQuadType::kRect;
- } else if (matrix.preservesRightAngles()) {
- return GrQuadType::kRectilinear;
- } else if (matrix.hasPerspective()) {
- return GrQuadType::kPerspective;
- } else {
- return GrQuadType::kStandard;
- }
-}
-
-// Perform minimal analysis of 'pts' (which are suitable for MakeFromSkQuad), and determine a
-// quad type that will be as minimally general as possible.
-static GrQuadType quad_type_for_points(const SkPoint pts[4], const SkMatrix& matrix) {
- if (matrix.hasPerspective()) {
- return GrQuadType::kPerspective;
- }
- // If 'pts' was formed by SkRect::toQuad() and not transformed further, it is safe to use the
- // quad type derived from 'matrix'. Otherwise don't waste any more time and assume kStandard
- // (most general 2D quad).
- if ((pts[0].fX == pts[3].fX && pts[1].fX == pts[2].fX) &&
- (pts[0].fY == pts[1].fY && pts[2].fY == pts[3].fY)) {
- return quad_type_for_transformed_rect(matrix);
- } else {
- return GrQuadType::kStandard;
- }
-}
-
template <typename Q>
void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
- const Q& quad, GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
+ const Q& quad, GrQuadType knownType,
+ GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
// Most cases will keep the requested types unchanged
*outAAType = requestedAAType;
*outEdgeFlags = requestedEdgeFlags;
@@ -115,7 +86,7 @@
} else {
// For coverage AA, if the quad is a rect and it lines up with pixel boundaries
// then overall aa and per-edge aa can be completely disabled
- if (quad.quadType() == GrQuadType::kRect && !quad.aaHasEffectOnRect()) {
+ if (knownType == GrQuadType::kRect && !quad.aaHasEffectOnRect()) {
*outAAType = GrAAType::kNone;
*outEdgeFlags = GrQuadAAFlags::kNone;
}
@@ -136,46 +107,58 @@
};
// Instantiate GrResolve... for GrQuad and GrPerspQuad
-template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrQuad&,
+template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrQuad&, GrQuadType,
GrAAType*, GrQuadAAFlags*);
-template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrPerspQuad&,
+template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrPerspQuad&, GrQuadType,
GrAAType*, GrQuadAAFlags*);
+GrQuadType GrQuadTypeForTransformedRect(const SkMatrix& matrix) {
+ if (matrix.rectStaysRect()) {
+ return GrQuadType::kRect;
+ } else if (matrix.preservesRightAngles()) {
+ return GrQuadType::kRectilinear;
+ } else if (matrix.hasPerspective()) {
+ return GrQuadType::kPerspective;
+ } else {
+ return GrQuadType::kStandard;
+ }
+}
+
+GrQuadType GrQuadTypeForPoints(const SkPoint pts[4], const SkMatrix& matrix) {
+ if (matrix.hasPerspective()) {
+ return GrQuadType::kPerspective;
+ }
+ // If 'pts' was formed by SkRect::toQuad() and not transformed further, it is safe to use the
+ // quad type derived from 'matrix'. Otherwise don't waste any more time and assume kStandard
+ // (most general 2D quad).
+ if ((pts[0].fX == pts[3].fX && pts[1].fX == pts[2].fX) &&
+ (pts[0].fY == pts[1].fY && pts[2].fY == pts[3].fY)) {
+ return GrQuadTypeForTransformedRect(matrix);
+ } else {
+ return GrQuadType::kStandard;
+ }
+}
+
GrQuad GrQuad::MakeFromRect(const SkRect& rect, const SkMatrix& m) {
V4f x, y;
SkMatrix::TypeMask tm = m.getType();
- GrQuadType type;
if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
map_rect_translate_scale(rect, m, &x, &y);
- type = GrQuadType::kRect;
} else {
map_rect_general(rect, m, &x, &y, nullptr);
- type = quad_type_for_transformed_rect(m);
- if (type == GrQuadType::kPerspective) {
- // While the matrix created perspective, the coordinates were projected to a 2D quad
- // in map_rect_general since no w V4f was provided.
- type = GrQuadType::kStandard;
- }
}
- return GrQuad(x, y, type);
+ return GrQuad(x, y);
}
GrQuad GrQuad::MakeFromSkQuad(const SkPoint pts[4], const SkMatrix& matrix) {
V4f xs, ys;
rearrange_sk_to_gr_points(pts, &xs, &ys);
- GrQuadType type = quad_type_for_points(pts, matrix);
- if (type == GrQuadType::kPerspective) {
- // While the matrix created perspective, the coordinates were projected to a 2D quad
- // in map_rect_general since no w V4f was provided.
- type = GrQuadType::kStandard;
- }
-
if (matrix.isIdentity()) {
- return GrQuad(xs, ys, type);
+ return GrQuad(xs, ys);
} else {
V4f mx, my;
map_quad_general(xs, ys, matrix, &mx, &my, nullptr);
- return GrQuad(mx, my, type);
+ return GrQuad(mx, my);
}
}
@@ -184,8 +167,7 @@
}
// Private constructor used by GrQuadList to quickly fill in a quad's values from the channel arrays
-GrPerspQuad::GrPerspQuad(const float* xs, const float* ys, const float* ws, GrQuadType type)
- : fType(type) {
+GrPerspQuad::GrPerspQuad(const float* xs, const float* ys, const float* ws) {
memcpy(fX, xs, 4 * sizeof(float));
memcpy(fY, ys, 4 * sizeof(float));
memcpy(fW, ws, 4 * sizeof(float));
@@ -194,28 +176,24 @@
GrPerspQuad GrPerspQuad::MakeFromRect(const SkRect& rect, const SkMatrix& m) {
V4f x, y, w;
SkMatrix::TypeMask tm = m.getType();
- GrQuadType type;
if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
map_rect_translate_scale(rect, m, &x, &y);
w = 1.f;
- type = GrQuadType::kRect;
} else {
map_rect_general(rect, m, &x, &y, &w);
- type = quad_type_for_transformed_rect(m);
}
- return GrPerspQuad(x, y, w, type);
+ return GrPerspQuad(x, y, w);
}
GrPerspQuad GrPerspQuad::MakeFromSkQuad(const SkPoint pts[4], const SkMatrix& matrix) {
V4f xs, ys;
rearrange_sk_to_gr_points(pts, &xs, &ys);
- GrQuadType type = quad_type_for_points(pts, matrix);
if (matrix.isIdentity()) {
- return GrPerspQuad(xs, ys, 1.f, type);
+ return GrPerspQuad(xs, ys, 1.f);
} else {
V4f mx, my, mw;
map_quad_general(xs, ys, matrix, &mx, &my, &mw);
- return GrPerspQuad(mx, my, mw, type);
+ return GrPerspQuad(mx, my, mw);
}
}
diff --git a/src/gpu/GrQuad.h b/src/gpu/GrQuad.h
index cb2f15d..73b7310 100644
--- a/src/gpu/GrQuad.h
+++ b/src/gpu/GrQuad.h
@@ -34,12 +34,19 @@
};
static const int kGrQuadTypeCount = static_cast<int>(GrQuadType::kLast) + 1;
+// If an SkRect is transformed by this matrix, what class of quad is required to represent it.
+GrQuadType GrQuadTypeForTransformedRect(const SkMatrix& matrix);
+// Perform minimal analysis of 'pts' (which are suitable for MakeFromSkQuad), and determine a
+// quad type that will be as minimally general as possible.
+GrQuadType GrQuadTypeForPoints(const SkPoint pts[4], const SkMatrix& matrix);
+
// Resolve disagreements between the overall requested AA type and the per-edge quad AA flags.
// knownQuadType must have come from GrQuadTypeForTransformedRect with the matrix that created the
// provided quad. Both outAAType and outEdgeFlags will be updated.
template <typename Q>
void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
- const Q& quad, GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
+ const Q& quad, GrQuadType knownQuadType,
+ GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
/**
* GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
@@ -53,15 +60,17 @@
explicit GrQuad(const SkRect& rect)
: fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
- , fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
- , fType(GrQuadType::kRect) {}
+ , fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom} {}
- GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, GrQuadType type)
- : fType(type) {
+ GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys) {
xs.store(fX);
ys.store(fY);
}
+ explicit GrQuad(const SkPoint pts[4])
+ : fX{pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX}
+ , fY{pts[0].fY, pts[1].fY, pts[2].fY, pts[3].fY} {}
+
/** Sets the quad to the rect as transformed by the matrix. */
static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
@@ -86,8 +95,6 @@
skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
- GrQuadType quadType() const { return fType; }
-
// True if anti-aliasing affects this quad. Only valid when quadType == kRect_QuadType
bool aaHasEffectOnRect() const;
@@ -97,8 +104,6 @@
float fX[4];
float fY[4];
-
- GrQuadType fType;
};
class GrPerspQuad {
@@ -108,21 +113,16 @@
explicit GrPerspQuad(const SkRect& rect)
: fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
, fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
- , fW{1.f, 1.f, 1.f, 1.f}
- , fType(GrQuadType::kRect) {}
+ , fW{1.f, 1.f, 1.f, 1.f} {}
- GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
- GrQuadType type)
- : fType(type) {
- SkASSERT(type != GrQuadType::kPerspective);
+ GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys) {
xs.store(fX);
ys.store(fY);
fW[0] = fW[1] = fW[2] = fW[3] = 1.f;
}
GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
- const skvx::Vec<4, float>& ws, GrQuadType type)
- : fType(type) {
+ const skvx::Vec<4, float>& ws) {
xs.store(fX);
ys.store(fY);
ws.store(fW);
@@ -139,10 +139,10 @@
SkPoint3 point(int i) const { return {fX[i], fY[i], fW[i]}; }
- SkRect bounds() const {
+ SkRect bounds(GrQuadType type) const {
auto x = this->x4f();
auto y = this->y4f();
- if (fType == GrQuadType::kPerspective) {
+ if (type == GrQuadType::kPerspective) {
auto iw = this->iw4f();
x *= iw;
y *= iw;
@@ -161,9 +161,7 @@
skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }
- GrQuadType quadType() const { return fType; }
-
- bool hasPerspective() const { return fType == GrQuadType::kPerspective; }
+ bool hasPerspective() const { return any(w4f() != 1.f); }
// True if anti-aliasing affects this quad. Only valid when quadType == kRect_QuadType
bool aaHasEffectOnRect() const;
@@ -173,13 +171,11 @@
friend class GrQuadListBase;
// Copy 4 values from each of the arrays into the quad's components
- GrPerspQuad(const float xs[4], const float ys[4], const float ws[4], GrQuadType type);
+ GrPerspQuad(const float xs[4], const float ys[4], const float ws[4]);
float fX[4];
float fY[4];
float fW[4];
-
- GrQuadType fType;
};
// Underlying data used by GrQuadListBase. It is defined outside of GrQuadListBase due to compiler
@@ -209,9 +205,9 @@
GrQuadType quadType() const { return fType; }
- void reserve(int count, bool needsPerspective) {
+ void reserve(int count, GrQuadType forType) {
fXYs.reserve(count);
- if (needsPerspective || fType == GrQuadType::kPerspective) {
+ if (forType == GrQuadType::kPerspective || fType == GrQuadType::kPerspective) {
fWs.reserve(4 * count);
}
}
@@ -223,11 +219,11 @@
const QuadData<T>& item = fXYs[i];
if (fType == GrQuadType::kPerspective) {
// Read the explicit ws
- return GrPerspQuad(item.fX, item.fY, fWs.begin() + 4 * i, fType);
+ return GrPerspQuad(item.fX, item.fY, fWs.begin() + 4 * i);
} else {
// Ws are implicitly 1s.
static constexpr float kNoPerspectiveWs[4] = {1.f, 1.f, 1.f, 1.f};
- return GrPerspQuad(item.fX, item.fY, kNoPerspectiveWs, fType);
+ return GrPerspQuad(item.fX, item.fY, kNoPerspectiveWs);
}
}
@@ -253,8 +249,8 @@
}
// Returns the added item data so that its metadata can be initialized if T is not void
- QuadData<T>& pushBackImpl(const GrQuad& quad) {
- this->upgradeType(quad.quadType());
+ QuadData<T>& pushBackImpl(const GrQuad& quad, GrQuadType type) {
+ this->upgradeType(type);
QuadData<T>& item = fXYs.push_back();
memcpy(item.fX, quad.fX, 4 * sizeof(float));
memcpy(item.fY, quad.fY, 4 * sizeof(float));
@@ -264,8 +260,8 @@
return item;
}
- QuadData<T>& pushBackImpl(const GrPerspQuad& quad) {
- this->upgradeType(quad.quadType());
+ QuadData<T>& pushBackImpl(const GrPerspQuad& quad, GrQuadType type) {
+ this->upgradeType(type);
QuadData<T>& item = fXYs.push_back();
memcpy(item.fX, quad.fX, 4 * sizeof(float));
memcpy(item.fY, quad.fY, 4 * sizeof(float));
@@ -313,12 +309,12 @@
this->concatImpl(that);
}
- void push_back(const GrQuad& quad) {
- this->pushBackImpl(quad);
+ void push_back(const GrQuad& quad, GrQuadType type) {
+ this->pushBackImpl(quad, type);
}
- void push_back(const GrPerspQuad& quad) {
- this->pushBackImpl(quad);
+ void push_back(const GrPerspQuad& quad, GrQuadType type) {
+ this->pushBackImpl(quad, type);
}
private:
@@ -337,13 +333,13 @@
}
// Adding to the list requires metadata
- void push_back(const GrQuad& quad, T&& metadata) {
- QuadData<T>& item = this->pushBackImpl(quad);
+ void push_back(const GrQuad& quad, GrQuadType type, T&& metadata) {
+ QuadData<T>& item = this->pushBackImpl(quad, type);
item.fMetadata = std::move(metadata);
}
- void push_back(const GrPerspQuad& quad, T&& metadata) {
- QuadData<T>& item = this->pushBackImpl(quad);
+ void push_back(const GrPerspQuad& quad, GrQuadType type, T&& metadata) {
+ QuadData<T>& item = this->pushBackImpl(quad, type);
item.fMetadata = std::move(metadata);
}
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index aad26c1..1889b0b 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -64,32 +64,35 @@
GrQuadAAFlags edgeAA,
const GrUserStencilSettings* stencilSettings,
const GrPerspQuad& deviceQuad,
- const GrPerspQuad& localQuad) {
+ GrQuadType deviceQuadType,
+ const GrPerspQuad& localQuad,
+ GrQuadType localQuadType) {
// Clean up deviations between aaType and edgeAA
- GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, &aaType, &edgeAA);
+ GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, deviceQuadType, &aaType, &edgeAA);
return Helper::FactoryHelper<FillRectOp>(context, std::move(paint), aaType, edgeAA,
- stencilSettings, deviceQuad, localQuad);
+ stencilSettings, deviceQuad, deviceQuadType, localQuad, localQuadType);
}
// aaType is passed to Helper in the initializer list, so incongruities between aaType and
// edgeFlags must be resolved prior to calling this constructor.
FillRectOp(Helper::MakeArgs args, SkPMColor4f paintColor, GrAAType aaType,
GrQuadAAFlags edgeFlags, const GrUserStencilSettings* stencil,
- const GrPerspQuad& deviceQuad, const GrPerspQuad& localQuad)
+ const GrPerspQuad& deviceQuad, GrQuadType deviceQuadType,
+ const GrPerspQuad& localQuad, GrQuadType localQuadType)
: INHERITED(ClassID())
, fHelper(args, aaType, stencil) {
// The color stored with the quad is the clear color if a scissor-clear is decided upon
// when executing the op.
- fDeviceQuads.push_back(deviceQuad, { paintColor, edgeFlags });
+ fDeviceQuads.push_back(deviceQuad, deviceQuadType, { paintColor, edgeFlags });
if (!fHelper.isTrivial()) {
// Conservatively keep track of the local coordinates; it may be that the paint doesn't
// need them after analysis is finished. If the paint is known to be solid up front they
// can be skipped entirely.
- fLocalQuads.push_back(localQuad);
+ fLocalQuads.push_back(localQuad, localQuadType);
}
- this->setBounds(deviceQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
- IsZeroArea::kNo);
+ this->setBounds(deviceQuad.bounds(deviceQuadType),
+ HasAABloat(aaType == GrAAType::kCoverage), IsZeroArea::kNo);
}
const char* name() const override { return "FillRectOp"; }
@@ -294,7 +297,8 @@
// used with quad sets, which uses the same view matrix for each quad so this assumes that the
// device quad type of the new quad is the same as the op's.
void addQuad(const GrPerspQuad& deviceQuad, const GrPerspQuad& localQuad,
- const SkPMColor4f& color, GrQuadAAFlags edgeAA, GrAAType aaType) {
+ GrQuadType localQuadType, const SkPMColor4f& color, GrQuadAAFlags edgeAA,
+ GrAAType aaType) {
// The new quad's aa type should be the same as the first quad's or none, except when the
// first quad's aa type was already downgraded to none, in which case the stored type must
// be lifted to back to the requested type.
@@ -310,12 +314,12 @@
// Update the bounds and add the quad to this op's storage
SkRect newBounds = this->bounds();
- newBounds.joinPossiblyEmptyRect(deviceQuad.bounds());
+ newBounds.joinPossiblyEmptyRect(deviceQuad.bounds(fDeviceQuads.quadType()));
this->setBounds(newBounds, HasAABloat(fHelper.aaType() == GrAAType::kCoverage),
IsZeroArea::kNo);
- fDeviceQuads.push_back(deviceQuad, { color, edgeAA });
+ fDeviceQuads.push_back(deviceQuad, fDeviceQuads.quadType(), { color, edgeAA });
if (!fHelper.isTrivial()) {
- fLocalQuads.push_back(localQuad);
+ fLocalQuads.push_back(localQuad, localQuadType);
}
}
@@ -352,8 +356,10 @@
const SkMatrix& viewMatrix,
const SkRect& rect,
const GrUserStencilSettings* stencilSettings) {
+ GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
- GrPerspQuad::MakeFromRect(rect, viewMatrix), GrPerspQuad(rect));
+ GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
+ GrPerspQuad(rect), GrQuadType::kRect);
}
std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalMatrix(GrRecordingContext* context,
@@ -364,9 +370,11 @@
const SkMatrix& localMatrix,
const SkRect& rect,
const GrUserStencilSettings* stencilSettings) {
+ GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
+ GrQuadType localQuadType = GrQuadTypeForTransformedRect(localMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
- GrPerspQuad::MakeFromRect(rect, viewMatrix),
- GrPerspQuad::MakeFromRect(rect, localMatrix));
+ GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
+ GrPerspQuad::MakeFromRect(rect, localMatrix), localQuadType);
}
std::unique_ptr<GrDrawOp> MakePerEdgeWithLocalRect(GrRecordingContext* context,
@@ -377,8 +385,10 @@
const SkRect& rect,
const SkRect& localRect,
const GrUserStencilSettings* stencilSettings) {
+ GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
- GrPerspQuad::MakeFromRect(rect, viewMatrix), GrPerspQuad(localRect));
+ GrPerspQuad::MakeFromRect(rect, viewMatrix), dstQuadType,
+ GrPerspQuad(localRect), GrQuadType::kRect);
}
std::unique_ptr<GrDrawOp> MakePerEdgeQuad(GrRecordingContext* context,
@@ -389,10 +399,12 @@
const SkPoint quad[4],
const SkPoint localQuad[4],
const GrUserStencilSettings* stencilSettings) {
+ GrQuadType deviceType = GrQuadTypeForPoints(quad, viewMatrix);
+ GrQuadType localType = GrQuadTypeForPoints(localQuad ? localQuad : quad, SkMatrix::I());
return FillRectOp::Make(context, std::move(paint), aaType, edgeAA, stencilSettings,
- GrPerspQuad::MakeFromSkQuad(quad, viewMatrix),
+ GrPerspQuad::MakeFromSkQuad(quad, viewMatrix), deviceType,
GrPerspQuad::MakeFromSkQuad(localQuad ? localQuad : quad,
- SkMatrix::I()));
+ SkMatrix::I()), localType);
}
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
@@ -404,12 +416,14 @@
const GrUserStencilSettings* stencilSettings) {
// First make a draw op for the first quad in the set
SkASSERT(cnt > 0);
+ GrQuadType deviceQuadType = GrQuadTypeForTransformedRect(viewMatrix);
paint.setColor4f(quads[0].fColor);
std::unique_ptr<GrDrawOp> op = FillRectOp::Make(context, std::move(paint), aaType,
quads[0].fAAFlags, stencilSettings,
- GrPerspQuad::MakeFromRect(quads[0].fRect, viewMatrix),
- GrPerspQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix));
+ GrPerspQuad::MakeFromRect(quads[0].fRect, viewMatrix), deviceQuadType,
+ GrPerspQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix),
+ GrQuadTypeForTransformedRect(quads[0].fLocalMatrix));
auto* fillRects = op->cast<FillRectOp>();
// Accumulate remaining quads similar to onCombineIfPossible() without creating an op
@@ -418,12 +432,13 @@
GrAAType resolvedAA;
GrQuadAAFlags resolvedEdgeFlags;
- GrResolveAATypeForQuad(aaType, quads[i].fAAFlags, deviceQuad,
+ GrResolveAATypeForQuad(aaType, quads[i].fAAFlags, deviceQuad, deviceQuadType,
&resolvedAA, &resolvedEdgeFlags);
fillRects->addQuad(deviceQuad,
GrPerspQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
- quads[i].fColor, resolvedEdgeFlags,resolvedAA);
+ GrQuadTypeForTransformedRect(quads[i].fLocalMatrix), quads[i].fColor,
+ resolvedEdgeFlags,resolvedAA);
}
return op;
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 38c5955..62509d1 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -742,9 +742,6 @@
void* Tessellate(void* vertices, const VertexSpec& spec, const GrPerspQuad& deviceQuad,
const SkPMColor4f& color4f, const GrPerspQuad& localQuad, const SkRect& domain,
GrQuadAAFlags aaFlags) {
- SkASSERT(deviceQuad.quadType() <= spec.deviceQuadType());
- SkASSERT(!spec.hasLocalCoords() || localQuad.quadType() <= spec.localQuadType());
-
CoverageMode mode = get_mode_for_spec(spec);
// Load position data into V4fs (always x, y, and load w to avoid branching down the road)
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index fb28f43..a39535a 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -91,9 +91,6 @@
// based on the configuration in the vertex spec; if that attribute is disabled in the spec,
// then its corresponding function argument is ignored.
//
- // Tessellation is based on the quad type of the vertex spec, not the provided GrPerspQuad's
- // so that all quads in a batch are tessellated the same.
- //
// Returns the advanced pointer in vertices.
void* Tessellate(void* vertices, const VertexSpec& spec, const GrPerspQuad& deviceQuad,
const SkPMColor4f& color, const GrPerspQuad& localQuad, const SkRect& domain,
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 491704f..15e73a0 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -99,7 +99,7 @@
if (origin == kBottomLeft_GrSurfaceOrigin) {
ys = h - ys;
}
- return GrPerspQuad(xs, ys, GrQuadType::kStandard);
+ return GrPerspQuad(xs, ys);
}
/**
@@ -120,8 +120,9 @@
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
GrPerspQuad dstQuad = GrPerspQuad::MakeFromRect(dstRect, viewMatrix);
+ GrQuadType dstQuadType = GrQuadTypeForTransformedRect(viewMatrix);
- if (dstQuad.quadType() == GrQuadType::kRect) {
+ if (dstQuadType == GrQuadType::kRect) {
// Disable filtering if possible (note AA optimizations for rects are automatically
// handled above in GrResolveAATypeForQuad).
if (filter != GrSamplerState::Filter::kNearest &&
@@ -133,8 +134,8 @@
GrOpMemoryPool* pool = context->priv().opMemoryPool();
// srcRect provides both local coords and domain (if needed), so use nullptr for srcQuad
return pool->allocate<TextureOp>(
- std::move(proxy), filter, color, dstQuad, srcRect, constraint,
- nullptr, aaType, aaFlags, std::move(textureColorSpaceXform));
+ std::move(proxy), filter, color, dstQuad, dstQuadType, srcRect, constraint,
+ nullptr, GrQuadType::kRect, aaType, aaFlags, std::move(textureColorSpaceXform));
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
sk_sp<GrTextureProxy> proxy,
@@ -148,7 +149,9 @@
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
GrPerspQuad grDstQuad = GrPerspQuad::MakeFromSkQuad(dstQuad, viewMatrix);
+ GrQuadType dstQuadType = GrQuadTypeForPoints(dstQuad, viewMatrix);
GrPerspQuad grSrcQuad = GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I());
+ GrQuadType srcQuadType = GrQuadTypeForPoints(srcQuad, SkMatrix::I());
// If constraint remains fast, the value in srcRect will be ignored since srcQuads provides
// the local coordinates and a domain won't be used.
@@ -162,8 +165,9 @@
GrOpMemoryPool* pool = context->priv().opMemoryPool();
// Pass domain as srcRect if provided, but send srcQuad as a GrPerspQuad for local coords
return pool->allocate<TextureOp>(
- std::move(proxy), filter, color, grDstQuad, srcRect, constraint, &grSrcQuad,
- aaType, aaFlags, std::move(textureColorSpaceXform));
+ std::move(proxy), filter, color, grDstQuad, dstQuadType, srcRect, constraint,
+ &grSrcQuad, srcQuadType, aaType, aaFlags,
+ std::move(textureColorSpaceXform));
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
const GrRenderTargetContext::TextureSetEntry set[],
@@ -255,8 +259,9 @@
// If srcQuad is provided, it will be used for the local coords instead of srcRect, although
// srcRect will still specify the domain constraint if needed.
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, const SkPMColor4f& color,
- const GrPerspQuad& dstQuad, const SkRect& srcRect,
- SkCanvas::SrcRectConstraint constraint, const GrPerspQuad* srcQuad, GrAAType aaType,
+ const GrPerspQuad& dstQuad, GrQuadType dstQuadType,
+ const SkRect& srcRect, SkCanvas::SrcRectConstraint constraint,
+ const GrPerspQuad* srcQuad, GrQuadType srcQuadType, GrAAType aaType,
GrQuadAAFlags aaFlags, sk_sp<GrColorSpaceXform> textureColorSpaceXform)
: INHERITED(ClassID())
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
@@ -264,7 +269,7 @@
, fFinalized(0) {
// Clean up disparities between the overall aa type and edge configuration and apply
// optimizations based on the rect and matrix when appropriate
- GrResolveAATypeForQuad(aaType, aaFlags, dstQuad, &aaType, &aaFlags);
+ GrResolveAATypeForQuad(aaType, aaFlags, dstQuad, dstQuadType, &aaType, &aaFlags);
fAAType = static_cast<unsigned>(aaType);
// We expect our caller to have already caught this optimization.
@@ -283,14 +288,14 @@
Domain domain = constraint == SkCanvas::kStrict_SrcRectConstraint ? Domain::kYes
: Domain::kNo;
// Initially, if srcQuad is provided it will always be at index 0 of fSrcQuads
- fQuads.push_back(dstQuad, {color, srcRect, srcQuad ? 0 : -1, domain, aaFlags});
+ fQuads.push_back(dstQuad, dstQuadType, {color, srcRect, srcQuad ? 0 : -1, domain, aaFlags});
if (srcQuad) {
- fSrcQuads.push_back(*srcQuad);
+ fSrcQuads.push_back(*srcQuad, srcQuadType);
}
fProxyCnt = 1;
fProxies[0] = {proxy.release(), 1};
- this->setBounds(dstQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage),
- IsZeroArea::kNo);
+ auto bounds = dstQuad.bounds(dstQuadType);
+ this->setBounds(bounds, HasAABloat(aaType == GrAAType::kCoverage), IsZeroArea::kNo);
fDomain = static_cast<unsigned>(domain);
}
TextureOp(const GrRenderTargetContext::TextureSetEntry set[], int cnt,
@@ -308,7 +313,7 @@
// Most dst rects are transformed by the same view matrix, so their quad types start
// identical, unless an entry provides a dstClip or additional transform that changes it.
// The quad list will automatically adapt to that.
- fQuads.reserve(cnt, viewMatrix.hasPerspective());
+ fQuads.reserve(cnt, GrQuadTypeForTransformedRect(viewMatrix));
bool allOpaque = true;
Domain netDomain = Domain::kNo;
for (unsigned p = 0; p < fProxyCnt; ++p) {
@@ -326,19 +331,22 @@
auto quad = set[p].fDstClipQuad == nullptr ?
GrPerspQuad::MakeFromRect(set[p].fDstRect, ctm) :
GrPerspQuad::MakeFromSkQuad(set[p].fDstClipQuad, ctm);
+ GrQuadType quadType =
+ set[p].fDstClipQuad ? GrQuadTypeForPoints(set[p].fDstClipQuad, ctm)
+ : GrQuadTypeForTransformedRect(ctm);
- bounds.joinPossiblyEmptyRect(quad.bounds());
+ bounds.joinPossiblyEmptyRect(quad.bounds(quadType));
GrQuadAAFlags aaFlags;
// Don't update the overall aaType, might be inappropriate for some of the quads
GrAAType aaForQuad;
- GrResolveAATypeForQuad(aaType, set[p].fAAFlags, quad, &aaForQuad, &aaFlags);
+ GrResolveAATypeForQuad(aaType, set[p].fAAFlags, quad, quadType, &aaForQuad, &aaFlags);
// Resolve sets aaForQuad to aaType or None, there is never a change between aa methods
SkASSERT(aaForQuad == GrAAType::kNone || aaForQuad == aaType);
if (overallAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) {
overallAAType = aaType;
}
if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) {
- mustFilter = quad.quadType() != GrQuadType::kRect ||
+ mustFilter = quadType != GrQuadType::kRect ||
GrTextureOp::GetFilterHasEffect(ctm, set[p].fSrcRect,
set[p].fDstRect);
}
@@ -362,10 +370,12 @@
// but with respect to srcRect
SkPoint srcQuad[4];
GrMapRectPoints(set[p].fDstRect, set[p].fSrcRect, set[p].fDstClipQuad, srcQuad, 4);
- fSrcQuads.push_back(GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
+ fSrcQuads.push_back(GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()),
+ GrQuadTypeForPoints(srcQuad, SkMatrix::I()));
srcQuadIndex = fSrcQuads.count() - 1;
}
- fQuads.push_back(quad, {color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags});
+ fQuads.push_back(quad, quadType,
+ {color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags});
}
fAAType = static_cast<unsigned>(overallAAType);
if (!mustFilter) {
diff --git a/tests/GrQuadListTest.cpp b/tests/GrQuadListTest.cpp
index 3100c37..a9cd9b3 100644
--- a/tests/GrQuadListTest.cpp
+++ b/tests/GrQuadListTest.cpp
@@ -55,8 +55,8 @@
GrQuadList list2D;
// Add a plain quad, a 2D persp quad, and then a 3D persp quad, then read back and make sure
// the coordinates make sense (including that the type was lifted to perspective).
- list2D.push_back(make_2d_quad());
- list2D.push_back(make_2d_persp_quad());
+ list2D.push_back(make_2d_quad(), GrQuadType::kRect);
+ list2D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
// Check 2D state of the list
ASSERTF(list2D.count() == 2, "Unexpected count: %d", list2D.count());
@@ -66,7 +66,7 @@
ASSERTF(is_2d_persp_quad(list2D[1]), "Incorrect quad at i=1");
// Force the 2D quads to be updated to store ws by adding a perspective quad
- list2D.push_back(make_3d_persp_quad());
+ list2D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
ASSERTF(list2D.quadType() == GrQuadType::kPerspective,
"Expected 2D list to be upgraded to perspective");
@@ -81,9 +81,9 @@
// Now make a list that starts with a 3D persp quad, then has conventional quads added to it
// and make sure its state is correct
GrQuadList list3D;
- list3D.push_back(make_3d_persp_quad());
- list3D.push_back(make_2d_persp_quad());
- list3D.push_back(make_2d_quad());
+ list3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
+ list3D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
+ list3D.push_back(make_2d_quad(), GrQuadType::kRect);
ASSERTF(list3D.count() == 3, "Unexpected count: %d", list3D.count());
ASSERTF(is_3d_persp_quad(list3D[0]), "Incorrect quad at i=0");
@@ -96,8 +96,8 @@
GrTQuadList<TestData> list2D;
// Add a plain quad, a 2D persp quad, and then a 3D persp quad, then read back and make sure
// the coordinates make sense (including that the type was lifted to perspective).
- list2D.push_back(make_2d_quad(), {1, 1.f});
- list2D.push_back(make_2d_persp_quad(), {2, 2.f});
+ list2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
+ list2D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
// Check 2D state of the list
ASSERTF(list2D.count() == 2, "Unexpected count: %d", list2D.count());
@@ -111,7 +111,7 @@
"Incorrect metadata at i=1");
// Force the 2D quads to be updated to store ws by adding a perspective quad
- list2D.push_back(make_3d_persp_quad(), {3, 3.f});
+ list2D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {3, 3.f});
ASSERTF(list2D.quadType() == GrQuadType::kPerspective,
"Expected 2D list to be upgraded to perspective");
@@ -132,9 +132,9 @@
// Now make a list that starts with a 3D persp quad, then has conventional quads added to it
// and make sure its state is correct
GrTQuadList<TestData> list3D;
- list3D.push_back(make_3d_persp_quad(), {3, 3.f});
- list3D.push_back(make_2d_persp_quad(), {2, 2.f});
- list3D.push_back(make_2d_quad(), {1, 1.f});
+ list3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {3, 3.f});
+ list3D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
+ list3D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
ASSERTF(list3D.count() == 3, "Unexpected count: %d", list3D.count());
ASSERTF(is_3d_persp_quad(list3D[0]), "Incorrect quad at i=0");
@@ -150,9 +150,9 @@
TEST(Concat2DWith2D) {
GrQuadList a2D;
- a2D.push_back(make_2d_quad());
+ a2D.push_back(make_2d_quad(), GrQuadType::kRect);
GrQuadList b2D;
- b2D.push_back(make_2d_persp_quad());
+ b2D.push_back(make_2d_persp_quad(), GrQuadType::kRect);
a2D.concat(b2D);
@@ -163,9 +163,9 @@
TEST(Concat2DWith3D) {
GrQuadList a2D;
- a2D.push_back(make_2d_quad());
+ a2D.push_back(make_2d_quad(), GrQuadType::kRect);
GrQuadList b3D;
- b3D.push_back(make_3d_persp_quad());
+ b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
a2D.concat(b3D);
@@ -176,9 +176,9 @@
TEST(Concat3DWith2D) {
GrQuadList a3D;
- a3D.push_back(make_3d_persp_quad());
+ a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
GrQuadList b2D;
- b2D.push_back(make_2d_quad());
+ b2D.push_back(make_2d_quad(), GrQuadType::kRect);
a3D.concat(b2D);
@@ -189,9 +189,9 @@
TEST(Concat3DWith3D) {
GrQuadList a3D;
- a3D.push_back(make_3d_persp_quad());
+ a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
GrQuadList b3D;
- b3D.push_back(make_3d_persp_quad());
+ b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective);
a3D.concat(b3D);
@@ -202,9 +202,9 @@
TEST(Concat2DWith2DMetadata) {
GrTQuadList<TestData> a2D;
- a2D.push_back(make_2d_quad(), {1, 1.f});
+ a2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
GrTQuadList<TestData> b2D;
- b2D.push_back(make_2d_persp_quad(), {2, 2.f});
+ b2D.push_back(make_2d_persp_quad(), GrQuadType::kRect, {2, 2.f});
a2D.concat(b2D);
@@ -219,9 +219,9 @@
TEST(Concat2DWith3DMetadata) {
GrTQuadList<TestData> a2D;
- a2D.push_back(make_2d_quad(), {1, 1.f});
+ a2D.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
GrTQuadList<TestData> b3D;
- b3D.push_back(make_3d_persp_quad(), {2, 2.f});
+ b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {2, 2.f});
a2D.concat(b3D);
@@ -236,9 +236,9 @@
TEST(Concat3DWith2DMetadata) {
GrTQuadList<TestData> a3D;
- a3D.push_back(make_3d_persp_quad(), {1, 1.f});
+ a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {1, 1.f});
GrTQuadList<TestData> b2D;
- b2D.push_back(make_2d_quad(), {2, 2.f});
+ b2D.push_back(make_2d_quad(), GrQuadType::kRect, {2, 2.f});
a3D.concat(b2D);
@@ -253,9 +253,9 @@
TEST(Concat3DWith3DMetadata) {
GrTQuadList<TestData> a3D;
- a3D.push_back(make_3d_persp_quad(), {1, 1.f});
+ a3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {1, 1.f});
GrTQuadList<TestData> b3D;
- b3D.push_back(make_3d_persp_quad(), {2, 2.f});
+ b3D.push_back(make_3d_persp_quad(), GrQuadType::kPerspective, {2, 2.f});
a3D.concat(b3D);
@@ -270,7 +270,7 @@
TEST(WriteMetadata) {
GrTQuadList<TestData> list;
- list.push_back(make_2d_quad(), {1, 1.f});
+ list.push_back(make_2d_quad(), GrQuadType::kRect, {1, 1.f});
ASSERTF(list.metadata(0).fItem1 == 1 && list.metadata(0).fItem2 == 1.f,
"Incorrect metadata at i=0"); // Sanity check