Add GrTextUtils::Target

This abstracts the portion of GrRenderTargetContext that is used by GrAtlasTextContext and opens the door to creating alternative consumers of GrAtlasTextOps.

Change-Id: Iaa48f93f4d7d49e231744d44427e9396c5d36fe7
Reviewed-on: https://skia-review.googlesource.com/64760
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 49d6474..5f071e8 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -10,6 +10,7 @@
 #include "../private/SkShadowFlags.h"
 #include "GrAppliedClip.h"
 #include "GrBackendSemaphore.h"
+#include "GrBlurUtils.h"
 #include "GrColor.h"
 #include "GrContextPriv.h"
 #include "GrDrawingManager.h"
@@ -24,12 +25,14 @@
 #include "GrStencilAttachment.h"
 #include "GrTracing.h"
 #include "SkDrawShadowInfo.h"
+#include "SkGr.h"
 #include "SkLatticeIter.h"
 #include "SkMatrixPriv.h"
 #include "SkShadowUtils.h"
 #include "SkSurfacePriv.h"
 #include "effects/GrRRectEffect.h"
 #include "instanced/InstancedRendering.h"
+#include "ops/GrAtlasTextOp.h"
 #include "ops/GrClearOp.h"
 #include "ops/GrClearStencilClipOp.h"
 #include "ops/GrDebugMarkerOp.h"
@@ -47,6 +50,41 @@
 #include "ops/GrTextureOp.h"
 #include "text/GrAtlasTextContext.h"
 #include "text/GrStencilAndCoverTextContext.h"
+#include "text/GrTextUtils.h"
+
+class GrRenderTargetContext::TextTarget : public GrTextUtils::Target {
+public:
+    TextTarget(GrRenderTargetContext* renderTargetContext)
+            : Target(renderTargetContext->width(), renderTargetContext->height(),
+                     renderTargetContext->colorSpaceInfo())
+            , fRenderTargetContext(renderTargetContext) {}
+
+    void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
+        fRenderTargetContext->addDrawOp(clip, std::move(op));
+    }
+
+    void drawPath(const GrClip& clip, const SkPath& path, const SkPaint& paint,
+                  const SkMatrix& viewMatrix, const SkMatrix* pathMatrix,
+                  const SkIRect& clipBounds) {
+        GrBlurUtils::drawPathWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
+                                            clip, path, paint, viewMatrix, pathMatrix, clipBounds,
+                                            false);
+    }
+
+    void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
+                     GrPaint* grPaint) {
+        GrContext* context = fRenderTargetContext->fContext;
+        const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
+        if (kARGB_GrMaskFormat == maskFormat) {
+            SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
+        } else {
+            SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
+        }
+    }
+
+private:
+    GrRenderTargetContext* fRenderTargetContext;
+};
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
 #define ASSERT_SINGLE_OWNER \
@@ -126,6 +164,7 @@
     // its rendertarget.
     this->getRTOpList();
 #endif
+    fTextTarget.reset(new TextTarget(this));
     SkDEBUGCODE(this->validate();)
 }
 
@@ -188,8 +227,8 @@
     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawText", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
-    atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
-                               byteLength, x, y, clipBounds);
+    atlasTextContext->drawText(fContext, fTextTarget.get(), clip, skPaint, viewMatrix,
+                               fSurfaceProps, text, byteLength, x, y, clipBounds);
 }
 
 void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
@@ -203,8 +242,9 @@
     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPosText", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
-    atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
-                                  byteLength, pos, scalarsPerPosition, offset, clipBounds);
+    atlasTextContext->drawPosText(fContext, fTextTarget.get(), clip, paint, viewMatrix,
+                                  fSurfaceProps, text, byteLength, pos, scalarsPerPosition, offset,
+                                  clipBounds);
 }
 
 void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
@@ -217,8 +257,8 @@
     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
 
     GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
-    atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
-                                   y, filter, clipBounds);
+    atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix,
+                                   fSurfaceProps, blob, x, y, filter, clipBounds);
 }
 
 void GrRenderTargetContext::discard() {
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index ea705db..82517b5 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -18,6 +18,7 @@
 #include "GrXferProcessor.h"
 #include "SkRefCnt.h"
 #include "SkSurfaceProps.h"
+#include "text/GrTextUtils.h"
 
 class GrBackendSemaphore;
 class GrCCPRAtlas;
@@ -367,6 +368,8 @@
     GrRenderTargetContextPriv priv();
     const GrRenderTargetContextPriv priv() const;
 
+    GrTextUtils::Target* textTarget() { return fTextTarget.get(); }
+
     bool isWrapped_ForTesting() const;
 
 protected:
@@ -377,6 +380,8 @@
     SkDEBUGCODE(void validate() const override;)
 
 private:
+    class TextTarget;
+
     inline GrAAType chooseAAType(GrAA aa, GrAllowMixedSamples allowMixedSamples) {
         return GrChooseAAType(aa, this->fsaaType(), allowMixedSamples, *this->caps());
     }
@@ -442,15 +447,16 @@
     GrRenderTargetOpList* getRTOpList();
     GrOpList* getOpList() override;
 
-    sk_sp<GrRenderTargetProxy>        fRenderTargetProxy;
+    std::unique_ptr<GrTextUtils::Target> fTextTarget;
+    sk_sp<GrRenderTargetProxy> fRenderTargetProxy;
 
     // In MDB-mode the GrOpList can be closed by some other renderTargetContext that has picked
     // it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
-    sk_sp<GrRenderTargetOpList>       fOpList;
-    GrInstancedPipelineInfo           fInstancedPipelineInfo;
+    sk_sp<GrRenderTargetOpList> fOpList;
+    GrInstancedPipelineInfo fInstancedPipelineInfo;
 
-    SkSurfaceProps                    fSurfaceProps;
-    bool                              fManagedOpList;
+    SkSurfaceProps fSurfaceProps;
+    bool fManagedOpList;
 
     typedef GrSurfaceContext INHERITED;
 };
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index a6dbd67..f083c85 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -9,7 +9,6 @@
 #include "GrBlurUtils.h"
 #include "GrClip.h"
 #include "GrContext.h"
-#include "GrRenderTargetContext.h"
 #include "GrTextUtils.h"
 #include "SkColorFilter.h"
 #include "SkDrawFilter.h"
@@ -257,24 +256,22 @@
     return false;
 }
 
-inline std::unique_ptr<GrDrawOp> GrAtlasTextBlob::makeOp(
+inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp(
         const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
         const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
         const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
-        const GrDistanceFieldAdjustTable* distanceAdjustTable,
-        GrAtlasGlyphCache* cache, GrRenderTargetContext* renderTargetContext) {
+        const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
+        GrTextUtils::Target* target) {
     GrMaskFormat format = info.maskFormat();
 
     GrPaint grPaint;
-    if (!paint.toGrPaint(info.maskFormat(), renderTargetContext, viewMatrix, &grPaint)) {
-        return nullptr;
-    }
+    target->makeGrPaint(info.maskFormat(), paint, viewMatrix, &grPaint);
     std::unique_ptr<GrAtlasTextOp> op;
     if (info.drawAsDistanceFields()) {
         bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
         op = GrAtlasTextOp::MakeDistanceField(
                 std::move(grPaint), glyphCount, cache, distanceAdjustTable,
-                renderTargetContext->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
+                target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
                 info.hasUseLCDText(), useBGR, info.isAntiAliased());
     } else {
         op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount, cache);
@@ -290,10 +287,10 @@
     geometry.fX = x;
     geometry.fY = y;
     op->init();
-    return std::move(op);
+    return op;
 }
 
-inline void GrAtlasTextBlob::flushRun(GrRenderTargetContext* rtc, const GrClip& clip, int run,
+inline void GrAtlasTextBlob::flushRun(GrTextUtils::Target* target, const GrClip& clip, int run,
                                       const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                       const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
                                       const GrDistanceFieldAdjustTable* distanceAdjustTable,
@@ -309,7 +306,7 @@
         bool skipClip = false;
         bool submitOp = true;
         SkIRect clipRect = SkIRect::MakeEmpty();
-        SkRect rtBounds = SkRect::MakeWH(rtc->width(), rtc->height());
+        SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
         SkRRect clipRRect;
         GrAA aa;
         // We can clip geometrically if we're not using SDFs,
@@ -332,12 +329,12 @@
 
         if (submitOp) {
             auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect,
-                                   std::move(paint), props, distanceAdjustTable, cache, rtc);
+                                   std::move(paint), props, distanceAdjustTable, cache, target);
             if (op) {
                 if (skipClip) {
-                    rtc->addDrawOp(GrNoClip(), std::move(op));
+                    target->addDrawOp(GrNoClip(), std::move(op));
                 } else {
-                    rtc->addDrawOp(clip, std::move(op));
+                    target->addDrawOp(clip, std::move(op));
                 }
             }
         }
@@ -364,7 +361,7 @@
     }
 }
 
-void GrAtlasTextBlob::flushBigGlyphs(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextBlob::flushBigGlyphs(GrContext* context, GrTextUtils::Target* target,
                                      const GrClip& clip, const SkPaint& paint,
                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                      const SkIRect& clipBounds) {
@@ -379,13 +376,11 @@
         if (!bigGlyph.fTreatAsBMP) {
             ctm.postConcat(viewMatrix);
         }
-
-        GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, bigGlyph.fPath, paint, ctm, nullptr,
-                                            clipBounds, false);
+        target->drawPath(clip, bigGlyph.fPath, paint, ctm, nullptr, clipBounds);
     }
 }
 
-void GrAtlasTextBlob::flushRunAsPaths(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextBlob::flushRunAsPaths(GrContext* context, GrTextUtils::Target* target,
                                       const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
                                       const GrClip& clip, const GrTextUtils::Paint& paint,
                                       SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
@@ -400,24 +395,24 @@
 
     switch (it.positioning()) {
         case SkTextBlob::kDefault_Positioning:
-            GrTextUtils::DrawTextAsPath(context, rtc, clip, runPaint, viewMatrix,
+            GrTextUtils::DrawTextAsPath(context, target, clip, runPaint, viewMatrix,
                                         (const char*)it.glyphs(), textLen, x + offset.x(),
                                         y + offset.y(), clipBounds);
             break;
         case SkTextBlob::kHorizontal_Positioning:
-            GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
+            GrTextUtils::DrawPosTextAsPath(context, target, props, clip, runPaint, viewMatrix,
                                            (const char*)it.glyphs(), textLen, it.pos(), 1,
                                            SkPoint::Make(x, y + offset.y()), clipBounds);
             break;
         case SkTextBlob::kFull_Positioning:
-            GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
+            GrTextUtils::DrawPosTextAsPath(context, target, props, clip, runPaint, viewMatrix,
                                            (const char*)it.glyphs(), textLen, it.pos(), 2,
                                            SkPoint::Make(x, y), clipBounds);
             break;
     }
 }
 
-void GrAtlasTextBlob::flushCached(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextBlob::flushCached(GrContext* context, GrTextUtils::Target* target,
                                   const SkTextBlob* blob, const SkSurfaceProps& props,
                                   const GrDistanceFieldAdjustTable* distanceAdjustTable,
                                   const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
@@ -428,42 +423,42 @@
     SkTextBlobRunIterator it(blob);
     for (int run = 0; !it.done(); it.next(), run++) {
         if (fRuns[run].fDrawAsPaths) {
-            this->flushRunAsPaths(context, rtc, props, it, clip, paint, drawFilter, viewMatrix,
+            this->flushRunAsPaths(context, target, props, it, clip, paint, drawFilter, viewMatrix,
                                   clipBounds, x, y);
             continue;
         }
-        this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
+        this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
                        context->getAtlasGlyphCache());
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
+    this->flushBigGlyphs(context, target, clip, paint, viewMatrix, x, y, clipBounds);
 }
 
-void GrAtlasTextBlob::flushThrowaway(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextBlob::flushThrowaway(GrContext* context, GrTextUtils::Target* target,
                                      const SkSurfaceProps& props,
                                      const GrDistanceFieldAdjustTable* distanceAdjustTable,
                                      const GrTextUtils::Paint& paint, const GrClip& clip,
                                      const SkMatrix& viewMatrix, const SkIRect& clipBounds,
                                      SkScalar x, SkScalar y) {
     for (int run = 0; run < fRunCount; run++) {
-        this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
+        this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
                        context->getAtlasGlyphCache());
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
+    this->flushBigGlyphs(context, target, clip, paint, viewMatrix, x, y, clipBounds);
 }
 
 std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp(
         int glyphCount, int run, int subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
         const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
         const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
-        GrRenderTargetContext* rtc) {
+        GrTextUtils::Target* target) {
     const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
     SkIRect emptyRect = SkIRect::MakeEmpty();
-    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, emptyRect,
-                        paint, props, distanceAdjustTable, cache, rtc);
+    return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, emptyRect, paint, props,
+                        distanceAdjustTable, cache, target);
 }
 
 void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) {
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 11f8505..0a90e20 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -183,14 +183,14 @@
                         const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
 
     // flush a GrAtlasTextBlob associated with a SkTextBlob
-    void flushCached(GrContext* context, GrRenderTargetContext* rtc, const SkTextBlob* blob,
+    void flushCached(GrContext* context, GrTextUtils::Target*, const SkTextBlob* blob,
                      const SkSurfaceProps& props,
                      const GrDistanceFieldAdjustTable* distanceAdjustTable,
                      const GrTextUtils::Paint&, SkDrawFilter* drawFilter, const GrClip& clip,
                      const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y);
 
     // flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
-    void flushThrowaway(GrContext* context, GrRenderTargetContext* rtc, const SkSurfaceProps& props,
+    void flushThrowaway(GrContext* context, GrTextUtils::Target*, const SkSurfaceProps& props,
                         const GrDistanceFieldAdjustTable* distanceAdjustTable,
                         const GrTextUtils::Paint& paint, const GrClip& clip,
                         const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
@@ -274,7 +274,7 @@
                                           const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                           const GrTextUtils::Paint&, const SkSurfaceProps&,
                                           const GrDistanceFieldAdjustTable*, GrAtlasGlyphCache*,
-                                          GrRenderTargetContext*);
+                                          GrTextUtils::Target*);
 
 private:
     GrAtlasTextBlob()
@@ -285,21 +285,21 @@
     void appendLargeGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph,
                           SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
 
-    inline void flushRun(GrRenderTargetContext* rtc, const GrClip&, int run,
-                         const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
-                         const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
+    inline void flushRun(GrTextUtils::Target*, const GrClip&, int run, const SkMatrix& viewMatrix,
+                         SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
+                         const SkSurfaceProps& props,
                          const GrDistanceFieldAdjustTable* distanceAdjustTable,
                          GrAtlasGlyphCache* cache);
 
-    void flushBigGlyphs(GrContext* context, GrRenderTargetContext* rtc, const GrClip& clip,
+    void flushBigGlyphs(GrContext* context, GrTextUtils::Target*, const GrClip& clip,
                         const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                         const SkIRect& clipBounds);
 
-    void flushRunAsPaths(GrContext* context, GrRenderTargetContext* rtc,
-                         const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
-                         const GrClip& clip, const GrTextUtils::Paint& paint,
-                         SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
-                         const SkIRect& clipBounds, SkScalar x, SkScalar y);
+    void flushRunAsPaths(GrContext* context, GrTextUtils::Target*, const SkSurfaceProps& props,
+                         const SkTextBlobRunIterator& it, const GrClip& clip,
+                         const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
+                         const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
+                         SkScalar y);
 
     // This function will only be called when we are generating a blob from scratch. We record the
     // initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
@@ -334,7 +334,7 @@
      * practice, the vast majority of runs have only a single subrun.
      *
      * Finally, for runs where the entire thing is too large for the GrAtlasTextContext to
-     * handle, we have a bit to mark the run as flusahable via rendering as paths.  It is worth
+     * handle, we have a bit to mark the run as flushable via rendering as paths.  It is worth
      * pointing. It would be a bit expensive to figure out ahead of time whether or not a run
      * can flush in this manner, so we always allocate vertices for the run, regardless of
      * whether or not it is too large.  The benefit of this strategy is that we can always reuse
@@ -497,13 +497,12 @@
                    Run* run, Run::SubRunInfo* info, SkAutoGlyphCache*, int glyphCount,
                    size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const;
 
-    inline std::unique_ptr<GrDrawOp> makeOp(const Run::SubRunInfo& info, int glyphCount, int run,
-                                            int subRun, const SkMatrix& viewMatrix,
-                                            SkScalar x, SkScalar y, const SkIRect& clipRect,
-                                            const GrTextUtils::Paint& paint,
-                                            const SkSurfaceProps& props,
-                                            const GrDistanceFieldAdjustTable* distanceAdjustTable,
-                                            GrAtlasGlyphCache* cache, GrRenderTargetContext*);
+    inline std::unique_ptr<GrAtlasTextOp> makeOp(
+            const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
+            const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
+            const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
+            const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
+            GrTextUtils::Target*);
 
     struct BigGlyph {
         BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, bool treatAsBMP)
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index adf4980..e5a8745 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -6,7 +6,6 @@
  */
 #include "GrAtlasTextContext.h"
 #include "GrContext.h"
-#include "GrRenderTargetContext.h"
 #include "GrTextBlobCache.h"
 #include "SkDraw.h"
 #include "SkDrawFilter.h"
@@ -73,11 +72,10 @@
     return false;
 }
 
-void GrAtlasTextContext::drawTextBlob(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target,
                                       const GrClip& clip, const SkPaint& skPaint,
-                                      const SkMatrix& viewMatrix,
-                                      const SkSurfaceProps& props, const SkTextBlob* blob,
-                                      SkScalar x, SkScalar y,
+                                      const SkMatrix& viewMatrix, const SkSurfaceProps& props,
+                                      const SkTextBlob* blob, SkScalar x, SkScalar y,
                                       SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
     // If we have been abandoned, then don't draw
     if (context->abandoned()) {
@@ -93,7 +91,7 @@
     bool canCache = !(skPaint.getPathEffect() ||
                       (mf && !mf->asABlur(&blurRec)) ||
                       drawFilter);
-    uint32_t scalerContextFlags = ComputeScalerContextFlags(rtc->colorSpaceInfo());
+    uint32_t scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
 
     GrTextBlobCache* cache = context->getTextBlobCache();
     if (canCache) {
@@ -118,7 +116,7 @@
         cacheBlob = cache->find(key);
     }
 
-    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
     if (cacheBlob) {
         if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) {
             // We have to remake the blob because changes may invalidate our masks.
@@ -155,8 +153,8 @@
                            props, blob, x, y, drawFilter);
     }
 
-    cacheBlob->flushCached(context, rtc, blob, props, fDistanceAdjustTable.get(), paint, drawFilter,
-                           clip, viewMatrix, clipBounds, x, y);
+    cacheBlob->flushCached(context, target, blob, props, fDistanceAdjustTable.get(), paint,
+                           drawFilter, clip, viewMatrix, clipBounds, x, y);
 }
 
 void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob,
@@ -287,7 +285,7 @@
     return blob;
 }
 
-void GrAtlasTextContext::drawText(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* target,
                                   const GrClip& clip, const SkPaint& skPaint,
                                   const SkMatrix& viewMatrix, const SkSurfaceProps& props,
                                   const char text[], size_t byteLength, SkScalar x, SkScalar y,
@@ -295,56 +293,58 @@
     if (context->abandoned()) {
         return;
     }
-    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
     if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
         sk_sp<GrAtlasTextBlob> blob(
                 MakeDrawTextBlob(context->getTextBlobCache(), context->getAtlasGlyphCache(),
                                  *context->caps()->shaderCaps(), paint,
-                                 ComputeScalerContextFlags(rtc->colorSpaceInfo()), viewMatrix,
+                                 ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix,
                                  props, text, byteLength, x, y));
         if (blob) {
-            blob->flushThrowaway(context, rtc, props, fDistanceAdjustTable.get(), paint, clip,
+            blob->flushThrowaway(context, target, props, fDistanceAdjustTable.get(), paint, clip,
                                  viewMatrix, regionClipBounds, x, y);
         }
         return;
     }
 
     // fall back to drawing as a path
-    GrTextUtils::DrawTextAsPath(context, rtc, clip, paint, viewMatrix, text, byteLength, x, y,
+    GrTextUtils::DrawTextAsPath(context, target, clip, paint, viewMatrix, text, byteLength, x, y,
                                 regionClipBounds);
 }
 
-void GrAtlasTextContext::drawPosText(GrContext* context, GrRenderTargetContext* rtc,
+void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target,
                                      const GrClip& clip, const SkPaint& skPaint,
                                      const SkMatrix& viewMatrix, const SkSurfaceProps& props,
                                      const char text[], size_t byteLength, const SkScalar pos[],
                                      int scalarsPerPosition, const SkPoint& offset,
                                      const SkIRect& regionClipBounds) {
-    GrTextUtils::Paint paint(&skPaint, &rtc->colorSpaceInfo());
+    GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
     if (context->abandoned()) {
         return;
     } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
         sk_sp<GrAtlasTextBlob> blob(
                 MakeDrawPosTextBlob(context->getTextBlobCache(), context->getAtlasGlyphCache(),
                                     *context->caps()->shaderCaps(), paint,
-                                    ComputeScalerContextFlags(rtc->colorSpaceInfo()), viewMatrix,
+                                    ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix,
                                     props, text, byteLength, pos, scalarsPerPosition, offset));
         if (blob) {
-            blob->flushThrowaway(context, rtc, props, fDistanceAdjustTable.get(), paint, clip,
+            blob->flushThrowaway(context, target, props, fDistanceAdjustTable.get(), paint, clip,
                                  viewMatrix, regionClipBounds, offset.fX, offset.fY);
         }
         return;
     }
 
     // fall back to drawing as a path
-    GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, paint, viewMatrix, text, byteLength,
-                                   pos, scalarsPerPosition, offset, regionClipBounds);
+    GrTextUtils::DrawPosTextAsPath(context, target, props, clip, paint, viewMatrix, text,
+                                   byteLength, pos, scalarsPerPosition, offset, regionClipBounds);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #if GR_TEST_UTILS
 
+#include "GrRenderTargetContext.h"
+
 GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
     static uint32_t gContextID = SK_InvalidGenID;
     static GrAtlasTextContext* gTextContext = nullptr;
@@ -394,7 +394,7 @@
 
     return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, gSurfaceProps,
                              gTextContext->dfAdjustTable(), context->getAtlasGlyphCache(),
-                             rtc.get());
+                             rtc->textTarget());
 }
 
 #endif
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index f9540de..905adc0 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -19,7 +19,6 @@
 #endif
 
 class GrDrawOp;
-class GrRenderTargetContext;
 class GrTextBlobCache;
 class SkGlyph;
 
@@ -33,17 +32,16 @@
     bool canDraw(const SkPaint&, const SkMatrix& viewMatrix, const SkSurfaceProps&,
                  const GrShaderCaps&);
 
-    void drawText(GrContext*, GrRenderTargetContext*, const GrClip&, const SkPaint&,
+    void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
                   const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
                   size_t byteLength, SkScalar x, SkScalar y, const SkIRect& regionClipBounds);
-    void drawPosText(GrContext*, GrRenderTargetContext*, const GrClip&, const SkPaint&,
+    void drawPosText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
                      const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
                      size_t byteLength, const SkScalar pos[], int scalarsPerPosition,
                      const SkPoint& offset, const SkIRect& regionClipBounds);
-    void drawTextBlob(GrContext*, GrRenderTargetContext*, const GrClip&, const SkPaint&,
+    void drawTextBlob(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
                       const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
-                      SkScalar x, SkScalar y,
-                      SkDrawFilter*, const SkIRect& clipBounds);
+                      SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds);
 
 private:
     GrAtlasTextContext();
diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp
index 4b8dd51..b072702 100644
--- a/src/gpu/text/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp
@@ -83,8 +83,8 @@
         }
         return;
     }
-    fFallbackTextContext->drawText(context, rtc, clip, skPaint, viewMatrix, props, text,
-                                       byteLength, x, y, clipBounds);
+    fFallbackTextContext->drawText(context, rtc->textTarget(), clip, skPaint, viewMatrix, props,
+                                   text, byteLength, x, y, clipBounds);
 }
 
 void GrStencilAndCoverTextContext::drawPosText(GrContext* context, GrRenderTargetContext* rtc,
@@ -105,8 +105,9 @@
         }
         return;
     }
-    fFallbackTextContext->drawPosText(context, rtc, clip, skPaint, viewMatrix, props, text,
-                                      byteLength, pos, scalarsPerPosition, offset, clipBounds);
+    fFallbackTextContext->drawPosText(context, rtc->textTarget(), clip, skPaint, viewMatrix, props,
+                                      text, byteLength, pos, scalarsPerPosition, offset,
+                                      clipBounds);
 }
 
 void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context,
@@ -161,8 +162,8 @@
     }
 
     if (!this->internalCanDraw(skPaint)) {
-        fFallbackTextContext->drawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob,
-                                           x, y, drawFilter, clipBounds);
+        fFallbackTextContext->drawTextBlob(context, rtc->textTarget(), clip, skPaint, viewMatrix,
+                                           props, skBlob, x, y, drawFilter, clipBounds);
         return;
     }
 
@@ -598,9 +599,9 @@
             fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio);
         }
 
-        fallbackTextContext->drawTextBlob(ctx, renderTargetContext, clip, fallbackSkPaint,
-                                          viewMatrix, props, fFallbackTextBlob.get(), x, y, nullptr,
-                                          clipBounds);
+        fallbackTextContext->drawTextBlob(ctx, renderTargetContext->textTarget(), clip,
+                                          fallbackSkPaint, viewMatrix, props,
+                                          fFallbackTextBlob.get(), x, y, nullptr, clipBounds);
     }
 }
 
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index 5465d28..d5eac10 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -11,8 +11,6 @@
 #include "GrBlurUtils.h"
 #include "GrCaps.h"
 #include "GrContext.h"
-#include "GrRenderTargetContext.h"
-#include "GrSurfaceContextPriv.h"
 #include "SkDistanceFieldGen.h"
 #include "SkDrawFilter.h"
 #include "SkDrawProcs.h"
@@ -39,19 +37,6 @@
 #endif
 };
 
-bool GrTextUtils::Paint::toGrPaint(GrMaskFormat maskFormat, GrRenderTargetContext* rtc,
-                                   const SkMatrix& viewMatrix, GrPaint* grPaint) const {
-    // TODO: this is the last use of GrSurfaceContextPriv
-    GrContext* context = rtc->surfPriv().getContext();
-    if (kARGB_GrMaskFormat == maskFormat) {
-        return SkPaintToGrPaintWithPrimitiveColor(context, rtc->colorSpaceInfo(), this->skPaint(),
-                                                  grPaint);
-    } else {
-        return SkPaintToGrPaint(context, rtc->colorSpaceInfo(), this->skPaint(), viewMatrix,
-                                grPaint);
-    }
-}
-
 void GrTextUtils::Paint::initFilteredColor() {
     // This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors
     if (fDstColorSpaceInfo->colorSpace()) {
@@ -506,10 +491,10 @@
     return true;
 }
 
-void GrTextUtils::DrawTextAsPath(GrContext* context, GrRenderTargetContext* rtc, const GrClip& clip,
-                                 const SkPaint& paint, const SkMatrix& viewMatrix,
-                                 const char text[], size_t byteLength, SkScalar x, SkScalar y,
-                                 const SkIRect& clipBounds) {
+void GrTextUtils::DrawTextAsPath(GrContext* context, GrTextUtils::Target* target,
+                                 const GrClip& clip, const SkPaint& paint,
+                                 const SkMatrix& viewMatrix, const char text[], size_t byteLength,
+                                 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
     if (!paint.countText(text, byteLength)) {
         return;
     }
@@ -526,21 +511,18 @@
         matrix.postTranslate(xpos - prevXPos, 0);
         if (iterPath) {
             const SkPaint& pnt = iter.getPaint();
-            GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, *iterPath,
-                                                pnt, viewMatrix, &matrix, clipBounds, false);
+            target->drawPath(clip, *iterPath, pnt, viewMatrix, &matrix, clipBounds);
         }
         prevXPos = xpos;
     }
 }
 
-void GrTextUtils::DrawPosTextAsPath(GrContext* context,
-                                    GrRenderTargetContext* rtc,
-                                    const SkSurfaceProps& props,
-                                    const GrClip& clip,
+void GrTextUtils::DrawPosTextAsPath(GrContext* context, GrTextUtils::Target* target,
+                                    const SkSurfaceProps& props, const GrClip& clip,
                                     const SkPaint& origPaint, const SkMatrix& viewMatrix,
-                                    const char text[], size_t byteLength,
-                                    const SkScalar pos[], int scalarsPerPosition,
-                                    const SkPoint& offset, const SkIRect& clipBounds) {
+                                    const char text[], size_t byteLength, const SkScalar pos[],
+                                    int scalarsPerPosition, const SkPoint& offset,
+                                    const SkIRect& clipBounds) {
     if (!origPaint.countText(text, byteLength)) {
         return;
     }
@@ -581,8 +563,7 @@
 
                 matrix[SkMatrix::kMTransX] = loc.fX;
                 matrix[SkMatrix::kMTransY] = loc.fY;
-                GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, *path, paint,
-                                                    viewMatrix, &matrix, clipBounds, false);
+                target->drawPath(clip, *path, paint, viewMatrix, &matrix, clipBounds);
             }
         }
         pos += scalarsPerPosition;
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index bd0a1ad..d8d841f 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -11,19 +11,18 @@
 #include "GrColor.h"
 #include "GrColorSpaceInfo.h"
 #include "SkColorFilter.h"
-#include "SkGr.h"
 #include "SkPaint.h"
 #include "SkScalar.h"
 #include "SkTLazy.h"
 
 class GrAtlasGlyphCache;
 class GrAtlasTextBlob;
+class GrAtlasTextOp;
 class GrAtlasTextStrike;
 class GrClip;
 class GrColorSpaceXform;
 class GrContext;
 class GrPaint;
-class GrRenderTargetContext;
 class GrShaderCaps;
 class SkColorSpace;
 class SkDrawFilter;
@@ -41,6 +40,32 @@
  */
 class GrTextUtils {
 public:
+    class Target {
+    public:
+        virtual ~Target() = default;
+
+        int width() const { return fWidth; }
+        int height() const { return fHeight; }
+        const GrColorSpaceInfo& colorSpaceInfo() const { return fColorSpaceInfo; }
+
+        virtual void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) = 0;
+
+        virtual void drawPath(const GrClip&, const SkPath&, const SkPaint&,
+                              const SkMatrix& viewMatrix, const SkMatrix* pathMatrix,
+                              const SkIRect& clipBounds) = 0;
+        virtual void makeGrPaint(GrMaskFormat, const SkPaint&, const SkMatrix& viewMatrix,
+                                 GrPaint*) = 0;
+
+    protected:
+        Target(int width, int height, const GrColorSpaceInfo& colorSpaceInfo)
+                : fWidth(width), fHeight(height), fColorSpaceInfo(colorSpaceInfo) {}
+
+    private:
+        int fWidth;
+        int fHeight;
+        const GrColorSpaceInfo& fColorSpaceInfo;
+    };
+
     /**
      *  This is used to wrap a SkPaint and its post-color filter color. It is also used by RunPaint
      *  (below). This keeps a pointer to the SkPaint it is initialized with and expects it to remain
@@ -61,9 +86,6 @@
         const SkPaint& skPaint() const { return *fPaint; }
         operator const SkPaint&() const { return this->skPaint(); }
 
-        bool toGrPaint(GrMaskFormat, GrRenderTargetContext*, const SkMatrix& viewMatrix,
-                       GrPaint*) const;
-
         // Just for RunPaint's constructor
         const GrColorSpaceInfo* dstColorSpaceInfo() const { return fDstColorSpaceInfo; }
 
@@ -130,17 +152,15 @@
                               int scalarsPerPosition, const SkPoint& offset);
 
     // Functions for drawing text as paths
-    static void DrawTextAsPath(GrContext*, GrRenderTargetContext*, const GrClip& clip,
-                               const SkPaint& paint, const SkMatrix& viewMatrix, const char text[],
-                               size_t byteLength, SkScalar x, SkScalar y,
-                               const SkIRect& clipBounds);
+    static void DrawTextAsPath(GrContext*, Target*, const GrClip& clip, const SkPaint& paint,
+                               const SkMatrix& viewMatrix, const char text[], size_t byteLength,
+                               SkScalar x, SkScalar y, const SkIRect& clipBounds);
 
-    static void DrawPosTextAsPath(GrContext* context, GrRenderTargetContext* rtc,
-                                  const SkSurfaceProps& props, const GrClip& clip,
-                                  const SkPaint& paint, const SkMatrix& viewMatrix,
-                                  const char text[], size_t byteLength, const SkScalar pos[],
-                                  int scalarsPerPosition, const SkPoint& offset,
-                                  const SkIRect& clipBounds);
+    static void DrawPosTextAsPath(GrContext* context, Target*, const SkSurfaceProps& props,
+                                  const GrClip& clip, const SkPaint& paint,
+                                  const SkMatrix& viewMatrix, const char text[], size_t byteLength,
+                                  const SkScalar pos[], int scalarsPerPosition,
+                                  const SkPoint& offset, const SkIRect& clipBounds);
 
     static bool ShouldDisableLCD(const SkPaint& paint);