Combine GrPerspQuad and GrQuad

Also moves GrQuadType to an inner enum of GrQuad as GrQuad::Type.
Renames some of the types for improved clarity (IMO)

Change-Id: I2c91d60374d2b7c414034e9fe0b0113a794bd610
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/216604
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1b28320..6b77d30 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -499,7 +499,7 @@
     AutoCheckFlush acf(this->drawingManager());
     std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
             fContext, std::move(paint), GrAAType::kNone, GrQuadAAFlags::kNone,
-            GrPerspQuad(r), GrPerspQuad::MakeFromRect(r, localMatrix));
+            GrQuad(r), GrQuad::MakeFromRect(r, localMatrix));
     this->addDrawOp(clip, std::move(op));
 }
 
@@ -695,7 +695,7 @@
     GrAAType aaType = this->chooseAAType(aa);
     this->addDrawOp(GrFixedClip::Disabled(),
                     GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeFlags,
-                                       GrPerspQuad(combinedRect), GrPerspQuad(combinedRect)));
+                                       GrQuad(combinedRect), GrQuad(combinedRect)));
     return true;
 }
 
@@ -724,8 +724,8 @@
     GrQuadAAFlags edgeFlags = aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
     this->addDrawOp(clip,
                     GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeFlags,
-                                       GrPerspQuad::MakeFromRect(croppedRect, viewMatrix),
-                                       GrPerspQuad(croppedRect), ss));
+                                       GrQuad::MakeFromRect(croppedRect, viewMatrix),
+                                       GrQuad(croppedRect), ss));
 }
 
 void GrRenderTargetContext::drawRect(const GrClip& clip,
@@ -908,11 +908,11 @@
 
     auto aaType = (GrAA::kYes == doStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
 
-    GrPerspQuad localQuad = localMatrix ? GrPerspQuad::MakeFromRect(rect, *localMatrix)
-                                        : GrPerspQuad(rect);
+    GrQuad localQuad = localMatrix ? GrQuad::MakeFromRect(rect, *localMatrix)
+                                   : GrQuad(rect);
     std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
             fRenderTargetContext->fContext, std::move(paint), aaType, GrQuadAAFlags::kNone,
-            GrPerspQuad::MakeFromRect(rect, viewMatrix), localQuad, ss);
+            GrQuad::MakeFromRect(rect, viewMatrix), localQuad, ss);
     fRenderTargetContext->addDrawOp(clip, std::move(op));
 }
 
@@ -937,8 +937,8 @@
             return;
         }
         op = GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeAA,
-                                GrPerspQuad::MakeFromRect(croppedRect, viewMatrix),
-                                GrPerspQuad(croppedLocalRect));
+                                GrQuad::MakeFromRect(croppedRect, viewMatrix),
+                                GrQuad(croppedLocalRect));
     } else {
         // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending
         // those to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming
@@ -957,8 +957,8 @@
             return;
         }
         op = GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeAA,
-                                GrPerspQuad::MakeFromRect(croppedRect, viewMatrix),
-                                GrPerspQuad(croppedRect));
+                                GrQuad::MakeFromRect(croppedRect, viewMatrix),
+                                GrQuad(croppedRect));
     }
 
     AutoCheckFlush acf(this->drawingManager());
@@ -979,8 +979,8 @@
     const SkPoint* localPoints = localQuad ? localQuad : quad;
     this->addDrawOp(clip,
                     GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeAA,
-                                       GrPerspQuad::MakeFromSkQuad(quad, viewMatrix),
-                                       GrPerspQuad::MakeFromSkQuad(localPoints, SkMatrix::I())));
+                                       GrQuad::MakeFromSkQuad(quad, viewMatrix),
+                                       GrQuad::MakeFromSkQuad(localPoints, SkMatrix::I())));
 }
 
 // Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
@@ -1047,8 +1047,8 @@
                 constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
                 filter, mode, color, std::move(textureColorSpaceXform), &paint);
         op = GrFillRectOp::Make(fContext, std::move(paint), aaType, aaFlags,
-                                GrPerspQuad::MakeFromRect(clippedDstRect, viewMatrix),
-                                GrPerspQuad(clippedSrcRect));
+                                GrQuad::MakeFromRect(clippedDstRect, viewMatrix),
+                                GrQuad(clippedSrcRect));
     } else {
         // Can use a lighter weight op that can chain across proxies
         op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
@@ -1087,8 +1087,8 @@
         draw_texture_to_grpaint(
                 std::move(proxy), domain, filter, mode, color, std::move(texXform), &paint);
         op = GrFillRectOp::Make(fContext, std::move(paint), aaType, aaFlags,
-                                GrPerspQuad::MakeFromSkQuad(dstQuad, viewMatrix),
-                                GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
+                                GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
+                                GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
     } else {
         // Use lighter weight GrTextureOp
         op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
@@ -1168,8 +1168,8 @@
     GrQuadAAFlags edgeFlags = aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
     this->addDrawOp(clip,
                     GrFillRectOp::Make(fContext, std::move(paint), aaType, edgeFlags,
-                                       GrPerspQuad::MakeFromRect(croppedRect, viewMatrix),
-                                       GrPerspQuad::MakeFromRect(croppedRect, localMatrix)));
+                                       GrQuad::MakeFromRect(croppedRect, viewMatrix),
+                                       GrQuad::MakeFromRect(croppedRect, localMatrix)));
 }
 
 void GrRenderTargetContext::drawVertices(const GrClip& clip,
diff --git a/src/gpu/geometry/GrQuad.cpp b/src/gpu/geometry/GrQuad.cpp
index dccd9ca..6ed7232 100644
--- a/src/gpu/geometry/GrQuad.cpp
+++ b/src/gpu/geometry/GrQuad.cpp
@@ -7,6 +7,7 @@
 
 #include "src/gpu/geometry/GrQuad.h"
 
+#include "include/core/SkMatrix.h"
 #include "include/private/GrTypesPriv.h"
 
 using V4f = skvx::Vec<4, float>;
@@ -70,23 +71,23 @@
 }
 
 // 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) {
+static GrQuad::Type quad_type_for_transformed_rect(const SkMatrix& matrix) {
     if (matrix.rectStaysRect()) {
-        return GrQuadType::kRect;
+        return GrQuad::Type::kAxisAligned;
     } else if (matrix.preservesRightAngles()) {
-        return GrQuadType::kRectilinear;
+        return GrQuad::Type::kRectilinear;
     } else if (matrix.hasPerspective()) {
-        return GrQuadType::kPerspective;
+        return GrQuad::Type::kPerspective;
     } else {
-        return GrQuadType::kStandard;
+        return GrQuad::Type::kGeneral;
     }
 }
 
 // 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) {
+static GrQuad::Type quad_type_for_points(const SkPoint pts[4], const SkMatrix& matrix) {
     if (matrix.hasPerspective()) {
-        return GrQuadType::kPerspective;
+        return GrQuad::Type::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
@@ -95,13 +96,12 @@
         (pts[0].fY == pts[1].fY && pts[2].fY == pts[3].fY)) {
         return quad_type_for_transformed_rect(matrix);
     } else {
-        return GrQuadType::kStandard;
+        return GrQuad::Type::kGeneral;
     }
 }
 
-template <typename Q>
 void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
-                            const Q& quad, GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
+                            const GrQuad& quad, GrAAType* outAAType, GrQuadAAFlags* outEdgeFlags) {
     // Most cases will keep the requested types unchanged
     *outAAType = requestedAAType;
     *outEdgeFlags = requestedEdgeFlags;
@@ -115,7 +115,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 (quad.quadType() == GrQuad::Type::kAxisAligned && !quad.aaHasEffectOnRect()) {
                     *outAAType = GrAAType::kNone;
                     *outEdgeFlags = GrQuadAAFlags::kNone;
                 }
@@ -135,91 +135,36 @@
     }
 };
 
-// Instantiate GrResolve... for GrQuad and GrPerspQuad
-template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrQuad&,
-                                     GrAAType*, GrQuadAAFlags*);
-template void GrResolveAATypeForQuad(GrAAType, GrQuadAAFlags, const GrPerspQuad&,
-                                     GrAAType*, GrQuadAAFlags*);
-
 GrQuad GrQuad::MakeFromRect(const SkRect& rect, const SkMatrix& m) {
-    V4f x, y;
+    V4f x, y, w;
     SkMatrix::TypeMask tm = m.getType();
-    GrQuadType type;
+    Type type;
     if (tm <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
         map_rect_translate_scale(rect, m, &x, &y);
-        type = GrQuadType::kRect;
+        w = 1.f;
+        type = Type::kAxisAligned;
     } else {
-        map_rect_general(rect, m, &x, &y, nullptr);
+        map_rect_general(rect, m, &x, &y, &w);
         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, w, type);
 }
 
 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;
-    }
-
+    Type type = quad_type_for_points(pts, matrix);
     if (matrix.isIdentity()) {
-        return GrQuad(xs, ys, type);
+        return GrQuad(xs, ys, 1.f, type);
     } else {
-        V4f mx, my;
-        map_quad_general(xs, ys, matrix, &mx, &my, nullptr);
-        return GrQuad(mx, my, type);
+        V4f mx, my, mw;
+        map_quad_general(xs, ys, matrix, &mx, &my, &mw);
+        return GrQuad(mx, my, mw, type);
     }
 }
 
 bool GrQuad::aaHasEffectOnRect() const {
-    return aa_affects_rect(fX[0], fY[0], fX[3], fY[3]);
-}
-
-// 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) {
-    memcpy(fX, xs, 4 * sizeof(float));
-    memcpy(fY, ys, 4 * sizeof(float));
-    memcpy(fW, ws, 4 * sizeof(float));
-}
-
-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);
-}
-
-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);
-    } else {
-        V4f mx, my, mw;
-        map_quad_general(xs, ys, matrix, &mx, &my, &mw);
-        return GrPerspQuad(mx, my, mw, type);
-    }
-}
-
-bool GrPerspQuad::aaHasEffectOnRect() const {
+    SkASSERT(this->quadType() == Type::kAxisAligned);
     // If rect, ws must all be 1s so no need to divide
     return aa_affects_rect(fX[0], fY[0], fX[3], fY[3]);
 }
diff --git a/src/gpu/geometry/GrQuad.h b/src/gpu/geometry/GrQuad.h
index f7d31ce..27d98cb 100644
--- a/src/gpu/geometry/GrQuad.h
+++ b/src/gpu/geometry/GrQuad.h
@@ -16,132 +16,85 @@
 enum class GrAAType : unsigned;
 enum class GrQuadAAFlags;
 
-// Rectangles transformed by matrices (view or local) can be classified in three ways:
-//  1. Stays a rectangle - the matrix rectStaysRect() is true, or x(0) == x(1) && x(2) == x(3)
-//     and y(0) == y(2) && y(1) == y(3). Or under mirrors, x(0) == x(2) && x(1) == x(3) and
-//     y(0) == y(1) && y(2) == y(3).
-//  2. Is rectilinear - the matrix does not have skew or perspective, but may rotate (unlike #1)
-//  3. Is a quadrilateral - the matrix does not have perspective, but may rotate or skew, or
-//     ws() == all ones.
-//  4. Is a perspective quad - the matrix has perspective, subsuming all previous quad types.
-enum class GrQuadType {
-    kRect,
-    kRectilinear,
-    kStandard,
-    kPerspective,
-    kLast = kPerspective
-};
-static const int kGrQuadTypeCount = static_cast<int>(GrQuadType::kLast) + 1;
-
-// 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);
-
 /**
  * GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
  * points make a triangle strip with CCW triangles (top-left, bottom-left, top-right, bottom-right).
  */
 class GrQuad {
 public:
-    GrQuad() = default;
+    // Quadrilaterals can be classified in several useful ways that assist AA tessellation and other
+    // analysis when drawing, in particular, knowing if it was originally a rectangle transformed by
+    // certain types of matrices:
+    enum class Type {
+        // The 4 points remain an axis-aligned rectangle; their logical indices may not respect
+        // TL, BL, TR, BR ordering if the transform was a 90 degre rotation or mirror.
+        kAxisAligned,
+        // The 4 points represent a rectangle subjected to a rotation, its corners are right angles.
+        kRectilinear,
+        // Arbitrary 2D quadrilateral; may have been a rectangle transformed with skew or some
+        // clipped polygon. Its w coordinates will all be 1.
+        kGeneral,
+        // Even more general-purpose than kGeneral, this allows the w coordinates to be non-unity.
+        kPerspective,
+        kLast = kPerspective
+    };
+    static const int kTypeCount = static_cast<int>(Type::kLast) + 1;
 
-    GrQuad(const GrQuad& that) = default;
+    GrQuad() = default;
 
     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) {}
-
-    GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, GrQuadType type)
-            : fType(type) {
-        xs.store(fX);
-        ys.store(fY);
-    }
-
-    /** Sets the quad to the rect as transformed by the matrix. */
-    static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
-
-    // Creates a GrQuad from the quadrilateral 'pts', transformed by the matrix. Unlike the explicit
-    // constructor, the input points array is arranged as per SkRect::toQuad (top-left, top-right,
-    // bottom-right, bottom-left). The returned instance's point order will still be CCW tri-strip
-    // order.
-    static GrQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);
-
-    GrQuad& operator=(const GrQuad& that) = default;
-
-    SkPoint point(int i) const { return {fX[i], fY[i]}; }
-
-    SkRect bounds() const {
-        auto x = this->x4f(), y = this->y4f();
-        return {min(x), min(y), max(x), max(y)};
-    }
-
-    float x(int i) const { return fX[i]; }
-    float y(int i) const { return fY[i]; }
-
-    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;
-
-private:
-    template<typename T>
-    friend class GrQuadListBase;
-
-    float fX[4];
-    float fY[4];
-
-    GrQuadType fType;
-};
-
-class GrPerspQuad {
-public:
-    GrPerspQuad() = default;
-
-    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) {}
+            , fType(Type::kAxisAligned) {}
 
-    GrPerspQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
-                GrQuadType type)
+    GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, Type type)
             : fType(type) {
-        SkASSERT(type != GrQuadType::kPerspective);
+        SkASSERT(type != Type::kPerspective);
         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)
+    GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
+           const skvx::Vec<4, float>& ws, Type type)
             : fType(type) {
         xs.store(fX);
         ys.store(fY);
         ws.store(fW);
     }
 
-    static GrPerspQuad MakeFromRect(const SkRect&, const SkMatrix&);
+    // Copy 4 values from each of the arrays into the quad's components
+    GrQuad(const float xs[4], const float ys[4], const float ws[4], Type type)
+            : fType(type) {
+        memcpy(fX, xs, 4 * sizeof(float));
+        memcpy(fY, ys, 4 * sizeof(float));
+        memcpy(fW, ws, 4 * sizeof(float));
+    }
 
-    // Creates a GrPerspQuad from the quadrilateral 'pts', transformed by the matrix. The input
+    static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
+
+    // Creates a GrQuad from the quadrilateral 'pts', transformed by the matrix. The input
     // points array is arranged as per SkRect::toQuad (top-left, top-right, bottom-right,
     // bottom-left). The returned instance's point order will still be CCW tri-strip order.
-    static GrPerspQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);
+    static GrQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);
 
-    GrPerspQuad& operator=(const GrPerspQuad&) = default;
+    GrQuad& operator=(const GrQuad&) = default;
 
-    SkPoint3 point(int i) const { return {fX[i], fY[i], fW[i]}; }
+    SkPoint3 point3(int i) const { return {fX[i], fY[i], fW[i]}; }
+
+    SkPoint point(int i) const {
+        if (fType == Type::kPerspective) {
+            return {fX[i] / fW[i], fY[i] / fW[i]};
+        } else {
+            return {fX[i], fY[i]};
+        }
+    }
 
     SkRect bounds() const {
         auto x = this->x4f();
         auto y = this->y4f();
-        if (fType == GrQuadType::kPerspective) {
+        if (fType == Type::kPerspective) {
             auto iw = this->iw4f();
             x *= iw;
             y *= iw;
@@ -160,25 +113,27 @@
     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; }
+    Type quadType() const { return fType; }
 
-    bool hasPerspective() const { return fType == GrQuadType::kPerspective; }
+    bool hasPerspective() const { return fType == Type::kPerspective; }
 
-    // True if anti-aliasing affects this quad. Only valid when quadType == kRect_QuadType
+    // True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
     bool aaHasEffectOnRect() const;
 
 private:
     template<typename T>
-    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);
+    friend class GrQuadListBase; // for access to fX, fY, fW
 
     float fX[4];
     float fY[4];
     float fW[4];
 
-    GrQuadType fType;
+    Type fType;
 };
 
+// Resolve disagreements between the overall requested AA type and the per-edge quad AA flags.
+// Both outAAType and outEdgeFlags will be updated.
+void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
+                            const GrQuad& quad, GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
+
 #endif
diff --git a/src/gpu/geometry/GrQuadList.h b/src/gpu/geometry/GrQuadList.h
index a802f9e..b1cbf6a 100644
--- a/src/gpu/geometry/GrQuadList.h
+++ b/src/gpu/geometry/GrQuadList.h
@@ -36,27 +36,27 @@
 
     int count() const { return fXYs.count(); }
 
-    GrQuadType quadType() const { return fType; }
+    GrQuad::Type quadType() const { return fType; }
 
     void reserve(int count, bool needsPerspective) {
         fXYs.reserve(count);
-        if (needsPerspective || fType == GrQuadType::kPerspective) {
+        if (needsPerspective || fType == GrQuad::Type::kPerspective) {
             fWs.reserve(4 * count);
         }
     }
 
-    GrPerspQuad operator[] (int i) const {
+    GrQuad operator[] (int i) const {
         SkASSERT(i < this->count());
         SkASSERT(i >= 0);
 
         const QuadData<T>& item = fXYs[i];
-        if (fType == GrQuadType::kPerspective) {
+        if (fType == GrQuad::Type::kPerspective) {
             // Read the explicit ws
-            return GrPerspQuad(item.fX, item.fY, fWs.begin() + 4 * i, fType);
+            return GrQuad(item.fX, item.fY, fWs.begin() + 4 * i, fType);
         } 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 GrQuad(item.fX, item.fY, kNoPerspectiveWs, fType);
         }
     }
 
@@ -64,13 +64,13 @@
     // the metadata argument is only present in GrTQuadList's push_back definition.
 
 protected:
-    GrQuadListBase() : fType(GrQuadType::kRect) {}
+    GrQuadListBase() : fType(GrQuad::Type::kAxisAligned) {}
 
     void concatImpl(const GrQuadListBase<T>& that) {
         this->upgradeType(that.fType);
         fXYs.push_back_n(that.fXYs.count(), that.fXYs.begin());
-        if (fType == GrQuadType::kPerspective) {
-            if (that.fType == GrQuadType::kPerspective) {
+        if (fType == GrQuad::Type::kPerspective) {
+            if (that.fType == GrQuad::Type::kPerspective) {
                 // Copy the other's ws into the end of this list's data
                 fWs.push_back_n(that.fWs.count(), that.fWs.begin());
             } else {
@@ -87,18 +87,7 @@
         QuadData<T>& item = fXYs.push_back();
         memcpy(item.fX, quad.fX, 4 * sizeof(float));
         memcpy(item.fY, quad.fY, 4 * sizeof(float));
-        if (fType == GrQuadType::kPerspective) {
-            fWs.push_back_n(4, 1.f);
-        }
-        return item;
-    }
-
-    QuadData<T>& pushBackImpl(const GrPerspQuad& quad) {
-        this->upgradeType(quad.quadType());
-        QuadData<T>& item = fXYs.push_back();
-        memcpy(item.fX, quad.fX, 4 * sizeof(float));
-        memcpy(item.fY, quad.fY, 4 * sizeof(float));
-        if (fType == GrQuadType::kPerspective) {
+        if (fType == GrQuad::Type::kPerspective) {
             fWs.push_back_n(4, quad.fW);
         }
         return item;
@@ -113,11 +102,11 @@
     }
 
 private:
-    void upgradeType(GrQuadType type) {
+    void upgradeType(GrQuad::Type type) {
         // Possibly upgrade the overall type tracked by the list
         if (type > fType) {
             fType = type;
-            if (type == GrQuadType::kPerspective) {
+            if (type == GrQuad::Type::kPerspective) {
                 // All existing quads were 2D, so the ws array just needs to be filled with 1s
                 fWs.push_back_n(4 * this->count(), 1.f);
             }
@@ -130,7 +119,7 @@
     // The w channel is kept separate so that it can remain empty when only dealing with 2D quads.
     SkTArray<float, true> fWs;
 
-    GrQuadType fType;
+    GrQuad::Type fType;
 };
 
 // This list only stores the quad data itself.
@@ -146,10 +135,6 @@
         this->pushBackImpl(quad);
     }
 
-    void push_back(const GrPerspQuad& quad) {
-        this->pushBackImpl(quad);
-    }
-
 private:
     typedef GrQuadListBase<void> INHERITED;
 };
@@ -171,11 +156,6 @@
         item.fMetadata = std::move(metadata);
     }
 
-    void push_back(const GrPerspQuad& quad, T&& metadata) {
-        QuadData<T>& item = this->pushBackImpl(quad);
-        item.fMetadata = std::move(metadata);
-    }
-
     // And provide access to the metadata per quad
     const T& metadata(int i) const {
         return this->item(i).fMetadata;
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 18765d9..3433dc9 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -28,8 +28,8 @@
 using ColorType = GrQuadPerEdgeAA::ColorType;
 
 #ifdef SK_DEBUG
-static SkString dump_quad_info(int index, const GrPerspQuad& deviceQuad,
-                               const GrPerspQuad& localQuad, const SkPMColor4f& color,
+static SkString dump_quad_info(int index, const GrQuad& deviceQuad,
+                               const GrQuad& localQuad, const SkPMColor4f& color,
                                GrQuadAAFlags aaFlags) {
     SkString str;
     str.appendf("%d: Color: [%.2f, %.2f, %.2f, %.2f], Edge AA: l%u_t%u_r%u_b%u, \n"
@@ -64,8 +64,8 @@
                                           GrAAType aaType,
                                           GrQuadAAFlags edgeAA,
                                           const GrUserStencilSettings* stencilSettings,
-                                          const GrPerspQuad& deviceQuad,
-                                          const GrPerspQuad& localQuad) {
+                                          const GrQuad& deviceQuad,
+                                          const GrQuad& localQuad) {
         // Clean up deviations between aaType and edgeAA
         GrResolveAATypeForQuad(aaType, edgeAA, deviceQuad, &aaType, &edgeAA);
         return Helper::FactoryHelper<FillRectOp>(context, std::move(paint), aaType, edgeAA,
@@ -76,7 +76,7 @@
     // 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 GrQuad& deviceQuad, const GrQuad& localQuad)
             : INHERITED(ClassID())
             , fHelper(args, aaType, stencil) {
         // The color stored with the quad is the clear color if a scissor-clear is decided upon
@@ -106,7 +106,7 @@
         str.appendf("Device quad type: %u, local quad type: %u\n",
                     (uint32_t) fDeviceQuads.quadType(), (uint32_t) fLocalQuads.quadType());
         str += fHelper.dumpInfo();
-        GrPerspQuad device, local;
+        GrQuad device, local;
         for (int i = 0; i < this->quadCount(); i++) {
             device = fDeviceQuads[i];
             const ColorAndAA& info = fDeviceQuads.metadata(i);
@@ -221,7 +221,7 @@
         void* vertices = vdata;
         if (fHelper.isTrivial()) {
             SkASSERT(fLocalQuads.count() == 0); // No local coords, so send an ignored dummy quad
-            static const GrPerspQuad kIgnoredLocal(SkRect::MakeEmpty());
+            static const GrQuad kIgnoredLocal(SkRect::MakeEmpty());
 
             for (int i = 0; i < this->quadCount(); ++i) {
                 const ColorAndAA& info = fDeviceQuads.metadata(i);
@@ -294,7 +294,7 @@
     // But since it's avoiding the op list management, it must update the op's bounds. This is only
     // 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,
+    void addQuad(const GrQuad& deviceQuad, const GrQuad& localQuad,
                  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
@@ -350,8 +350,8 @@
                                GrPaint&& paint,
                                GrAAType aaType,
                                GrQuadAAFlags aaFlags,
-                               const GrPerspQuad& deviceQuad,
-                               const GrPerspQuad& localQuad,
+                               const GrQuad& deviceQuad,
+                               const GrQuad& localQuad,
                                const GrUserStencilSettings* stencil) {
     return FillRectOp::Make(context, std::move(paint), aaType, aaFlags, stencil,
                             deviceQuad, localQuad);
@@ -363,7 +363,7 @@
                                         const SkRect& rect,
                                         const GrUserStencilSettings* stencil) {
     return FillRectOp::Make(context, std::move(paint), GrAAType::kNone, GrQuadAAFlags::kNone,
-                            stencil, GrPerspQuad::MakeFromRect(rect, view), GrPerspQuad(rect));
+                            stencil, GrQuad::MakeFromRect(rect, view), GrQuad(rect));
 }
 
 std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
@@ -379,13 +379,13 @@
     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));
+            GrQuad::MakeFromRect(quads[0].fRect, viewMatrix),
+            GrQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix));
     auto* fillRects = op->cast<FillRectOp>();
 
     // Accumulate remaining quads similar to onCombineIfPossible() without creating an op
     for (int i = 1; i < cnt; ++i) {
-        GrPerspQuad deviceQuad = GrPerspQuad::MakeFromRect(quads[i].fRect, viewMatrix);
+        GrQuad deviceQuad = GrQuad::MakeFromRect(quads[i].fRect, viewMatrix);
 
         GrAAType resolvedAA;
         GrQuadAAFlags resolvedEdgeFlags;
@@ -393,7 +393,7 @@
                                &resolvedAA, &resolvedEdgeFlags);
 
         fillRects->addQuad(deviceQuad,
-                           GrPerspQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
+                           GrQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
                            quads[i].fColor, resolvedEdgeFlags,resolvedAA);
     }
 
@@ -452,21 +452,21 @@
                 // Single local matrix
                 SkMatrix localMatrix = GrTest::TestMatrixInvertible(random);
                 return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
-                                          GrPerspQuad::MakeFromRect(rect, viewMatrix),
-                                          GrPerspQuad::MakeFromRect(rect, localMatrix), stencil);
+                                          GrQuad::MakeFromRect(rect, viewMatrix),
+                                          GrQuad::MakeFromRect(rect, localMatrix), stencil);
             }
         } else {
             // Pass local rect directly
             SkRect localRect = GrTest::TestRect(random);
             return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
-                                      GrPerspQuad::MakeFromRect(rect, viewMatrix),
-                                      GrPerspQuad(localRect), stencil);
+                                      GrQuad::MakeFromRect(rect, viewMatrix),
+                                      GrQuad(localRect), stencil);
         }
     } else {
         // The simplest constructor
         return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
-                                  GrPerspQuad::MakeFromRect(rect, viewMatrix),
-                                  GrPerspQuad(rect), stencil);
+                                  GrQuad::MakeFromRect(rect, viewMatrix),
+                                  GrQuad(rect), stencil);
     }
 }
 
diff --git a/src/gpu/ops/GrFillRectOp.h b/src/gpu/ops/GrFillRectOp.h
index 3422631..768ed8b 100644
--- a/src/gpu/ops/GrFillRectOp.h
+++ b/src/gpu/ops/GrFillRectOp.h
@@ -13,7 +13,7 @@
 
 class GrDrawOp;
 class GrPaint;
-class GrPerspQuad;
+class GrQuad;
 class GrRecordingContext;
 struct GrUserStencilSettings;
 class SkMatrix;
@@ -31,8 +31,8 @@
                                GrPaint&& paint,
                                GrAAType aaType,
                                GrQuadAAFlags aaFlags,
-                               const GrPerspQuad& deviceQuad,
-                               const GrPerspQuad& localQuad,
+                               const GrQuad& deviceQuad,
+                               const GrQuad& localQuad,
                                const GrUserStencilSettings* stencil = nullptr);
 
 // Utility function to create a non-AA rect transformed by view. This is used commonly enough in
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 1d3c602..9bb9a85 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -671,7 +671,7 @@
         // save position, this is a float2 or float3 or float4 depending on the combination of
         // perspective and coverage mode.
         vb->write(quad.fX[i], quad.fY[i],
-                  If(spec.deviceQuadType() == GrQuadType::kPerspective, quad.fW[i]),
+                  If(spec.deviceQuadType() == GrQuad::Type::kPerspective, quad.fW[i]),
                   If(mode == CoverageMode::kWithPosition, coverage[i]));
 
         // save color
@@ -684,7 +684,7 @@
         // save local position
         if (spec.hasLocalCoords()) {
             vb->write(quad.fU[i], quad.fV[i],
-                      If(spec.localQuadType() == GrQuadType::kPerspective, quad.fR[i]));
+                      If(spec.localQuadType() == GrQuad::Type::kPerspective, quad.fR[i]));
         }
 
         // save the geometry domain
@@ -739,8 +739,8 @@
 
 ////////////////// Tessellate Implementation
 
-void* Tessellate(void* vertices, const VertexSpec& spec, const GrPerspQuad& deviceQuad,
-                 const SkPMColor4f& color4f, const GrPerspQuad& localQuad, const SkRect& domain,
+void* Tessellate(void* vertices, const VertexSpec& spec, const GrQuad& deviceQuad,
+                 const SkPMColor4f& color4f, const GrQuad& localQuad, const SkRect& domain,
                  GrQuadAAFlags aaFlags) {
     SkASSERT(deviceQuad.quadType() <= spec.deviceQuadType());
     SkASSERT(!spec.hasLocalCoords() || localQuad.quadType() <= spec.localQuadType());
@@ -770,7 +770,7 @@
 
         SkRect geomDomain;
         V4f maxCoverage = 1.f;
-        if (spec.deviceQuadType() == GrQuadType::kPerspective) {
+        if (spec.deviceQuadType() == GrQuad::Type::kPerspective) {
             // For perspective, send quads with all edges non-AA through the tessellation to ensure
             // their corners are processed the same as adjacent quads. This approach relies on
             // solving edge equations to reconstruct corners, which can create seams if an inner
@@ -780,7 +780,7 @@
             // In 2D, the simpler corner math does not cause issues with seaming against non-AA
             // inner quads.
             maxCoverage = compute_nested_quad_vertices(
-                    aaFlags, spec.deviceQuadType() <= GrQuadType::kRectilinear, &inner, &outer,
+                    aaFlags, spec.deviceQuadType() <= GrQuad::Type::kRectilinear, &inner, &outer,
                     &geomDomain);
         } else if (spec.requiresGeometryDomain()) {
             // The quad itself wouldn't need a geometric domain, but the batch does, so set the
@@ -839,11 +839,11 @@
 ////////////////// VertexSpec Implementation
 
 int VertexSpec::deviceDimensionality() const {
-    return this->deviceQuadType() == GrQuadType::kPerspective ? 3 : 2;
+    return this->deviceQuadType() == GrQuad::Type::kPerspective ? 3 : 2;
 }
 
 int VertexSpec::localDimensionality() const {
-    return fHasLocalCoords ? (this->localQuadType() == GrQuadType::kPerspective ? 3 : 2) : 0;
+    return fHasLocalCoords ? (this->localQuadType() == GrQuad::Type::kPerspective ? 3 : 2) : 0;
 }
 
 ////////////////// Geometry Processor Implementation
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index 8b92cb6..7133a1b 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -36,7 +36,7 @@
     // GPAttributes maintains. If hasLocalCoords is false, then the local quad type can be ignored.
     struct VertexSpec {
     public:
-        VertexSpec(GrQuadType deviceQuadType, ColorType colorType, GrQuadType localQuadType,
+        VertexSpec(GrQuad::Type deviceQuadType, ColorType colorType, GrQuad::Type localQuadType,
                    bool hasLocalCoords, Domain domain, GrAAType aa, bool coverageAsAlpha)
                 : fDeviceQuadType(static_cast<unsigned>(deviceQuadType))
                 , fLocalQuadType(static_cast<unsigned>(localQuadType))
@@ -46,10 +46,10 @@
                 , fUsesCoverageAA(aa == GrAAType::kCoverage)
                 , fCompatibleWithCoverageAsAlpha(coverageAsAlpha)
                 , fRequiresGeometryDomain(aa == GrAAType::kCoverage &&
-                                          deviceQuadType > GrQuadType::kRectilinear) { }
+                                          deviceQuadType > GrQuad::Type::kRectilinear) { }
 
-        GrQuadType deviceQuadType() const { return static_cast<GrQuadType>(fDeviceQuadType); }
-        GrQuadType localQuadType() const { return static_cast<GrQuadType>(fLocalQuadType); }
+        GrQuad::Type deviceQuadType() const { return static_cast<GrQuad::Type>(fDeviceQuadType); }
+        GrQuad::Type localQuadType() const { return static_cast<GrQuad::Type>(fLocalQuadType); }
         bool hasLocalCoords() const { return fHasLocalCoords; }
         ColorType colorType() const { return static_cast<ColorType>(fColorType); }
         bool hasVertexColors() const { return ColorType::kNone != this->colorType(); }
@@ -64,7 +64,7 @@
 
         int verticesPerQuad() const { return fUsesCoverageAA ? 8 : 4; }
     private:
-        static_assert(kGrQuadTypeCount <= 4, "GrQuadType doesn't fit in 2 bits");
+        static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type doesn't fit in 2 bits");
         static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits");
 
         unsigned fDeviceQuadType: 2;
@@ -91,12 +91,12 @@
     // 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
+    // Tessellation is based on the quad type of the vertex spec, not the provided GrQuad'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,
+    void* Tessellate(void* vertices, const VertexSpec& spec, const GrQuad& deviceQuad,
+                     const SkPMColor4f& color, const GrQuad& localQuad, const SkRect& domain,
                      GrQuadAAFlags aa);
 
     // The mesh will have its index data configured to meet the expectations of the Tessellate()
diff --git a/src/gpu/ops/GrStrokeRectOp.cpp b/src/gpu/ops/GrStrokeRectOp.cpp
index 1dd2bd6..9c27e47 100644
--- a/src/gpu/ops/GrStrokeRectOp.cpp
+++ b/src/gpu/ops/GrStrokeRectOp.cpp
@@ -776,8 +776,8 @@
         }
         return GrFillRectOp::Make(context, std::move(paint), GrAAType::kCoverage,
                                   GrQuadAAFlags::kAll,
-                                  GrPerspQuad::MakeFromRect(rects[0], viewMatrix),
-                                  GrPerspQuad(rects[0]));
+                                  GrQuad::MakeFromRect(rects[0], viewMatrix),
+                                  GrQuad(rects[0]));
     }
 
     return AAStrokeRectOp::Make(context, std::move(paint), viewMatrix, devOutside, devInside);
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 342d7ba..3f9f0f1 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -75,8 +75,8 @@
 
 // If normalizing the src quad then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass
 // 1, 1, and height.
-static GrPerspQuad compute_src_quad_from_rect(GrSurfaceOrigin origin, const SkRect& srcRect,
-                                              float iw, float ih, float h) {
+static GrQuad compute_src_quad_from_rect(GrSurfaceOrigin origin, const SkRect& srcRect,
+                                         float iw, float ih, float h) {
     // Convert the pixel-space src rectangle into normalized texture coordinates
     SkRect texRect = {
         iw * srcRect.fLeft,
@@ -88,11 +88,11 @@
         texRect.fTop = h - texRect.fTop;
         texRect.fBottom = h - texRect.fBottom;
     }
-    return GrPerspQuad(texRect);
+    return GrQuad(texRect);
 }
 // Normalizes logical src coords and corrects for origin
-static GrPerspQuad compute_src_quad(GrSurfaceOrigin origin, const GrPerspQuad& srcQuad,
-                                    float iw, float ih, float h) {
+static GrQuad compute_src_quad(GrSurfaceOrigin origin, const GrQuad& srcQuad,
+                               float iw, float ih, float h) {
     // The src quad should not have any perspective
     SkASSERT(!srcQuad.hasPerspective());
     skvx::Vec<4, float> xs = srcQuad.x4f() * iw;
@@ -100,7 +100,7 @@
     if (origin == kBottomLeft_GrSurfaceOrigin) {
         ys = h - ys;
     }
-    return GrPerspQuad(xs, ys, srcQuad.quadType());
+    return GrQuad(xs, ys, srcQuad.quadType());
 }
 
 /**
@@ -120,9 +120,9 @@
                                           SkCanvas::SrcRectConstraint constraint,
                                           const SkMatrix& viewMatrix,
                                           sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
-        GrPerspQuad dstQuad = GrPerspQuad::MakeFromRect(dstRect, viewMatrix);
+        GrQuad dstQuad = GrQuad::MakeFromRect(dstRect, viewMatrix);
 
-        if (dstQuad.quadType() == GrQuadType::kRect) {
+        if (dstQuad.quadType() == GrQuad::Type::kAxisAligned) {
             // Disable filtering if possible (note AA optimizations for rects are automatically
             // handled above in GrResolveAATypeForQuad).
             if (filter != GrSamplerState::Filter::kNearest &&
@@ -148,8 +148,8 @@
                                           const SkRect* domain,
                                           const SkMatrix& viewMatrix,
                                           sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
-        GrPerspQuad grDstQuad = GrPerspQuad::MakeFromSkQuad(dstQuad, viewMatrix);
-        GrPerspQuad grSrcQuad = GrPerspQuad::MakeFromSkQuad(srcQuad, SkMatrix::I());
+        GrQuad grDstQuad = GrQuad::MakeFromSkQuad(dstQuad, viewMatrix);
+        GrQuad grSrcQuad = GrQuad::MakeFromSkQuad(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.
@@ -161,7 +161,7 @@
         }
 
         GrOpMemoryPool* pool = context->priv().opMemoryPool();
-        // Pass domain as srcRect if provided, but send srcQuad as a GrPerspQuad for local coords
+        // Pass domain as srcRect if provided, but send srcQuad as a GrQuad for local coords
         return pool->allocate<TextureOp>(
                 std::move(proxy), filter, color, grDstQuad, srcRect, constraint, &grSrcQuad,
                 aaType, aaFlags, std::move(textureColorSpaceXform));
@@ -208,7 +208,7 @@
             str.appendf("Proxy ID: %d, Filter: %d\n", fProxies[p].fProxy->uniqueID().asUInt(),
                         static_cast<int>(fFilter));
             for (int i = 0; i < fProxies[p].fQuadCnt; ++i, ++q) {
-                GrPerspQuad quad = fQuads[q];
+                GrQuad quad = fQuads[q];
                 const ColorDomainAndAA& info = fQuads.metadata(i);
                 str.appendf(
                         "%d: Color: 0x%08x, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] "
@@ -257,8 +257,8 @@
     // 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 GrQuad& dstQuad, const SkRect& srcRect,
+              SkCanvas::SrcRectConstraint constraint, const GrQuad* srcQuad, GrAAType aaType,
               GrQuadAAFlags aaFlags, sk_sp<GrColorSpaceXform> textureColorSpaceXform)
             : INHERITED(ClassID())
             , fTextureColorSpaceXform(std::move(textureColorSpaceXform))
@@ -326,8 +326,8 @@
 
             // Use dstRect unless dstClip is provided, which is assumed to be a quad
             auto quad = set[p].fDstClipQuad == nullptr ?
-                    GrPerspQuad::MakeFromRect(set[p].fDstRect, ctm) :
-                    GrPerspQuad::MakeFromSkQuad(set[p].fDstClipQuad, ctm);
+                    GrQuad::MakeFromRect(set[p].fDstRect, ctm) :
+                    GrQuad::MakeFromSkQuad(set[p].fDstClipQuad, ctm);
 
             bounds.joinPossiblyEmptyRect(quad.bounds());
             GrQuadAAFlags aaFlags;
@@ -340,7 +340,7 @@
                 overallAAType = aaType;
             }
             if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) {
-                mustFilter = quad.quadType() != GrQuadType::kRect ||
+                mustFilter = quad.quadType() != GrQuad::Type::kAxisAligned ||
                              GrTextureOp::GetFilterHasEffect(ctm, set[p].fSrcRect,
                                                              set[p].fDstRect);
             }
@@ -364,7 +364,7 @@
                 // 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(GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
                 srcQuadIndex = fSrcQuads.count() - 1;
             }
             fQuads.push_back(quad, {color, set[p].fSrcRect, srcQuadIndex, domainForQuad, aaFlags});
@@ -393,10 +393,10 @@
         }
 
         for (int i = start; i < start + cnt; ++i) {
-            const GrPerspQuad& device = fQuads[i];
+            const GrQuad& device = fQuads[i];
             const ColorDomainAndAA& info = fQuads.metadata(i);
 
-            GrPerspQuad srcQuad = info.fSrcQuadIndex >= 0 ?
+            GrQuad srcQuad = info.fSrcQuadIndex >= 0 ?
                     compute_src_quad(origin, fSrcQuads[info.fSrcQuadIndex], iw, ih, h) :
                     compute_src_quad_from_rect(origin, info.fSrcRect, iw, ih, h);
             SkRect domain =
@@ -408,8 +408,8 @@
 
     void onPrepareDraws(Target* target) override {
         TRACE_EVENT0("skia", TRACE_FUNC);
-        GrQuadType quadType = GrQuadType::kRect;
-        GrQuadType srcQuadType = GrQuadType::kRect;
+        GrQuad::Type quadType = GrQuad::Type::kAxisAligned;
+        GrQuad::Type srcQuadType = GrQuad::Type::kAxisAligned;
         Domain domain = Domain::kNo;
         ColorType colorType = ColorType::kNone;
         int numProxies = 0;
@@ -659,7 +659,7 @@
     unsigned fProxyCnt : 32 - 8;
     Proxy fProxies[1];
 
-    static_assert(kGrQuadTypeCount <= 4, "GrQuadType does not fit in 2 bits");
+    static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type does not fit in 2 bits");
 
     typedef GrMeshDrawOp INHERITED;
 };