Revert of Make GrTextContext be owned by the GrDrawContext (patchset #7 id:120001 of https://codereview.chromium.org/1175553002/)

Reason for revert:
Breaking Test-Win8-MSVC-ShuttleA-GPU-GTX660-x86_64-Debug ?

https://build.chromium.org/p/client.skia/builders/Test-Win8-MSVC-ShuttleA-GPU-GTX660-x86_64-Debug/builds/436/steps/dm/logs/stdio

Original issue's description:
> Make GrTextContext be owned by the GrDrawContext
>
> This CL makes the GrTextContext be owned (and hidden) by the GrDrawContext. This funnels all the drawText* calls through the GrDrawContext and hides the (dispreferred) GrPipelineBuilder drawText variant.
>
> Some consequences of this are:
>
> GrDrawContext now has to get the text drawing settings (i.e., SkDeviceProperties & useDFT). This means that we need a separate GrDrawContext for each combination of pixel geometry and DFT-use.
>
> All the GrTextContext-derived classes now get a back pointer to the originating GrDrawContext so their method calls no longer take one.
>
> Committed: https://skia.googlesource.com/skia/+/5b16e740fe6ab6d679083d06f07651602265081b

TBR=joshualitt@chromium.org,joshualitt@google.com,jvanverth@google.com,reed@google.com,robertphillips@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1178383003
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index e95f2c0..acd7b1a 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -43,6 +43,7 @@
 class GrVertexBuffer;
 class GrStrokeInfo;
 class GrSoftwarePathRenderer;
+class SkGpuDevice;
 
 class SK_API GrContext : public SkRefCnt {
 public:
@@ -173,16 +174,11 @@
 
     /**
      * Returns a helper object to orchestrate draws. 
-     * Callers should take a ref if they rely on the GrDrawContext sticking around.
-     * NULL will be returned if the context has been abandoned.
-     *
-     * @param  devProps the device properties (mainly defines text drawing)
-     * @param  uesDFT should Distance Field Text be used?
      *
      * @return a draw context
      */
-    GrDrawContext* drawContext(const SkDeviceProperties* devProps = NULL, bool useDFT = false) {
-        return fDrawingMgr.drawContext(devProps, useDFT);    
+    GrDrawContext* drawContext() {
+        return fDrawingMgr.drawContext();    
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -394,17 +390,15 @@
     GrContext(); // init must be called after the constructor.
     bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
 
-    // Currently the DrawingMgr stores a separate GrDrawContext for each
-    // combination of text drawing options (pixel geometry x DFT use)
-    // and hands the appropriate one back given the user's request.
-    // All of the GrDrawContexts still land in the same GrDrawTarget!
-    //
-    // In the future this class will allocate a new GrDrawContext for 
-    // each GrRenderTarget/GrDrawTarget and manage the DAG.
+    // Currently the DrawingMgr just wraps the single GrDrawTarget in a single
+    // GrDrawContext and hands it out. In the future this class will allocate
+    // a new GrDrawContext for each GrRenderTarget/GrDrawTarget and manage
+    // the DAG.
     class DrawingMgr {
     public:
-        DrawingMgr() : fDrawTarget(NULL) {
-            sk_bzero(fDrawContext, sizeof(fDrawContext));
+        DrawingMgr()
+            : fDrawTarget(NULL)
+            , fDrawContext(NULL) {
         }
 
         ~DrawingMgr();
@@ -420,18 +414,14 @@
 
         // Callers should take a ref if they rely on the GrDrawContext sticking around.
         // NULL will be returned if the context has been abandoned.
-        GrDrawContext* drawContext(const SkDeviceProperties* devProps, bool useDFT);
+        GrDrawContext* drawContext();
 
     private:
         friend class GrContext;  // for access to fDrawTarget for testing
 
-        static const int kNumPixelGeometries = 5; // The different pixel geometries
-        static const int kNumDFTOptions = 2;      // DFT or no DFT
-
-        GrContext*        fContext;
         GrDrawTarget*     fDrawTarget;
 
-        GrDrawContext*    fDrawContext[kNumPixelGeometries][kNumDFTOptions];
+        GrDrawContext*    fDrawContext;
     };
 
     DrawingMgr                      fDrawingMgr;
@@ -440,6 +430,18 @@
     void initCommon();
 
     /**
+     * Creates a new text rendering context that is optimal for the
+     * render target and the context. Caller assumes the ownership
+     * of the returned object. The returned object must be deleted
+     * before the context is destroyed.
+     * TODO bury this behind context!
+     */
+    GrTextContext* createTextContext(GrRenderTarget*,
+                                     const SkDeviceProperties&,
+                                     bool enableDistanceFieldFonts);
+
+
+    /**
      * These functions create premul <-> unpremul effects if it is possible to generate a pair
      * of effects that make a readToUPM->writeToPM->readToUPM cycle invariant. Otherwise, they
      * return NULL.
@@ -459,6 +461,9 @@
      */
     static void TextBlobCacheOverBudgetCB(void* data);
 
+    // TODO see note on createTextContext
+    friend class SkGpuDevice;
+
     typedef SkRefCnt INHERITED;
 };
 
diff --git a/include/gpu/GrDrawContext.h b/include/gpu/GrDrawContext.h
index 7e71126..4b78c89 100644
--- a/include/gpu/GrDrawContext.h
+++ b/include/gpu/GrDrawContext.h
@@ -22,18 +22,14 @@
 class GrRenderTarget;
 class GrStrokeInfo;
 class GrSurface;
-class GrTextContext;
-struct SkDeviceProperties;
-class SkDrawFilter;
 struct SkIPoint;
 struct SkIRect;
 class SkMatrix;
-class SkPaint;
 class SkPath;
 struct SkPoint;
 struct SkRect;
 class SkRRect;
-class SkTextBlob;
+
 
 /*
  * A helper object to orchestrate draws
@@ -42,28 +38,14 @@
 public:
     SK_DECLARE_INST_COUNT(GrDrawContext)
 
-    ~GrDrawContext() override;
-
     void copySurface(GrRenderTarget* dst, GrSurface* src,
                      const SkIRect& srcRect, const SkIPoint& dstPoint);
 
-    // TODO: it is odd that we need both the SkPaint in the following 3 methods.
-    // We should extract the text parameters from SkPaint and pass them separately
-    // akin to GrStrokeInfo (GrTextInfo?)
-    void drawText(GrRenderTarget*, const GrClip&,  const GrPaint&, const SkPaint&,
-                  const SkMatrix& viewMatrix, const char text[], size_t byteLength,
-                  SkScalar x, SkScalar y, const SkIRect& clipBounds);
-    void drawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
-                     const SkMatrix& viewMatrix, const char text[], size_t byteLength,
-                     const SkScalar pos[], int scalarsPerPosition,
-                     const SkPoint& offset, const SkIRect& clipBounds);
-    void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
-                      const SkMatrix& viewMatrix, const SkTextBlob*,
-                      SkScalar x, SkScalar y,
-                      SkDrawFilter*, const SkIRect& clipBounds);
+    // drawText and drawPaths are thanks to the GrAtlasTextContext and the 
+    // GrStencilAndCoverTextContext respectively
+    // TODO: remove these two
+    void drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch);
 
-    // drawPaths is thanks to GrStencilAndCoverTextContext
-    // TODO: remove
     void drawPaths(GrPipelineBuilder* pipelineBuilder,
                    const GrPathProcessor* pathProc,
                    const GrPathRange* pathRange,
@@ -241,17 +223,16 @@
 
 
 private:
-    friend class GrAtlasTextContext; // for access to drawBatch
     friend class GrContext; // for ctor
 
-    GrDrawContext(GrContext*, GrDrawTarget*, const SkDeviceProperties&, bool useDFT);
+    GrDrawContext(GrContext* context, GrDrawTarget* drawTarget);
+    ~GrDrawContext() override;
 
     // Sets the paint. Returns true on success; false on failure.
     bool prepareToDraw(GrPipelineBuilder*,
                        GrRenderTarget* rt,
                        const GrClip&,
                        const GrPaint* paint);
-    GrTextContext* createTextContext(GrRenderTarget*, const SkDeviceProperties&, bool useDFT);
 
     // A simpler version of the above which just returns true on success; false on failure.  
     // Clip is *NOT* set
@@ -265,16 +246,8 @@
                           const SkPath&,
                           const GrStrokeInfo&);
 
-    // This entry point allows the GrTextContext-derived classes to add their batches to
-    // the drawTarget.
-    void drawBatch(GrPipelineBuilder* pipelineBuilder, GrBatch* batch);
-
-    GrContext*          fContext;     // owning context -> no ref
-    GrDrawTarget*       fDrawTarget;
-    GrTextContext*      fTextContext; // lazily created
-
-    SkDeviceProperties* fDevProps;    // ptr b.c. SkDeviceProperties isn't public
-    bool                fUseDFT;
+    GrContext*     fContext;     // owning context -> no ref
+    GrDrawTarget*  fDrawTarget;
 };
 
 #endif
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 45d4b30..14784a2 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -19,7 +19,7 @@
 #include "SkTextToPathIter.h"
 
 SkBaseDevice::SkBaseDevice()
-    : fLeakyProperties(SkNEW(SkDeviceProperties))
+    : fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLegacyLCD_InitType)))
 #ifdef SK_DEBUG
     , fAttachedToCanvas(false)
 #endif
diff --git a/src/core/SkDeviceProperties.h b/src/core/SkDeviceProperties.h
index 85f87bc..e79f21a 100644
--- a/src/core/SkDeviceProperties.h
+++ b/src/core/SkDeviceProperties.h
@@ -11,12 +11,11 @@
 #include "SkSurfacePriv.h"
 
 struct SkDeviceProperties {
-    SkDeviceProperties(const SkDeviceProperties& src) 
-        : fGamma(src.fGamma)
-        , fPixelGeometry(src.fPixelGeometry) {
-    }
+    enum InitType {
+        kLegacyLCD_InitType
+    };
 
-    SkDeviceProperties(float gamma = SK_GAMMA_EXPONENT)
+    SkDeviceProperties(InitType, float gamma = SK_GAMMA_EXPONENT)
         : fGamma(gamma)
         , fPixelGeometry(SkSurfacePropsDefaultPixelGeometry())
     {}
@@ -26,15 +25,15 @@
         , fPixelGeometry(geo)
     {}
 
-    float gamma() const { return fGamma; }
     SkPixelGeometry pixelGeometry() const { return fPixelGeometry; }
+    float gamma() const { return fGamma; }
 
     void setPixelGeometry(SkPixelGeometry geo) {
         fPixelGeometry = geo;
     }
 
 private:
-    const float     fGamma;
+    const float   fGamma;
     SkPixelGeometry fPixelGeometry;
 };
 
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index d1076bb..75aaf04 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -13,7 +13,6 @@
 #include "GrBlurUtils.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawContext.h"
-#include "GrDrawTarget.h"
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrResourceProvider.h"
@@ -98,10 +97,9 @@
 // Distance field text in textblobs
 
 GrAtlasTextContext::GrAtlasTextContext(GrContext* context,
-                                       GrDrawContext* drawContext,
                                        const SkDeviceProperties& properties,
-                                       bool useDFT)
-    : INHERITED(context, drawContext, properties)
+                                       bool enableDistanceFields)
+    : INHERITED(context, properties)
     , fDistanceAdjustTable(SkNEW_ARGS(DistanceAdjustTable, (properties.gamma()))) {
     // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
     // vertexStride
@@ -113,7 +111,7 @@
 #if SK_FORCE_DISTANCE_FIELD_TEXT
     fEnableDFRendering = true;
 #else
-    fEnableDFRendering = useDFT;
+    fEnableDFRendering = enableDistanceFields;
 #endif
 }
 
@@ -200,10 +198,9 @@
 }
 
 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
-                                               GrDrawContext* drawContext,
                                                const SkDeviceProperties& props,
-                                               bool useDFT) {
-    return SkNEW_ARGS(GrAtlasTextContext, (context, drawContext, props, useDFT));
+                                               bool enableDistanceFields) {
+    return SkNEW_ARGS(GrAtlasTextContext, (context, props, enableDistanceFields));
 }
 
 bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
@@ -359,6 +356,11 @@
         return;
     }
 
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (!drawContext) {
+        return;
+    }
+
     SkAutoTUnref<BitmapTextBlob> cacheBlob;
     SkMaskFilter::BlurRec blurRec;
     BitmapTextBlob::Key key;
@@ -433,7 +435,7 @@
     }
 
     cacheBlob->fPaintColor = skPaint.getColor();
-    this->flush(blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
+    this->flush(drawContext, blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
                 clip, viewMatrix, clipBounds, x, y, transX, transY);
 }
 
@@ -775,32 +777,36 @@
     return blob;
 }
 
-void GrAtlasTextContext::onDrawText(GrRenderTarget* rt,
+void GrAtlasTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
                                     const GrClip& clip, 
                                     const GrPaint& paint, const SkPaint& skPaint,
                                     const SkMatrix& viewMatrix,
                                     const char text[], size_t byteLength,
                                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
-    SkAutoTUnref<BitmapTextBlob> blob(
-        this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
-                                 text, byteLength, x, y, regionClipBounds));
-    this->flush(blob, rt, skPaint, paint, clip, regionClipBounds);
+    if (drawContext) {
+        SkAutoTUnref<BitmapTextBlob> blob(
+            this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
+                                     text, byteLength, x, y, regionClipBounds));
+        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
+    }
 }
 
-void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt,
+void GrAtlasTextContext::onDrawPosText(GrDrawContext* drawContext, GrRenderTarget* rt,
                                        const GrClip& clip,
                                        const GrPaint& paint, const SkPaint& skPaint,
                                        const SkMatrix& viewMatrix,
                                        const char text[], size_t byteLength,
                                        const SkScalar pos[], int scalarsPerPosition,
                                        const SkPoint& offset, const SkIRect& regionClipBounds) {
-    SkAutoTUnref<BitmapTextBlob> blob(
-        this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
-                                    text, byteLength,
-                                    pos, scalarsPerPosition,
-                                    offset, regionClipBounds));
+    if (drawContext) {
+        SkAutoTUnref<BitmapTextBlob> blob(
+            this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
+                                        text, byteLength,
+                                        pos, scalarsPerPosition,
+                                        offset, regionClipBounds));
 
-    this->flush(blob, rt, skPaint, paint, clip, regionClipBounds);
+        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
+    }
 }
 
 void GrAtlasTextContext::internalDrawBMPText(BitmapTextBlob* blob, int runIndex,
@@ -2039,7 +2045,8 @@
     float fGamma;
 };
 
-void GrAtlasTextContext::flushRunAsPaths(GrRenderTarget* rt, const SkTextBlob::RunIterator& it, 
+void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* drawContext,
+                                         GrRenderTarget* rt, const SkTextBlob::RunIterator& it, 
                                          const GrClip& clip, const SkPaint& skPaint,
                                          SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
                                          const SkIRect& clipBounds, SkScalar x, SkScalar y) {
@@ -2058,18 +2065,18 @@
 
     switch (it.positioning()) {
         case SkTextBlob::kDefault_Positioning:
-            this->drawTextAsPath(rt, clip, runPaint, viewMatrix,
+            this->drawTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
                                  (const char *)it.glyphs(),
                                  textLen, x + offset.x(), y + offset.y(), clipBounds);
             break;
         case SkTextBlob::kHorizontal_Positioning:
-            this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix,
+            this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
                                     (const char*)it.glyphs(),
                                     textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
                                     clipBounds);
             break;
         case SkTextBlob::kFull_Positioning:
-            this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix,
+            this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
                                     (const char*)it.glyphs(),
                                     textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
             break;
@@ -2121,7 +2128,8 @@
     return batch;
 }
 
-inline void GrAtlasTextContext::flushRun(GrPipelineBuilder* pipelineBuilder,
+inline void GrAtlasTextContext::flushRun(GrDrawContext* drawContext,
+                                         GrPipelineBuilder* pipelineBuilder,
                                          BitmapTextBlob* cacheBlob, int run, GrColor color,
                                          SkScalar transX, SkScalar transY,
                                          const SkPaint& skPaint) {
@@ -2135,11 +2143,12 @@
         SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, glyphCount, run,
                                                               subRun, color, transX, transY,
                                                               skPaint));
-        fDrawContext->drawBatch(pipelineBuilder, batch);
+        drawContext->drawText(pipelineBuilder, batch);
     }
 }
 
-inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
+inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob,
+                                               GrDrawContext* drawContext, GrRenderTarget* rt,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                SkScalar transX, SkScalar transY,
                                                const SkIRect& clipBounds) {
@@ -2160,12 +2169,13 @@
         SkMatrix translate = cacheBlob->fViewMatrix;
         translate.postTranslate(bigGlyph.fVx, bigGlyph.fVy);
 
-        GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, bigGlyph.fPath,
+        GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, bigGlyph.fPath,
                                             skPaint, translate, &pathMatrix, clipBounds, false);
     }
 }
 
-void GrAtlasTextContext::flush(const SkTextBlob* blob,
+void GrAtlasTextContext::flush(GrDrawContext* drawContext,
+                               const SkTextBlob* blob,
                                BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
                                const SkPaint& skPaint,
@@ -2186,20 +2196,21 @@
     SkTextBlob::RunIterator it(blob);
     for (int run = 0; !it.done(); it.next(), run++) {
         if (cacheBlob->fRuns[run].fDrawAsPaths) {
-            this->flushRunAsPaths(rt, it, clip, skPaint,
+            this->flushRunAsPaths(drawContext, rt, it, clip, skPaint,
                                   drawFilter, viewMatrix, clipBounds, x, y);
             continue;
         }
         cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
-        this->flushRun(&pipelineBuilder, cacheBlob, run, color,
+        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color,
                        transX, transY, skPaint);
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(cacheBlob, rt, clip, skPaint, transX, transY, clipBounds);
+    this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, transX, transY, clipBounds);
 }
 
-void GrAtlasTextContext::flush(BitmapTextBlob* cacheBlob,
+void GrAtlasTextContext::flush(GrDrawContext* drawContext,
+                               BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
                                const SkPaint& skPaint,
                                const GrPaint& grPaint,
@@ -2210,11 +2221,11 @@
 
     GrColor color = grPaint.getColor();
     for (int run = 0; run < cacheBlob->fRunCount; run++) {
-        this->flushRun(&pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
+        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(cacheBlob, rt, clip, skPaint, 0, 0, clipBounds);
+    this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, 0, 0, clipBounds);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2224,19 +2235,15 @@
 BATCH_TEST_DEFINE(TextBlobBatch) {
     static uint32_t gContextID = SK_InvalidGenID;
     static GrAtlasTextContext* gTextContext = NULL;
-    static SkDeviceProperties gDevProperties;
+    static SkDeviceProperties gDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
 
     if (context->uniqueID() != gContextID) {
         gContextID = context->uniqueID();
         SkDELETE(gTextContext);
-
-        static const bool kUseDFT = false;
         // We don't yet test the fall back to paths in the GrTextContext base class.  This is mostly
         // because we don't really want to have a gpu device here.
         // We enable distance fields by twiddling a knob on the paint
-        GrDrawContext* drawContext = context->drawContext(&gDevProperties, kUseDFT);
-
-        gTextContext = GrAtlasTextContext::Create(context, drawContext, gDevProperties, kUseDFT);
+        gTextContext = GrAtlasTextContext::Create(context, gDeviceProperties, false);
     }
 
     // create dummy render target
diff --git a/src/gpu/GrAtlasTextContext.h b/src/gpu/GrAtlasTextContext.h
index 47bb7ae..9a4ef6a 100644
--- a/src/gpu/GrAtlasTextContext.h
+++ b/src/gpu/GrAtlasTextContext.h
@@ -25,7 +25,6 @@
 
 class BitmapTextBatch;
 class GrDrawContext;
-class GrDrawTarget;
 class GrPipelineBuilder;
 class GrTextBlobCache;
 
@@ -35,20 +34,20 @@
  */
 class GrAtlasTextContext : public GrTextContext {
 public:
-    static GrAtlasTextContext* Create(GrContext*, GrDrawContext*,
-                                      const SkDeviceProperties&, bool enableDistanceFields);
+    static GrAtlasTextContext* Create(GrContext*, const SkDeviceProperties&,
+                                      bool enableDistanceFields);
 
 private:
-    GrAtlasTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&, bool useDFT);
+    GrAtlasTextContext(GrContext*, const SkDeviceProperties&, bool enableDistanceFields);
     ~GrAtlasTextContext() override {}
 
     bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                  const SkPaint&, const SkMatrix& viewMatrix) override;
 
-    void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix, const char text[], size_t byteLength,
                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
-    void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&,
+    void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&,
                        const SkPaint&, const SkMatrix& viewMatrix,
                        const char text[], size_t byteLength,
                        const SkScalar pos[], int scalarsPerPosition,
@@ -272,7 +271,7 @@
                                   size_t vertexStride, bool useVertexColor,
                                   GrGlyph*);
 
-    inline void flushRunAsPaths(GrRenderTarget*,
+    inline void flushRunAsPaths(GrDrawContext*, GrRenderTarget*,
                                 const SkTextBlob::RunIterator&, const GrClip& clip,
                                 const SkPaint&, SkDrawFilter*,
                                 const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
@@ -281,18 +280,18 @@
                                         int glyphCount, int run, int subRun,
                                         GrColor, SkScalar transX, SkScalar transY,
                                         const SkPaint&);
-    inline void flushRun(GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
+    inline void flushRun(GrDrawContext*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
                          SkScalar transX, SkScalar transY, const SkPaint&);
-    inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget*,
+    inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrDrawContext*, GrRenderTarget*,
                                const GrClip& clip, const SkPaint& skPaint,
                                SkScalar transX, SkScalar transY, const SkIRect& clipBounds);
 
     // We have to flush SkTextBlobs differently from drawText / drawPosText
-    void flush(const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
+    void flush(GrDrawContext*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
                const SkPaint&, const GrPaint&, SkDrawFilter*, const GrClip&,
                const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y,
                SkScalar transX, SkScalar transY);
-    void flush(BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
+    void flush(GrDrawContext*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
                const GrPaint&, const GrClip&, const SkIRect& clipBounds);
 
     // A helper for drawing BitmapText in a run of distance fields
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 9e33340..64f4cb3 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -9,6 +9,7 @@
 #include "GrContext.h"
 
 #include "GrAARectRenderer.h"
+#include "GrAtlasTextContext.h"
 #include "GrBatch.h"
 #include "GrBatchFontCache.h"
 #include "GrBatchTarget.h"
@@ -31,6 +32,7 @@
 #include "GrResourceCache.h"
 #include "GrResourceProvider.h"
 #include "GrSoftwarePathRenderer.h"
+#include "GrStencilAndCoverTextContext.h"
 #include "GrStrokeInfo.h"
 #include "GrSurfacePriv.h"
 #include "GrTextBlobCache.h"
@@ -60,33 +62,24 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::DrawingMgr::init(GrContext* context) {
-    fContext = context;
-
 #ifdef IMMEDIATE_MODE
     fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context));
 #else
     fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context));
 #endif    
+
+    fDrawContext = SkNEW_ARGS(GrDrawContext, (context, fDrawTarget));
 }
 
 GrContext::DrawingMgr::~DrawingMgr() {
     SkSafeUnref(fDrawTarget);
-    for (int i = 0; i < kNumPixelGeometries; ++i) {
-        SkSafeUnref(fDrawContext[i][0]);
-        SkSafeUnref(fDrawContext[i][1]);
-    }
+    SkSafeUnref(fDrawContext);
 }
 
 void GrContext::DrawingMgr::abandon() {
     SkSafeSetNull(fDrawTarget);
-    for (int i = 0; i < kNumPixelGeometries; ++i) {
-        for (int j = 0; j < kNumDFTOptions; ++j) {
-            if (fDrawContext[i][j]) {
-                SkSafeSetNull(fDrawContext[i][j]->fDrawTarget);
-                SkSafeSetNull(fDrawContext[i][j]);
-            }
-        }
-    }
+    SkSafeSetNull(fDrawContext->fDrawTarget);
+    SkSafeSetNull(fDrawContext);
 }
 
 void GrContext::DrawingMgr::purgeResources() {
@@ -107,29 +100,11 @@
     }
 }
 
-GrDrawContext* GrContext::DrawingMgr::drawContext(const SkDeviceProperties* devProps, bool useDFT) { 
+GrDrawContext* GrContext::DrawingMgr::drawContext() { 
     if (this->abandoned()) {
         return NULL;
     }
-
-    const SkDeviceProperties defProps;
-    if (!devProps) {
-        devProps = &defProps;
-    }
-
-    SkASSERT(devProps->pixelGeometry() < kNumPixelGeometries);
-    if (!fDrawContext[devProps->pixelGeometry()][useDFT]) {
-        fDrawContext[devProps->pixelGeometry()][useDFT] =
-                SkNEW_ARGS(GrDrawContext, (fContext, fDrawTarget, *devProps, useDFT));
-    }
-
-    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->pixelGeometry() ==
-             devProps->pixelGeometry());
-    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->gamma() == 
-             devProps->gamma());
-    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fUseDFT == useDFT);
-
-    return fDrawContext[devProps->pixelGeometry()][useDFT]; 
+    return fDrawContext; 
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -271,6 +246,21 @@
     }
 }
 
+GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
+                                            const SkDeviceProperties&
+                                            leakyProperties,
+                                            bool enableDistanceFieldFonts) {
+    if (fGpu->caps()->shaderCaps()->pathRenderingSupport() &&
+        renderTarget->isStencilBufferMultisampled()) {
+        GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
+        if (sb) {
+            return GrStencilAndCoverTextContext::Create(this, leakyProperties);
+        }
+    } 
+
+    return GrAtlasTextContext::Create(this, leakyProperties, enableDistanceFieldFonts);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::OverBudgetCB(void* data) {
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 7f97275..23c349b 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -7,16 +7,12 @@
  */
 
 #include "GrAARectRenderer.h"
-#include "GrAtlasTextContext.h"
 #include "GrBatch.h"
 #include "GrBatchTest.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawContext.h"
 #include "GrOvalRenderer.h"
 #include "GrPathRenderer.h"
-#include "GrRenderTarget.h"
-#include "GrRenderTargetPriv.h"
-#include "GrStencilAndCoverTextContext.h"
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
 #define RETURN_IF_ABANDONED        if (!fDrawTarget) { return; }
@@ -32,21 +28,13 @@
     GrContext* fContext;
 };
 
-GrDrawContext::GrDrawContext(GrContext* context,
-                             GrDrawTarget* drawTarget,
-                             const SkDeviceProperties& devProps,
-                             bool useDFT)
+GrDrawContext::GrDrawContext(GrContext* context, GrDrawTarget* drawTarget)
     : fContext(context)
-    , fDrawTarget(SkRef(drawTarget))
-    , fTextContext(NULL)
-    , fDevProps(SkNEW_ARGS(SkDeviceProperties, (devProps)))
-    , fUseDFT(useDFT) {
+    , fDrawTarget(SkRef(drawTarget)) {
 }
 
 GrDrawContext::~GrDrawContext() {
     SkSafeUnref(fDrawTarget);
-    SkDELETE(fTextContext);
-    SkDELETE(fDevProps);
 }
 
 void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src,
@@ -58,58 +46,8 @@
     fDrawTarget->copySurface(dst, src, srcRect, dstPoint);
 }
 
-GrTextContext* GrDrawContext::createTextContext(GrRenderTarget* renderTarget,
-                                                const SkDeviceProperties& leakyProperties,
-                                                bool enableDistanceFieldFonts) {
-    if (fContext->caps()->shaderCaps()->pathRenderingSupport() &&
-        renderTarget->isStencilBufferMultisampled()) {
-        GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
-        if (sb) {
-            return GrStencilAndCoverTextContext::Create(fContext, this, 
-                                                        leakyProperties,
-                                                        enableDistanceFieldFonts);
-        }
-    } 
-
-    return GrAtlasTextContext::Create(fContext, this, leakyProperties, enableDistanceFieldFonts);
-}
-
-void GrDrawContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint,
-                             const SkPaint& skPaint,
-                             const SkMatrix& viewMatrix,
-                             const char text[], size_t byteLength,
-                             SkScalar x, SkScalar y, const SkIRect& clipBounds) {
-    if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
-    }
-
-    fTextContext->drawText(rt, clip, grPaint, skPaint, viewMatrix,
-                           text, byteLength, x, y, clipBounds);
-
-}
-void GrDrawContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint,
-                                const SkPaint& skPaint,
-                                const SkMatrix& viewMatrix,
-                                const char text[], size_t byteLength,
-                                const SkScalar pos[], int scalarsPerPosition,
-                                const SkPoint& offset, const SkIRect& clipBounds) {
-    if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
-    }
-
-    fTextContext->drawPosText(rt, clip, grPaint, skPaint, viewMatrix, text, byteLength,
-                               pos, scalarsPerPosition, offset, clipBounds);
-
-}
-void GrDrawContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const SkPaint& skPaint,
-                                 const SkMatrix& viewMatrix, const SkTextBlob* blob,
-                                 SkScalar x, SkScalar y,
-                                 SkDrawFilter* filter, const SkIRect& clipBounds) {
-    if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
-    }
-
-    fTextContext->drawTextBlob(rt, clip, skPaint, viewMatrix, blob, x, y, filter, clipBounds);
+void GrDrawContext::drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
+    fDrawTarget->drawBatch(pipelineBuilder, batch);
 }
 
 void GrDrawContext::drawPaths(GrPipelineBuilder* pipelineBuilder,
@@ -1209,10 +1147,6 @@
     return true;
 }
 
-void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
-    fDrawTarget->drawBatch(pipelineBuilder, batch);
-}
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #ifdef GR_TEST_UTILS
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index d1b6a84..763863f 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -22,21 +22,18 @@
 #include "SkTextFormatParams.h"
 
 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
-                                                           GrDrawContext* drawContext,
                                                            const SkDeviceProperties& properties)
-    : GrTextContext(context, drawContext, properties)
+    : GrTextContext(context, properties)
     , fStroke(SkStrokeRec::kFill_InitStyle)
     , fQueuedGlyphCount(0)
     , fFallbackGlyphsIdx(kGlyphBufferSize) {
 }
 
 GrStencilAndCoverTextContext*
-GrStencilAndCoverTextContext::Create(GrContext* context, GrDrawContext* drawContext,
-                                     const SkDeviceProperties& props, bool fallbackUsesDFT) {
+GrStencilAndCoverTextContext::Create(GrContext* context, const SkDeviceProperties& props) {
     GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext,
-                                                           (context, drawContext, props));
-    textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, drawContext,
-                                                                   props, fallbackUsesDFT);
+                                                           (context, props));
+    textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, props, false);
 
     return textContext;
 }
@@ -74,7 +71,7 @@
     return rec.getFormat() != SkMask::kARGB32_Format;
 }
 
-void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt,
+void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
                                               const GrClip& clip,
                                               const GrPaint& paint,
                                               const SkPaint& skPaint,
@@ -157,17 +154,19 @@
         const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
         fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
         if (glyph.fWidth) {
-            this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
+            this->appendGlyph(drawContext, glyph, 
+                              SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
         }
 
         fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
         fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
     }
 
-    this->finish();
+    this->finish(drawContext);
 }
 
-void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt,
+void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* drawContext,
+                                                 GrRenderTarget* rt,
                                                  const GrClip& clip,
                                                  const GrPaint& paint,
                                                  const SkPaint& skPaint,
@@ -211,12 +210,12 @@
             SkPoint loc;
             alignProc(tmsLoc, glyph, &loc);
 
-            this->appendGlyph(glyph, loc);
+            this->appendGlyph(drawContext, glyph, loc);
         }
         pos += scalarsPerPosition;
     }
 
-    this->finish();
+    this->finish(drawContext);
 }
 
 static GrPathRange* get_gr_glyphs(GrContext* ctx,
@@ -411,10 +410,11 @@
     return true;
 }
 
-inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
+inline void GrStencilAndCoverTextContext::appendGlyph(GrDrawContext* drawContext,
+                                                      const SkGlyph& glyph, const SkPoint& pos) {
     if (fQueuedGlyphCount >= fFallbackGlyphsIdx) {
         SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx);
-        this->flush();
+        this->flush(drawContext);
     }
 
     // Stick the glyphs we can't draw at the end of the buffer, growing backwards.
@@ -432,17 +432,17 @@
     return &pointArray[0].fX;
 }
 
-void GrStencilAndCoverTextContext::flush() {
+void GrStencilAndCoverTextContext::flush(GrDrawContext* drawContext) {
     if (fQueuedGlyphCount > 0) {
         SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(),
                                                                  fViewMatrix,
                                                                  fLocalMatrix));
 
-        fDrawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
-                                fGlyphIndices, GrPathRange::kU16_PathIndexType,
-                                get_xy_scalar_array(fGlyphPositions),
-                                GrPathRendering::kTranslate_PathTransformType,
-                                fQueuedGlyphCount, GrPathRendering::kWinding_FillType);
+        drawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
+                               fGlyphIndices, GrPathRange::kU16_PathIndexType,
+                               get_xy_scalar_array(fGlyphPositions),
+                               GrPathRendering::kTranslate_PathTransformType,
+                               fQueuedGlyphCount, GrPathRendering::kWinding_FillType);
 
         fQueuedGlyphCount = 0;
     }
@@ -474,8 +474,8 @@
     }
 }
 
-void GrStencilAndCoverTextContext::finish() {
-    this->flush();
+void GrStencilAndCoverTextContext::finish(GrDrawContext* drawContext) {
+    this->flush(drawContext);
 
     fGlyphs->unref();
     fGlyphs = NULL;
diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h
index 920f2d7..d36b60f 100644
--- a/src/gpu/GrStencilAndCoverTextContext.h
+++ b/src/gpu/GrStencilAndCoverTextContext.h
@@ -23,8 +23,7 @@
  */
 class GrStencilAndCoverTextContext : public GrTextContext {
 public:
-    static GrStencilAndCoverTextContext* Create(GrContext*, GrDrawContext*,
-                                                const SkDeviceProperties&, bool fallbackUsesDFT);
+    static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&);
 
     virtual ~GrStencilAndCoverTextContext();
 
@@ -68,16 +67,16 @@
     SkMatrix                                            fLocalMatrix;
     bool                                                fUsingDeviceSpaceGlyphs;
 
-    GrStencilAndCoverTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&);
+    GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
 
     bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                  const SkPaint&, const SkMatrix& viewMatrix) override;
 
-    void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix,
                     const char text[], size_t byteLength,
                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
-    void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                        const SkMatrix& viewMatrix,
                        const char text[], size_t byteLength,
                        const SkScalar pos[], int scalarsPerPosition,
@@ -87,9 +86,9 @@
               size_t textByteLength, RenderMode, const SkMatrix& viewMatrix,
               const SkIRect& regionClipBounds);
     bool mapToFallbackContext(SkMatrix* inverse);
-    void appendGlyph(const SkGlyph&, const SkPoint&);
-    void flush();
-    void finish();
+    void appendGlyph(GrDrawContext*, const SkGlyph&, const SkPoint&);
+    void flush(GrDrawContext*);
+    void finish(GrDrawContext*);
 
 };
 
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 5559b2d..91c8e85 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -20,12 +20,10 @@
 #include "SkTextMapStateProc.h"
 #include "SkTextToPathIter.h"
 
-GrTextContext::GrTextContext(GrContext* context, GrDrawContext* drawContext,
-                             const SkDeviceProperties& properties)
+GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties)
     : fFallbackTextContext(NULL)
     , fContext(context)
-    , fDeviceProperties(properties)
-    , fDrawContext(drawContext) {
+    , fDeviceProperties(properties) {
 }
 
 GrTextContext::~GrTextContext() {
@@ -49,14 +47,19 @@
                              const SkPaint& skPaint, const SkMatrix& viewMatrix,
                              const char text[], size_t byteLength,
                              SkScalar x, SkScalar y, const SkIRect& clipBounds) {
-    if (fContext->abandoned() || !fDrawContext) {
+    if (fContext->abandoned()) {
+        return;
+    }
+
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (!drawContext) {
         return;
     }
 
     GrTextContext* textContext = this;
     do {
         if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
-            textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix,
+            textContext->onDrawText(drawContext, rt, clip, paint, skPaint, viewMatrix,
                                     text, byteLength, x, y, clipBounds);
             return;
         }
@@ -64,7 +67,7 @@
     } while (textContext);
 
     // fall back to drawing as a path
-    this->drawTextAsPath(rt, clip, skPaint, viewMatrix,
+    this->drawTextAsPath(drawContext, rt, clip, skPaint, viewMatrix,
                          text, byteLength, x, y, clipBounds);
 }
 
@@ -73,14 +76,19 @@
                                 const char text[], size_t byteLength,
                                 const SkScalar pos[], int scalarsPerPosition,
                                 const SkPoint& offset, const SkIRect& clipBounds) {
-    if (fContext->abandoned() || !fDrawContext) {
+    if (fContext->abandoned()) {
+        return;
+    }
+
+    GrDrawContext* drawContext = fContext->drawContext();
+    if (!drawContext) {
         return;
     }
 
     GrTextContext* textContext = this;
     do {
         if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
-            textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix,
+            textContext->onDrawPosText(drawContext, rt, clip, paint, skPaint, viewMatrix,
                                        text, byteLength, pos,
                                        scalarsPerPosition, offset, clipBounds);
             return;
@@ -89,7 +97,7 @@
     } while (textContext);
 
     // fall back to drawing as a path
-    this->drawPosTextAsPath(rt, clip, skPaint, viewMatrix, text, byteLength, pos,
+    this->drawPosTextAsPath(drawContext, rt, clip, skPaint, viewMatrix, text, byteLength, pos,
                             scalarsPerPosition, offset, clipBounds);
 }
 
@@ -175,7 +183,7 @@
     }
 }
 
-void GrTextContext::drawTextAsPath(GrRenderTarget* rt,
+void GrTextContext::drawTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
                                    const GrClip& clip,
                                    const SkPaint& skPaint, const SkMatrix& viewMatrix,
                                    const char text[], size_t byteLength, SkScalar x, SkScalar y,
@@ -193,14 +201,14 @@
         matrix.postTranslate(xpos - prevXPos, 0);
         if (iterPath) {
             const SkPaint& pnt = iter.getPaint();
-            GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, *iterPath,
+            GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *iterPath,
                                                 pnt, viewMatrix, &matrix, clipBounds, false);
         }
         prevXPos = xpos;
     }
 }
 
-void GrTextContext::drawPosTextAsPath(GrRenderTarget* rt,
+void GrTextContext::drawPosTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
                                       const GrClip& clip,
                                       const SkPaint& origPaint, const SkMatrix& viewMatrix,
                                       const char text[], size_t byteLength,
@@ -241,7 +249,7 @@
 
                 matrix[SkMatrix::kMTransX] = loc.fX;
                 matrix[SkMatrix::kMTransY] = loc.fY;
-                GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, *path, paint,
+                GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *path, paint,
                                                     viewMatrix, &matrix, clipBounds, false);
             }
         }
diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h
index 775203e..f4c0982 100644
--- a/src/gpu/GrTextContext.h
+++ b/src/gpu/GrTextContext.h
@@ -48,7 +48,6 @@
     GrContext*                     fContext;
     SkDeviceProperties             fDeviceProperties;
 
-    GrDrawContext*                 fDrawContext;  // owning drawContext
     SkAutoTUnref<GrRenderTarget>   fRenderTarget;
     GrClip                         fClip;
     SkIRect                        fClipRect;
@@ -56,27 +55,27 @@
     GrPaint                        fPaint;
     SkPaint                        fSkPaint;
 
-    GrTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&);
+    GrTextContext(GrContext*, const SkDeviceProperties&);
 
     virtual bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                          const SkPaint&, const SkMatrix& viewMatrix) = 0;
 
-    virtual void onDrawText(GrRenderTarget*, const GrClip&,
+    virtual void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&,
                             const GrPaint&, const SkPaint&,
                             const SkMatrix& viewMatrix, const char text[], size_t byteLength,
                             SkScalar x, SkScalar y, const SkIRect& clipBounds) = 0;
-    virtual void onDrawPosText(GrRenderTarget*, const GrClip&,
+    virtual void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&,
                                const GrPaint&, const SkPaint&,
                                const SkMatrix& viewMatrix,
                                const char text[], size_t byteLength,
                                const SkScalar pos[], int scalarsPerPosition,
                                const SkPoint& offset, const SkIRect& clipBounds) = 0;
 
-    void drawTextAsPath(GrRenderTarget*, const GrClip& clip,
+    void drawTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
                         const SkPaint& origPaint, const SkMatrix& viewMatrix,
                         const char text[], size_t byteLength, SkScalar x, SkScalar y,
                         const SkIRect& clipBounds);
-    void drawPosTextAsPath(GrRenderTarget*, const GrClip& clip,
+    void drawPosTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
                            const SkPaint& origPaint, const SkMatrix& viewMatrix,
                            const char text[], size_t byteLength,
                            const SkScalar pos[], int scalarsPerPosition,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 07c8dc1..18b2643 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -10,7 +10,6 @@
 #include "GrBlurUtils.h"
 #include "GrContext.h"
 #include "GrDrawContext.h"
-#include "GrFontScaler.h"
 #include "GrGpu.h"
 #include "GrGpuResourcePriv.h"
 #include "GrLayerHoister.h"
@@ -138,7 +137,7 @@
     if (props) {
         return SkDeviceProperties(props->pixelGeometry());
     } else {
-        return SkDeviceProperties();
+        return SkDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
     }
 }
 
@@ -168,7 +167,8 @@
     fLegacyBitmap.setPixelRef(pr)->unref();
 
     bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
-    fDrawContext.reset(SkRef(fContext->drawContext(&this->getLeakyProperties(), useDFT)));
+    fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT);
+    fDrawContext.reset(SkRef(fContext->drawContext()));
 }
 
 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::Budgeted budgeted,
@@ -227,6 +227,8 @@
         delete fDrawProcs;
     }
 
+    SkDELETE(fTextContext);
+
     fRenderTarget->unref();
     fContext->unref();
 }
@@ -353,9 +355,7 @@
     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
     fLegacyBitmap.setPixelRef(pr)->unref();
 
-    bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
-    fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext(&this->getLeakyProperties(),
-                                                                      useDFT)));
+    fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext()));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1638,7 +1638,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fDrawContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
+    fTextContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
                            (const char *)text, byteLength, x, y, draw.fClip->getBounds());
 }
 
@@ -1655,7 +1655,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fDrawContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
+    fTextContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
                               (const char *)text, byteLength, pos, scalarsPerPos, offset,
                               draw.fClip->getBounds());
 }
@@ -1667,7 +1667,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fDrawContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix,
+    fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix,
                                blob, x, y, drawFilter, draw.fClip->getBounds());
 }
 
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index cf85cd9..c06cdc2 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -23,6 +23,7 @@
 
 class GrAccelData;
 struct GrCachedLayer;
+class GrTextContext;
 
 /**
  *  Subclass of SkBaseDevice, which directs all drawing to the GrGpu owned by the
@@ -150,6 +151,7 @@
     SkAutoTUnref<const SkClipStack> fClipStack;
     SkIPoint                        fClipOrigin;
     GrClip                          fClip;
+    GrTextContext*                  fTextContext;
     SkAutoTUnref<GrDrawContext>     fDrawContext;
     SkSurfaceProps                  fSurfaceProps;
     GrRenderTarget*                 fRenderTarget;
@@ -217,6 +219,7 @@
                                               int sampleCount);
 
     friend class GrAtlasTextContext;
+    friend class GrTextContext;
     typedef SkBaseDevice INHERITED;
 };
 
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index dfb8f92..eaaed8a 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -228,8 +228,8 @@
 
     const SkRect rect = SkRect::MakeWH(SkIntToScalar(dstDesc.fWidth),
                                        SkIntToScalar(dstDesc.fHeight));
-    GrDrawContext* drawContext = ctx->drawContext();
-    drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(), rect);
+    ctx->drawContext()->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(),
+                                 rect);
     ctx->flushSurfaceWrites(dst);
     return SkNEW_ARGS(SkImage_Gpu, (dstDesc.fWidth, dstDesc.fHeight, kOpaque_SkAlphaType, dst, 0,
                                     budgeted));