Make GrDrawContext be GrRenderTargetProxy-backed

This is split out of https://codereview.chromium.org/2215323003/ (Start using RenderTargetProxy (omnibus))

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3841

CQ_INCLUDE_TRYBOTS=master.client.skia.android:Test-Android-Clang-Nexus5-GPU-Adreno330-arm-Debug-GN_Android-Trybot

Change-Id: I1a47f19ed1ac0c249e6ccac8db74095d7f456db4
Reviewed-on: https://skia-review.googlesource.com/3841
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 4c66ac0..30003cd 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -195,6 +195,16 @@
                                                  const SkSurfaceProps* surfaceProps = nullptr,
                                                  SkBudgeted = SkBudgeted::kYes);
 
+    // Create a new draw context as above but have it backed by a deferred-style 
+    // GrRenderTargetProxy rather than one that is backed by an actual GrRenderTarget
+    sk_sp<GrRenderTargetContext> makeDeferredRenderTargetContext(SkBackingFit fit, 
+                                                 int width, int height,
+                                                 GrPixelConfig config,
+                                                 sk_sp<SkColorSpace> colorSpace,
+                                                 int sampleCnt = 0,
+                                                 GrSurfaceOrigin origin = kDefault_GrSurfaceOrigin,
+                                                 const SkSurfaceProps* surfaceProps = nullptr,
+                                                 SkBudgeted = SkBudgeted::kYes);
     /*
      * This method will attempt to create a renderTargetContext that has, at least, the number of
      * channels and precision per channel as requested in 'config' (e.g., A8 and 888 can be
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index 445846f..dcbe8ea 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -143,6 +143,7 @@
     virtual bool completeStencilAttachment() = 0;
 
     friend class GrRenderTargetPriv;
+    friend class GrRenderTargetProxy; // for Flags
 
     GrStencilAttachment*  fStencilAttachment;
     uint8_t               fMultisampleSpecsID;
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index d1dc0c4..f728ef1 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -16,6 +16,7 @@
 #include "SkRegion.h"
 #include "SkSurfaceProps.h"
 #include "../private/GrInstancedPipelineInfo.h"
+#include "../private/GrRenderTargetProxy.h"
 #include "../private/GrSingleOwner.h"
 
 class GrAuditTrail;
@@ -314,21 +315,21 @@
                      int x, int y);
 
     bool isStencilBufferMultisampled() const {
-        return fRenderTarget->isStencilBufferMultisampled();
+        return fRenderTargetProxy->isStencilBufferMultisampled();
     }
-    bool isUnifiedMultisampled() const { return fRenderTarget->isUnifiedMultisampled(); }
-    bool hasMixedSamples() const { return fRenderTarget->isMixedSampled(); }
+    bool isUnifiedMultisampled() const { return fRenderTargetProxy->isUnifiedMultisampled(); }
+    bool hasMixedSamples() const { return fRenderTargetProxy->isMixedSampled(); }
 
     bool mustUseHWAA(const GrPaint& paint) const {
-        return paint.isAntiAlias() && fRenderTarget->isUnifiedMultisampled();
+        return paint.isAntiAlias() && fRenderTargetProxy->isUnifiedMultisampled();
     }
 
     const GrCaps* caps() const { return fContext->caps(); }
-    const GrSurfaceDesc& desc() const { return fRenderTarget->desc(); }
-    int width() const { return fRenderTarget->width(); }
-    int height() const { return fRenderTarget->height(); }
-    GrPixelConfig config() const { return fRenderTarget->config(); }
-    int numColorSamples() const { return fRenderTarget->numColorSamples(); }
+    const GrSurfaceDesc& desc() const { return fRenderTargetProxy->desc(); }
+    int width() const { return fRenderTargetProxy->width(); }
+    int height() const { return fRenderTargetProxy->height(); }
+    GrPixelConfig config() const { return fRenderTargetProxy->config(); }
+    int numColorSamples() const { return fRenderTargetProxy->numColorSamples(); }
     bool isGammaCorrect() const { return SkToBool(fColorSpace.get()); }
     SkSourceGammaTreatment sourceGammaTreatment() const {
         return this->isGammaCorrect() ? SkSourceGammaTreatment::kRespect
@@ -337,13 +338,23 @@
     const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
     SkColorSpace* getColorSpace() const { return fColorSpace.get(); }
     GrColorSpaceXform* getColorXformFromSRGB() const { return fColorXformFromSRGB.get(); }
-    GrSurfaceOrigin origin() const { return fRenderTarget->origin(); }
+    GrSurfaceOrigin origin() const { return fRenderTargetProxy->origin(); }
 
     bool wasAbandoned() const;
 
-    GrRenderTarget* accessRenderTarget() { return fRenderTarget.get(); }
+    GrRenderTarget* accessRenderTarget() {
+        // TODO: usage of this entry point needs to be reduced and potentially eliminated
+        // since it ends the deferral of the GrRenderTarget's allocation
+        return fRenderTargetProxy->instantiate(fContext->textureProvider());
+    }
 
-    sk_sp<GrTexture> asTexture() { return sk_ref_sp(fRenderTarget->asTexture()); }
+    sk_sp<GrTexture> asTexture() {
+        // TODO: usage of this entry point needs to be reduced and potentially eliminated
+        // since it ends the deferral of the GrRenderTarget's allocation
+        // It's usage should migrate to the soon-to-be-added asDeferredTexture which
+        // returns a GrTextureProxy
+        return sk_ref_sp(this->accessRenderTarget()->asTexture());
+    }
 
     // Provides access to functions that aren't part of the public API.
     GrRenderTargetContextPriv priv();
@@ -352,8 +363,9 @@
     GrAuditTrail* auditTrail() { return fAuditTrail; }
 
 protected:
-    GrRenderTargetContext(GrContext*, GrDrawingManager*, sk_sp<GrRenderTarget>, sk_sp<SkColorSpace>,
-                          const SkSurfaceProps* surfaceProps, GrAuditTrail*, GrSingleOwner*);
+    GrRenderTargetContext(GrContext*, GrDrawingManager*, sk_sp<GrRenderTargetProxy>,
+                          sk_sp<SkColorSpace>, const SkSurfaceProps* surfaceProps, GrAuditTrail*,
+                          GrSingleOwner*);
 
     GrDrawingManager* drawingManager() { return fDrawingManager; }
 
@@ -418,7 +430,7 @@
     GrRenderTargetOpList* getOpList();
 
     GrDrawingManager*                 fDrawingManager;
-    sk_sp<GrRenderTarget>             fRenderTarget;
+    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'.
diff --git a/include/private/GrInstancedPipelineInfo.h b/include/private/GrInstancedPipelineInfo.h
index 7e6482d..6f9c779 100644
--- a/include/private/GrInstancedPipelineInfo.h
+++ b/include/private/GrInstancedPipelineInfo.h
@@ -8,20 +8,20 @@
 #ifndef GrGrInstancedPipelineInfo_DEFINED
 #define GrGrInstancedPipelineInfo_DEFINED
 
-#include "GrRenderTarget.h"
+#include "GrRenderTargetProxy.h"
 
 /**
  * Provides info about the pipeline that GrInstancedRendering needs in order to select appropriate
  * drawing algorithms.
  */
 struct GrInstancedPipelineInfo {
-    GrInstancedPipelineInfo(const GrRenderTarget* rt)
-        : fIsMultisampled(rt->isStencilBufferMultisampled()),
-          fIsMixedSampled(rt->isMixedSampled()),
-          fIsRenderingToFloat(GrPixelConfigIsFloatingPoint(rt->desc().fConfig)),
-          fColorDisabled(false),
-          fDrawingShapeToStencil(false),
-          fCanDiscard(false) {
+    GrInstancedPipelineInfo(const GrRenderTargetProxy* rtp)
+        : fIsMultisampled(rtp->isStencilBufferMultisampled())
+        , fIsMixedSampled(rtp->isMixedSampled())
+        , fIsRenderingToFloat(GrPixelConfigIsFloatingPoint(rtp->desc().fConfig))
+        , fColorDisabled(false)
+        , fDrawingShapeToStencil(false)
+        , fCanDiscard(false) {
     }
 
     bool canUseCoverageAA() const {
diff --git a/include/private/GrRenderTargetProxy.h b/include/private/GrRenderTargetProxy.h
index 59fed59..7d36bf6 100644
--- a/include/private/GrRenderTargetProxy.h
+++ b/include/private/GrRenderTargetProxy.h
@@ -9,7 +9,6 @@
 #define GrRenderTargetProxy_DEFINED
 
 #include "GrRenderTarget.h"
-#include "GrRenderTargetPriv.h"
 #include "GrSurfaceProxy.h"
 #include "GrTypes.h"
 
@@ -41,7 +40,7 @@
      * For our purposes, "Mixed Sampled" means the stencil buffer is multisampled but the color
      * buffer is not.
      */
-    bool isMixedSampled() const { return fFlags & GrRenderTargetPriv::Flags::kMixedSampled; }
+    bool isMixedSampled() const { return fFlags & GrRenderTarget::Flags::kMixedSampled; }
 
     /**
      * "Unified Sampled" means the stencil and color buffers are both multisampled.
@@ -58,7 +57,13 @@
      */
     int numColorSamples() const { return this->isMixedSampled() ? 0 : fDesc.fSampleCnt; }
 
-    GrRenderTargetPriv::Flags testingOnly_getFlags() const;
+    GrRenderTarget::Flags testingOnly_getFlags() const;
+
+    GrRenderTargetOpList* getLastRenderTargetOpList() {
+        return (GrRenderTargetOpList*) this->getLastOpList();
+    }
+
+    SkDEBUGCODE(void validate(GrContext*) const;)
 
 private:
     // Deferred version
@@ -67,16 +72,16 @@
     // Wrapped version
     GrRenderTargetProxy(const GrCaps&, sk_sp<GrRenderTarget> rt);
 
-    // For wrapped render targets we store it here.
-    // For deferred proxies we will fill this in when we need to instantiate the deferred resource
-    sk_sp<GrRenderTarget>       fTarget;
+    // For wrapped render targets the actual GrRenderTarget is stored in the GrIORefProxy class.
+    // For deferred proxies that pointer is filled in when we need to instantiate the
+    // deferred resource.
 
     // These don't usually get computed until the render target is instantiated, but the render
     // target proxy may need to answer queries about it before then. And since in the deferred case
     // we know the newly created render target will be internal, we are able to precompute what the
     // flags will ultimately end up being. In the wrapped case we just copy the wrapped
     // rendertarget's info here.
-    GrRenderTargetPriv::Flags   fFlags;
+    GrRenderTarget::Flags   fFlags;
 
     typedef GrSurfaceProxy INHERITED;
 };
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 79d3450..d57c2f5 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -9,13 +9,70 @@
 #define GrSurfaceProxy_DEFINED
 
 #include "GrGpuResource.h"
+#include "GrSurface.h"
 #include "SkRect.h"
 
 class GrOpList;
 class GrTextureProxy;
 class GrRenderTargetProxy;
 
-class GrSurfaceProxy : public GrIORef<GrSurfaceProxy> {
+// This class replicates the functionality GrIORef<GrSurface> but tracks the
+// utilitization for later resource allocation (for the deferred case) and
+// forwards on the utilization in the wrapped case
+class GrIORefProxy : public SkNoncopyable {
+public:
+    void ref() const {
+        this->validate();
+
+        ++fRefCnt;
+        if (fTarget) {
+            fTarget->ref();
+        }
+    }
+
+    void unref() const {
+        this->validate();
+
+        if (fTarget) {
+            fTarget->unref();
+        }
+
+        if (!(--fRefCnt)) {
+            delete this;
+            return;
+        }
+
+        this->validate();
+    }
+
+    void validate() const {
+#ifdef SK_DEBUG    
+        SkASSERT(fRefCnt >= 0);
+#endif
+    }
+
+protected:
+    GrIORefProxy() : fRefCnt(1), fTarget(nullptr) {}
+    GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1) {
+        // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing
+        // anything extra.
+        fTarget = surface.release();
+    }
+    virtual ~GrIORefProxy() {
+        // We don't unref 'fTarget' here since the 'unref' method will already
+        // have forwarded on the unref call that got use here.
+    }
+
+    // TODO: add the IO ref counts. Although if we can delay shader creation to flush time
+    // we may not even need to do that.
+    mutable int32_t fRefCnt;
+
+    // For deferred proxies this will be null. For wrapped proxies it will point to the
+    // wrapped resource.
+    GrSurface* fTarget;
+};
+
+class GrSurfaceProxy : public GrIORefProxy {
 public:
     const GrSurfaceDesc& desc() const { return fDesc; }
 
@@ -25,7 +82,7 @@
         return fDesc.fOrigin;
     }
     int width() const { return fDesc.fWidth; }
-    int height() const { return fDesc.fWidth; }
+    int height() const { return fDesc.fHeight; }
     GrPixelConfig config() const { return fDesc.fConfig; }
 
     uint32_t uniqueID() const { return fUniqueID; }
@@ -66,18 +123,10 @@
     }
 
     // Wrapped version
-    GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, 
-                   SkBudgeted budgeted, uint32_t uniqueID)
-        : fDesc(desc)
-        , fFit(fit)
-        , fBudgeted(budgeted)
-        , fUniqueID(uniqueID)
-        , fLastOpList(nullptr) {
-    }
+    GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit);
 
     virtual ~GrSurfaceProxy();
 
-
     // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
     const GrSurfaceDesc fDesc;
     const SkBackingFit  fFit;      // always exact for wrapped resources
@@ -85,11 +134,6 @@
     const uint32_t      fUniqueID; // set from the backing resource for wrapped resources
 
 private:
-
-    // See comment in GrGpuResource.h.
-    void notifyAllCntsAreZero(CntType) const { delete this; }
-    bool notifyRefCountIsZero() const { return true; }
-
     // The last opList that wrote to or is currently going to write to this surface
     // The opList can be closed (e.g., no render target context is currently bound
     // to this renderTarget).
@@ -98,10 +142,7 @@
     // and the opList of a destination surface to which this one is being drawn or copied.
     GrOpList* fLastOpList;
 
-    typedef GrIORef<GrSurfaceProxy> INHERITED;
-
-    // to access notifyAllCntsAreZero and notifyRefCntIsZero.
-    friend class GrIORef<GrSurfaceProxy>;
+    typedef GrIORefProxy INHERITED;
 };
 
 #endif
diff --git a/include/private/GrTextureProxy.h b/include/private/GrTextureProxy.h
index 63cb3c8..5b4eeef 100644
--- a/include/private/GrTextureProxy.h
+++ b/include/private/GrTextureProxy.h
@@ -36,9 +36,9 @@
     // Wrapped version
     GrTextureProxy(sk_sp<GrTexture> tex);
 
-    // For wrapped textures we store it here.
-    // For deferred proxies we will fill this in when we need to instantiate the deferred resource
-    sk_sp<GrTexture> fTexture;
+    // For wrapped proxies the GrTexture pointer is stored in GrIORefProxy.
+    // For deferred proxies that pointer will be filled n when we need to instantiate
+    // the deferred resource
 
     typedef GrSurfaceProxy INHERITED;
 };