Dynamically allocate the GrDrawContexts

This CL moves the allocation and storage of the GrTextContexts into the DrawingManager. The GrDrawContexts now just get their GrTextContext from the DrawingManager.

Review URL: https://codereview.chromium.org/1375153007
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 065d61b..b1959bb 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -28,6 +28,7 @@
 #include "GrResourceCache.h"
 #include "GrResourceProvider.h"
 #include "GrSoftwarePathRenderer.h"
+#include "GrStencilAndCoverTextContext.h"
 #include "GrStrokeInfo.h"
 #include "GrSurfacePriv.h"
 #include "GrTextBlobCache.h"
@@ -44,6 +45,7 @@
 #include "SkTLS.h"
 #include "SkTraceEvent.h"
 
+
 #include "batches/GrBatch.h"
 
 #include "effects/GrConfigConversionEffect.h"
@@ -65,9 +67,13 @@
 
 void GrContext::DrawingMgr::cleanup() {
     SkSafeSetNull(fDrawTarget);
+    delete fNVPRTextContext;
+    fNVPRTextContext = nullptr;
     for (int i = 0; i < kNumPixelGeometries; ++i) {
-        SkSafeSetNull(fDrawContext[i][0]);
-        SkSafeSetNull(fDrawContext[i][1]);
+        delete fTextContexts[i][0];
+        fTextContexts[i][0] = nullptr;
+        delete fTextContexts[i][1];
+        fTextContexts[i][1] = nullptr;
     }
 }
 
@@ -76,15 +82,7 @@
 }
 
 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]);
-            }
-        }
-    }
+    this->cleanup();
 }
 
 void GrContext::DrawingMgr::reset() {
@@ -99,21 +97,40 @@
     }
 }
 
+GrTextContext* GrContext::DrawingMgr::textContext(const SkSurfaceProps& props,
+                                                  GrRenderTarget* rt) {
+    if (this->abandoned()) {
+        return nullptr;
+    }
+
+    SkASSERT(props.pixelGeometry() < kNumPixelGeometries);
+    bool useDIF = props.isUseDeviceIndependentFonts();
+
+    if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
+        rt->isStencilBufferMultisampled()) {
+        GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt);
+        if (sb) {
+            if (!fNVPRTextContext) {
+                fNVPRTextContext = GrStencilAndCoverTextContext::Create(fContext, props);
+            }
+
+            return fNVPRTextContext;
+        }
+    }
+
+    if (!fTextContexts[props.pixelGeometry()][useDIF]) {
+        fTextContexts[props.pixelGeometry()][useDIF] = GrAtlasTextContext::Create(fContext, props);
+    }
+
+    return fTextContexts[props.pixelGeometry()][useDIF];
+}
+
 GrDrawContext* GrContext::DrawingMgr::drawContext(const SkSurfaceProps* surfaceProps) {
     if (this->abandoned()) {
         return nullptr;
     }
 
-    const SkSurfaceProps props(SkSurfacePropsCopyOrDefault(surfaceProps));
-
-    SkASSERT(props.pixelGeometry() < kNumPixelGeometries);
-    if (!fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]) {
-        fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()] =
-                new GrDrawContext(fContext, fDrawTarget, props);
-    }
-
-    // For now, everyone gets a faux creation ref
-    return SkRef(fDrawContext[props.pixelGeometry()][props.isUseDeviceIndependentFonts()]);
+    return new GrDrawContext(fContext, fDrawTarget, surfaceProps);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 0a63eb8..7e1e66f 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -16,6 +16,7 @@
 #include "GrRenderTargetPriv.h"
 #include "GrResourceProvider.h"
 #include "GrStencilAndCoverTextContext.h"
+#include "SkSurfacePriv.h"
 
 #include "batches/GrBatch.h"
 #include "batches/GrDrawAtlasBatch.h"
@@ -23,9 +24,9 @@
 #include "batches/GrRectBatchFactory.h"
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
-#define RETURN_IF_ABANDONED        if (!fDrawTarget) { return; }
-#define RETURN_FALSE_IF_ABANDONED  if (!fDrawTarget) { return false; }
-#define RETURN_NULL_IF_ABANDONED   if (!fDrawTarget) { return nullptr; }
+#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }
+#define RETURN_FALSE_IF_ABANDONED  if (fContext->abandoned()) { return false; }
+#define RETURN_NULL_IF_ABANDONED   if (fContext->abandoned()) { return nullptr; }
 
 class AutoCheckFlush {
 public:
@@ -38,20 +39,21 @@
 
 GrDrawContext::GrDrawContext(GrContext* context,
                              GrDrawTarget* drawTarget,
-                             const SkSurfaceProps& surfaceProps)
+                             const SkSurfaceProps* surfaceProps)
     : fContext(context)
     , fDrawTarget(SkRef(drawTarget))
     , fTextContext(nullptr)
-    , fSurfaceProps(surfaceProps) {
+    , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
 }
 
 GrDrawContext::~GrDrawContext() {
     SkSafeUnref(fDrawTarget);
-    delete fTextContext;
 }
 
 void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src,
                                 const SkIRect& srcRect, const SkIPoint& dstPoint) {
+    RETURN_IF_ABANDONED
+
     if (!this->prepareToDraw(dst)) {
         return;
     }
@@ -59,28 +61,16 @@
     fDrawTarget->copySurface(dst, src, srcRect, dstPoint);
 }
 
-GrTextContext* GrDrawContext::createTextContext(GrRenderTarget* renderTarget,
-                                                const SkSurfaceProps& surfaceProps) {
-    if (fContext->caps()->shaderCaps()->pathRenderingSupport() &&
-        renderTarget->isStencilBufferMultisampled() &&
-        fSurfaceProps.isUseDeviceIndependentFonts()) {
-        GrStencilAttachment* sb =
-            fContext->resourceProvider()->attachStencilAttachment(renderTarget);
-        if (sb) {
-            return GrStencilAndCoverTextContext::Create(fContext, surfaceProps);
-        }
-    } 
-
-    return GrAtlasTextContext::Create(fContext, surfaceProps);
-}
 
 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) {
+    RETURN_IF_ABANDONED
+
     if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, fSurfaceProps);
+        fTextContext = fContext->textContext(fSurfaceProps, rt);
     }
 
     fTextContext->drawText(this, rt, clip, grPaint, skPaint, viewMatrix,
@@ -93,8 +83,10 @@
                                 const char text[], size_t byteLength,
                                 const SkScalar pos[], int scalarsPerPosition,
                                 const SkPoint& offset, const SkIRect& clipBounds) {
+    RETURN_IF_ABANDONED
+
     if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, fSurfaceProps);
+        fTextContext = fContext->textContext(fSurfaceProps, rt);
     }
 
     fTextContext->drawPosText(this, rt, clip, grPaint, skPaint, viewMatrix, text, byteLength,
@@ -105,8 +97,10 @@
                                  const SkMatrix& viewMatrix, const SkTextBlob* blob,
                                  SkScalar x, SkScalar y,
                                  SkDrawFilter* filter, const SkIRect& clipBounds) {
+    RETURN_IF_ABANDONED
+
     if (!fTextContext) {
-        fTextContext = this->createTextContext(rt, fSurfaceProps);
+        fTextContext = fContext->textContext(fSurfaceProps, rt);
     }
 
     fTextContext->drawTextBlob(this, rt,
@@ -119,6 +113,8 @@
                                        GrColor color,
                                        GrPathRangeDraw* draw,
                                        int /*GrPathRendering::FillType*/ fill) {
+    RETURN_IF_ABANDONED
+
     fDrawTarget->drawPathsFromRange(*pipelineBuilder, viewMatrix, localMatrix, color, draw,
                                     (GrPathRendering::FillType) fill);
 }
@@ -761,5 +757,7 @@
 }
 
 void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
+    RETURN_IF_ABANDONED
+
     fDrawTarget->drawBatch(*pipelineBuilder, batch);
 }
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 1041b88..a2e245d 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -27,7 +27,9 @@
     , fSurfaceProps(surfaceProps) {
 }
 
-GrTextContext::~GrTextContext() { delete fFallbackTextContext; }
+GrTextContext::~GrTextContext() {
+    delete fFallbackTextContext;
+}
 
 void GrTextContext::drawText(GrDrawContext* dc, GrRenderTarget* rt,
                              const GrClip& clip, const GrPaint& paint,