Add GrSurfaceFillContext

This is a new base class for GrSurfaceDrawContext. It allows any
alpha-type but is restricted to non-blending fills of irects using FPs,
clears,and discards.

Bug: skia:11019

Change-Id: I229ce5f452e66796e2fa5c0e7a6ddccbf23bef5c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341680
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index ab40c07..b9c9444 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -45,8 +45,6 @@
 
     std::unique_ptr<GrSurfaceContext> surfaceContext;
     if (proxy->asRenderTargetProxy()) {
-        SkASSERT(info.alphaType() == kPremul_SkAlphaType ||
-                 info.alphaType() == kOpaque_SkAlphaType);
         // Will we ever want a swizzle that is not the default write swizzle for the format and
         // colorType here? If so we will need to manually pass that in.
         GrSwizzle writeSwizzle;
@@ -55,12 +53,19 @@
                                                                    info.colorType());
         }
         GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle);
-        surfaceContext = std::make_unique<GrSurfaceDrawContext>(context,
-                                                                std::move(readView),
-                                                                std::move(writeView),
-                                                                info.colorType(),
-                                                                info.refColorSpace(),
-                                                                /*surface props*/ nullptr);
+        if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) {
+            surfaceContext = std::make_unique<GrSurfaceDrawContext>(context,
+                                                                    std::move(readView),
+                                                                    std::move(writeView),
+                                                                    info.colorType(),
+                                                                    info.refColorSpace(),
+                                                                    /*surface props*/ nullptr);
+        } else {
+            surfaceContext = std::make_unique<GrSurfaceFillContext>(context,
+                                                                    std::move(readView),
+                                                                    std::move(writeView),
+                                                                    info);
+        }
     } else {
         surfaceContext = std::make_unique<GrSurfaceContext>(context, std::move(readView), info);
     }
@@ -237,11 +242,14 @@
             GrColorType colorType = (canvas2DFastPath || srcIsCompressed)
                                             ? GrColorType::kRGBA_8888
                                             : this->colorInfo().colorType();
-            tempCtx = GrSurfaceDrawContext::Make(
-                    dContext, colorType, this->colorInfo().refColorSpace(), SkBackingFit::kApprox,
-                    dstInfo.dimensions(), 1, GrMipMapped::kNo, GrProtected::kNo,
-                    kTopLeft_GrSurfaceOrigin);
-            if (!tempCtx) {
+            SkAlphaType alphaType = canvas2DFastPath ? dstInfo.alphaType()
+                                                     : this->colorInfo().alphaType();
+            GrImageInfo tempInfo(colorType,
+                                 alphaType,
+                                 this->colorInfo().refColorSpace(),
+                                 dstInfo.dimensions());
+            auto sfc = GrSurfaceFillContext::Make(dContext, tempInfo, SkBackingFit::kApprox);
+            if (!sfc) {
                 return false;
             }
 
@@ -253,25 +261,17 @@
                     fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
                     dstInfo = dstInfo.makeColorType(GrColorType::kRGBA_8888);
                 }
-                // The render target context is incorrectly tagged as kPremul even though we're
-                // writing unpremul data thanks to the PMToUPM effect. Fake out the dst alpha type
-                // so we don't double unpremul.
-                dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
             } else {
                 fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
             }
             if (!fp) {
                 return false;
             }
-            GrPaint paint;
-            paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-            paint.setColorFragmentProcessor(std::move(fp));
-
-            tempCtx->asRenderTargetContext()->fillRectToRect(
-                    nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
-                    SkRect::MakeWH(dstInfo.width(), dstInfo.height()),
-                    SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height()));
+            sfc->fillRectToRectWithFP(SkIRect::MakePtSize(pt, dstInfo.dimensions()),
+                                      SkIRect::MakeSize(dstInfo.dimensions()),
+                                      std::move(fp));
             pt = {0, 0};
+            tempCtx = std::move(sfc);
         } else {
             auto restrictions = this->caps()->getDstCopyRestrictions(this->asRenderTargetProxy(),
                                                                      this->colorInfo().colorType());
@@ -404,7 +404,7 @@
     bool canvas2DFastPath = !caps->avoidWritePixelsFastPath() && premul && !needColorConversion &&
                             (srcInfo.colorType() == GrColorType::kRGBA_8888 ||
                              srcInfo.colorType() == GrColorType::kBGRA_8888) &&
-                            SkToBool(this->asRenderTargetContext()) &&
+                            this->asFillContext() &&
                             (dstColorType == GrColorType::kRGBA_8888 ||
                              dstColorType == GrColorType::kBGRA_8888) &&
                             rgbaDefaultFormat.isValid() &&
@@ -434,7 +434,7 @@
         // we can use a draw instead which doesn't have this origin restriction. Thus for render
         // targets we will use top left and otherwise we will make the origins match.
         GrSurfaceOrigin tempOrigin =
-                this->asRenderTargetContext() ? kTopLeft_GrSurfaceOrigin : this->origin();
+                this->asFillContext() ? kTopLeft_GrSurfaceOrigin : this->origin();
         auto tempProxy = dContext->priv().proxyProvider()->createProxy(
                 format, srcInfo.dimensions(), GrRenderable::kNo, 1, GrMipmapped::kNo,
                 SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
@@ -455,7 +455,7 @@
             return false;
         }
 
-        if (this->asRenderTargetContext()) {
+        if (this->asFillContext()) {
             std::unique_ptr<GrFragmentProcessor> fp;
             if (canvas2DFastPath) {
                 fp = dContext->priv().createUPMToPMEffect(
@@ -470,13 +470,10 @@
             if (!fp) {
                 return false;
             }
-            GrPaint paint;
-            paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-            paint.setColorFragmentProcessor(std::move(fp));
-            this->asRenderTargetContext()->fillRectToRect(
-                    nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
-                    SkRect::MakeXYWH(pt.fX, pt.fY, srcInfo.width(), srcInfo.height()),
-                    SkRect::MakeWH(srcInfo.width(), srcInfo.height()));
+            this->asFillContext()->fillRectToRectWithFP(
+                    SkIRect::MakeSize(srcInfo.dimensions()),
+                    SkIRect::MakePtSize(pt, srcInfo.dimensions()),
+                    std::move(fp));
         } else {
             SkIRect srcRect = SkIRect::MakeWH(srcInfo.width(), srcInfo.height());
             SkIPoint dstPoint = SkIPoint::Make(pt.fX, pt.fY);