Use FillRRectOp in drawStrokedLine for dmsaa

This makes it so we don't trigger msaa in drawStrokedLine anymore.

Bug: skia:skia:12872
Change-Id: Id68b55ba9e3989f2a775affe9a1b20bf3186123c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/502816
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Christopher Dalton <csmartdalton@google.com>
diff --git a/gm/drawlines_with_local_matrix.cpp b/gm/drawlines_with_local_matrix.cpp
new file mode 100644
index 0000000..0fca912
--- /dev/null
+++ b/gm/drawlines_with_local_matrix.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm/gm.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkPaint.h"
+#include "include/effects/SkGradientShader.h"
+
+DEF_SIMPLE_GM(drawlines_with_local_matrix, canvas, 500, 500) {
+    canvas->clipRect({0,0,500,500});
+    SkPaint grad;
+    grad.setAntiAlias(true);
+    grad.setStrokeCap(SkPaint::kSquare_Cap);
+    float pos[6] = {0, 2/6.f, 3/6.f, 4/6.f, 5/6.f, 1};
+    constexpr SkColor indigo = SkColorSetARGB(0xFF, 0x4b, 0x00, 0x82);
+    constexpr SkColor violet = SkColorSetARGB(0xFF, 0xee, 0x82, 0xee);
+    SkColor colors[6] = {SK_ColorRED, SK_ColorYELLOW, SK_ColorGREEN, SK_ColorBLUE, indigo, violet};
+    grad.setShader(SkGradientShader::MakeRadial({250,250}, 280, colors, pos, 6,SkTileMode::kClamp));
+    canvas->drawPaint(grad);
+
+    SkPaint white;
+    white.setAntiAlias(true);
+    white.setStrokeCap(SkPaint::kSquare_Cap);
+    white.setColor(SK_ColorWHITE);
+
+    auto drawLine = [&](float x0, float y0, float x1, float y1, float w) {
+        SkPoint p[2] = {{x0, y0}, {x1, y1}};
+        white.setStrokeWidth(w);
+        canvas->drawPoints(SkCanvas::kLines_PointMode, 2, p, white);
+        grad.setStrokeWidth(w - 4);
+        canvas->drawPoints(SkCanvas::kLines_PointMode, 2, p, grad);
+    };
+
+    drawLine(20, 20, 200, 120, 20);
+    drawLine(20, 200, 20, 100, 20);
+    drawLine(480, 20, 400, 400, 20);
+    drawLine(50, 480, 260, 100, 20);
+    drawLine(270, 20, 380, 210, 20);
+    drawLine(280, 280, 400, 480, 20);
+    drawLine(160, 375, 280, 375, 20);
+    drawLine(220, 410, 220, 470, 20);
+    drawLine(250, 250, 250, 250, 20);
+}
diff --git a/gn/gm.gni b/gn/gm.gni
index c3132f6..e0a4d38 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -157,6 +157,7 @@
   "$_gm/drawbitmaprect.cpp",
   "$_gm/drawglyphs.cpp",
   "$_gm/drawimageset.cpp",
+  "$_gm/drawlines_with_local_matrix.cpp",
   "$_gm/drawminibitmaprect.cpp",
   "$_gm/drawregion.cpp",
   "$_gm/drawregionmodes.cpp",
diff --git a/src/gpu/ops/FillRRectOp.cpp b/src/gpu/ops/FillRRectOp.cpp
index a8b9b1f..b9e0d7f5 100644
--- a/src/gpu/ops/FillRRectOp.cpp
+++ b/src/gpu/ops/FillRRectOp.cpp
@@ -38,12 +38,27 @@
 public:
     DEFINE_OP_CLASS_ID
 
+    struct LocalCoords {
+        enum class Type : bool { kRect, kMatrix };
+        LocalCoords(const SkRect& localRect)
+                : fType(Type::kRect)
+                , fRect(localRect) {}
+        LocalCoords(const SkMatrix& localMatrix)
+                : fType(Type::kMatrix)
+                , fMatrix(localMatrix) {}
+        Type fType;
+        union {
+            SkRect fRect;
+            SkMatrix fMatrix;
+        };
+    };
+
     static GrOp::Owner Make(GrRecordingContext*,
                             SkArenaAlloc*,
                             GrPaint&&,
                             const SkMatrix& viewMatrix,
                             const SkRRect&,
-                            const SkRect& localRect,
+                            const LocalCoords&,
                             GrAA);
 
     const char* name() const override { return "FillRRectOp"; }
@@ -94,7 +109,7 @@
                     SkArenaAlloc*,
                     const SkMatrix& viewMatrix,
                     const SkRRect&,
-                    const SkRect& localRect,
+                    const LocalCoords&,
                     ProcessorFlags);
 
     GrProgramInfo* programInfo() override { return fProgramInfo; }
@@ -112,25 +127,12 @@
     Helper         fHelper;
     ProcessorFlags fProcessorFlags;
 
-    struct LocalCoords {
-        enum class Type : bool { kRect, kMatrix };
-        LocalCoords(const SkRect& localRect)
-                : fType(Type::kRect)
-                , fRect(localRect) {}
-        LocalCoords(const SkMatrix& localMatrix)
-                : fType(Type::kMatrix)
-                , fMatrix(localMatrix) {}
-        Type fType;
-        union {
-            SkRect fRect;
-            SkMatrix fMatrix;
-        };
-    };
-
     struct Instance {
-        Instance(const SkMatrix& viewMatrix, const SkRRect& rrect, const SkRect& localRect,
+        Instance(const SkMatrix& viewMatrix,
+                 const SkRRect& rrect,
+                 const LocalCoords& localCoords,
                  const SkPMColor4f& color)
-                : fViewMatrix(viewMatrix), fRRect(rrect), fLocalCoords(localRect), fColor(color) {
+                : fViewMatrix(viewMatrix), fRRect(rrect), fLocalCoords(localCoords), fColor(color) {
         }
         SkMatrix fViewMatrix;
         SkRRect fRRect;
@@ -166,7 +168,7 @@
                                   GrPaint&& paint,
                                   const SkMatrix& viewMatrix,
                                   const SkRRect& rrect,
-                                  const SkRect& localRect,
+                                  const LocalCoords& localCoords,
                                   GrAA aa) {
     const GrCaps* caps = ctx->priv().caps();
 
@@ -197,7 +199,7 @@
     }
 
     return Helper::FactoryHelper<FillRRectOpImpl>(ctx, std::move(paint), arena, viewMatrix, rrect,
-                                                  localRect, flags);
+                                                  localCoords, flags);
 }
 
 FillRRectOpImpl::FillRRectOpImpl(GrProcessorSet* processorSet,
@@ -205,7 +207,7 @@
                                  SkArenaAlloc* arena,
                                  const SkMatrix& viewMatrix,
                                  const SkRRect& rrect,
-                                 const SkRect& localRect,
+                                 const LocalCoords& localCoords,
                                  ProcessorFlags processorFlags)
         : GrMeshDrawOp(ClassID())
         , fHelper(processorSet,
@@ -215,7 +217,7 @@
         , fProcessorFlags(processorFlags & ~(ProcessorFlags::kHasLocalCoords |
                                              ProcessorFlags::kWideColor |
                                              ProcessorFlags::kMSAAEnabled))
-        , fHeadInstance(arena->make<Instance>(viewMatrix, rrect, localRect, paintColor))
+        , fHeadInstance(arena->make<Instance>(viewMatrix, rrect, localCoords, paintColor))
         , fTailInstance(&fHeadInstance->fNext) {
     // FillRRectOp::Make fails if there is perspective.
     SkASSERT(!viewMatrix.hasPerspective());
@@ -906,6 +908,16 @@
     return FillRRectOpImpl::Make(ctx, arena, std::move(paint), viewMatrix, rrect, localRect, aa);
 }
 
+GrOp::Owner Make(GrRecordingContext* ctx,
+                 SkArenaAlloc* arena,
+                 GrPaint&& paint,
+                 const SkMatrix& viewMatrix,
+                 const SkRRect& rrect,
+                 const SkMatrix& localMatrix,
+                 GrAA aa) {
+    return FillRRectOpImpl::Make(ctx, arena, std::move(paint), viewMatrix, rrect, localMatrix, aa);
+}
+
 } // namespace skgpu::v1::FillRRectOp
 
 #if GR_TEST_UTILS
diff --git a/src/gpu/ops/FillRRectOp.h b/src/gpu/ops/FillRRectOp.h
index 478cb6c..0443b0f 100644
--- a/src/gpu/ops/FillRRectOp.h
+++ b/src/gpu/ops/FillRRectOp.h
@@ -27,6 +27,14 @@
                      const SkRect& localRect,
                      GrAA);
 
+    GrOp::Owner Make(GrRecordingContext*,
+                     SkArenaAlloc*,
+                     GrPaint&&,
+                     const SkMatrix& viewMatrix,
+                     const SkRRect&,
+                     const SkMatrix& localMatrix,
+                     GrAA);
+
 }  // namespace skgpu::v1::FillRRectOp
 
 #endif // FillRRectOp_DEFINED
diff --git a/src/gpu/v1/SurfaceDrawContext.cpp b/src/gpu/v1/SurfaceDrawContext.cpp
index ae60262..2c057f3 100644
--- a/src/gpu/v1/SurfaceDrawContext.cpp
+++ b/src/gpu/v1/SurfaceDrawContext.cpp
@@ -1687,17 +1687,41 @@
     parallel *= halfWidth;
 
     SkVector ortho = { parallel.fY, -parallel.fX };
-    if (SkPaint::kButt_Cap == stroke.getCap()) {
-        // No extra extension for butt caps
-        parallel = {0.f, 0.f};
+    SkPoint p0 = points[0], p1 = points[1];
+    if (stroke.getCap() == SkPaint::kSquare_Cap) {
+        // Extra extension for square caps
+        p0 -= parallel;
+        p1 += parallel;
     }
+
+    // If we are using dmsaa or reduced shader mode then attempt to draw with FillRRectOp.
+    if (this->caps()->drawInstancedSupport() &&
+        (this->alwaysAntialias() ||
+         (fContext->priv().caps()->reducedShaderMode() && aa == GrAA::kYes))) {
+        SkMatrix localMatrix = SkMatrix::MakeAll(p1.fX - p0.fX, ortho.fX, p0.fX,
+                                                 p1.fY - p0.fY, ortho.fY, p0.fY,
+                                                 0, 0, 1);
+        if (auto op = FillRRectOp::Make(fContext,
+                                        this->arenaAlloc(),
+                                        std::move(paint),
+                                        SkMatrix::Concat(viewMatrix, localMatrix),
+                                        SkRRect::MakeRect({0,-1,1,1}),
+                                        localMatrix,
+                                        GrAA::kYes)) {
+            this->addDrawOp(clip, std::move(op));
+            return;
+        }
+    }
+
     // Order is TL, TR, BR, BL where arbitrarily "down" is p0 to p1 and "right" is positive
-    SkPoint corners[4] = { points[0] - ortho - parallel,
-                           points[0] + ortho - parallel,
-                           points[1] + ortho + parallel,
-                           points[1] - ortho + parallel };
+    SkPoint corners[4] = { p0 - ortho,
+                           p0 + ortho,
+                           p1 + ortho,
+                           p1 - ortho };
 
     GrQuadAAFlags edgeAA = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
+
+    assert_alive(paint);
     this->fillQuadWithEdgeAA(clip, std::move(paint), aa, edgeAA, viewMatrix, corners, nullptr);
 }