Additional DDL playback cleanup

This operates in tandem with https://skia-review.googlesource.com/c/skia/+/112702 (
Remove GrRestrictedAtlasManager) to get DDL playback working.

Change-Id: I6c2178fde760677bf79f2cf0a2dee8b5990aa5bc
Reviewed-on: https://skia-review.googlesource.com/113121
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/core/SkDeferredDisplayListRecorder.cpp b/src/core/SkDeferredDisplayListRecorder.cpp
index acd7b67..0775480 100644
--- a/src/core/SkDeferredDisplayListRecorder.cpp
+++ b/src/core/SkDeferredDisplayListRecorder.cpp
@@ -71,7 +71,6 @@
 
     GrSurfaceDesc desc;
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
-    desc.fOrigin = fCharacterization.origin();
     desc.fWidth = fCharacterization.width();
     desc.fHeight = fCharacterization.height();
     desc.fConfig = fCharacterization.config();
@@ -95,6 +94,7 @@
                 return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->priv().peekSurface());
             },
             desc,
+            fCharacterization.origin(),
             GrRenderTargetFlags::kNone,
             GrProxyProvider::Textureable(fCharacterization.isTextureable()),
             GrMipMapped::kNo,
diff --git a/src/core/SkMask.h b/src/core/SkMask.h
index d4c5e35..1acd8f9 100644
--- a/src/core/SkMask.h
+++ b/src/core/SkMask.h
@@ -146,6 +146,12 @@
         SkMask::FreeImage(fImage);
     }
 
+    uint8_t* release() {
+        uint8_t* tmp = fImage;
+        fImage = nullptr;
+        return tmp;
+    }
+
 private:
     uint8_t* fImage;
 };
diff --git a/src/effects/GrCircleBlurFragmentProcessor.cpp b/src/effects/GrCircleBlurFragmentProcessor.cpp
index b345f27..d44f431 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/effects/GrCircleBlurFragmentProcessor.cpp
@@ -107,9 +107,9 @@
 // the size of the profile being computed. Then for each of the n profile entries we walk out k
 // steps in each horizontal direction multiplying the corresponding y evaluation by the half
 // kernel entry and sum these values to compute the profile entry.
-static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) {
+static void create_circle_profile(uint8_t* weights, float sigma, float circleR,
+                                  int profileTextureWidth) {
     const int numSteps = profileTextureWidth;
-    uint8_t* weights = new uint8_t[numSteps];
 
     // The full kernel is 6 sigmas wide.
     int halfKernelSize = SkScalarCeilToInt(6.0f * sigma);
@@ -134,17 +134,15 @@
     }
     // Ensure the tail of the Gaussian goes to zero.
     weights[numSteps - 1] = 0;
-    return weights;
 }
 
-static uint8_t* create_half_plane_profile(int profileWidth) {
+static void create_half_plane_profile(uint8_t* profile, int profileWidth) {
     SkASSERT(!(profileWidth & 0x1));
     // The full kernel is 6 sigmas wide.
     float sigma = profileWidth / 6.f;
     int halfKernelSize = profileWidth / 2;
 
     SkAutoTArray<float> halfKernel(halfKernelSize);
-    uint8_t* profile = new uint8_t[profileWidth];
 
     // The half kernel should sum to 0.5.
     const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, sigma);
@@ -163,7 +161,6 @@
     }
     // Ensure tail goes to 0.
     profile[profileWidth - 1] = 0;
-    return profile;
 }
 
 static sk_sp<GrTextureProxy> create_profile_texture(GrProxyProvider* proxyProvider,
@@ -211,23 +208,26 @@
             proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
     if (!blurProfile) {
         static constexpr int kProfileTextureWidth = 512;
-        GrSurfaceDesc texDesc;
-        texDesc.fWidth = kProfileTextureWidth;
-        texDesc.fHeight = 1;
-        texDesc.fConfig = kAlpha_8_GrPixelConfig;
 
-        std::unique_ptr<uint8_t[]> profile(nullptr);
+        SkBitmap bm;
+        if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) {
+            return nullptr;
+        }
+
         if (useHalfPlaneApprox) {
-            profile.reset(create_half_plane_profile(kProfileTextureWidth));
+            create_half_plane_profile(bm.getAddr8(0, 0), kProfileTextureWidth);
         } else {
             // Rescale params to the size of the texture we're creating.
             SkScalar scale = kProfileTextureWidth / *textureRadius;
-            profile.reset(
-                    create_circle_profile(sigma * scale, circleR * scale, kProfileTextureWidth));
+            create_circle_profile(bm.getAddr8(0, 0), sigma * scale, circleR * scale,
+                                  kProfileTextureWidth);
         }
 
-        blurProfile =
-                proxyProvider->createTextureProxy(texDesc, SkBudgeted::kYes, profile.get(), 0);
+        bm.setImmutable();
+        sk_sp<SkImage> image = SkImage::MakeFromBitmap(bm);
+
+        blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, 1,
+                                                        SkBudgeted::kYes, SkBackingFit::kExact);
         if (!blurProfile) {
             return nullptr;
         }
diff --git a/src/effects/GrCircleBlurFragmentProcessor.fp b/src/effects/GrCircleBlurFragmentProcessor.fp
index ef4c289..71e5937 100644
--- a/src/effects/GrCircleBlurFragmentProcessor.fp
+++ b/src/effects/GrCircleBlurFragmentProcessor.fp
@@ -127,12 +127,12 @@
     // the size of the profile being computed. Then for each of the n profile entries we walk out k
     // steps in each horizontal direction multiplying the corresponding y evaluation by the half
     // kernel entry and sum these values to compute the profile entry.
-    static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) {
+    static void create_circle_profile(uint8_t* weights, float sigma, float circleR,
+                                      int profileTextureWidth) {
         const int numSteps = profileTextureWidth;
-        uint8_t* weights = new uint8_t[numSteps];
 
         // The full kernel is 6 sigmas wide.
-        int halfKernelSize = SkScalarCeilToInt(6.0f*sigma);
+        int halfKernelSize = SkScalarCeilToInt(6.0f * sigma);
         // round up to next multiple of 2 and then divide by 2
         halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1;
 
@@ -154,17 +154,15 @@
         }
         // Ensure the tail of the Gaussian goes to zero.
         weights[numSteps - 1] = 0;
-        return weights;
     }
 
-    static uint8_t* create_half_plane_profile(int profileWidth) {
+    static void create_half_plane_profile(uint8_t* profile, int profileWidth) {
         SkASSERT(!(profileWidth & 0x1));
         // The full kernel is 6 sigmas wide.
         float sigma = profileWidth / 6.f;
         int halfKernelSize = profileWidth / 2;
 
         SkAutoTArray<float> halfKernel(halfKernelSize);
-        uint8_t* profile = new uint8_t[profileWidth];
 
         // The half kernel should sum to 0.5.
         const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize,
@@ -184,7 +182,6 @@
         }
         // Ensure tail goes to 0.
         profile[profileWidth - 1] = 0;
-        return profile;
     }
 
     static sk_sp<GrTextureProxy> create_profile_texture(GrProxyProvider* proxyProvider,
@@ -233,23 +230,26 @@
                       proxyProvider->findOrCreateProxyByUniqueKey(key, kTopLeft_GrSurfaceOrigin);
         if (!blurProfile) {
             static constexpr int kProfileTextureWidth = 512;
-            GrSurfaceDesc texDesc;
-            texDesc.fWidth = kProfileTextureWidth;
-            texDesc.fHeight = 1;
-            texDesc.fConfig = kAlpha_8_GrPixelConfig;
 
-            std::unique_ptr<uint8_t[]> profile(nullptr);
+            SkBitmap bm;
+            if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) {
+                return nullptr;
+            }
+
             if (useHalfPlaneApprox) {
-                profile.reset(create_half_plane_profile(kProfileTextureWidth));
+                create_half_plane_profile(bm.getAddr8(0, 0), kProfileTextureWidth);
             } else {
                 // Rescale params to the size of the texture we're creating.
                 SkScalar scale = kProfileTextureWidth / *textureRadius;
-                profile.reset(create_circle_profile(sigma * scale, circleR * scale,
-                                                    kProfileTextureWidth));
+                create_circle_profile(bm.getAddr8(0, 0), sigma * scale, circleR * scale,
+                                      kProfileTextureWidth);
             }
 
-            blurProfile = proxyProvider->createTextureProxy(
-                    texDesc, SkBudgeted::kYes, profile.get(), 0);
+            bm.setImmutable();
+            sk_sp<SkImage> image = SkImage::MakeFromBitmap(bm);
+
+            blurProfile = proxyProvider->createTextureProxy(std::move(image), kNone_GrSurfaceFlags, 1,
+                                                            SkBudgeted::kYes, SkBackingFit::kExact);
             if (!blurProfile) {
                 return nullptr;
             }
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 0bddd5c..146f297 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -6,15 +6,18 @@
  */
 
 #include "GrBlurUtils.h"
-#include "GrRenderTargetContext.h"
+
 #include "GrCaps.h"
 #include "GrContext.h"
 #include "GrContextPriv.h"
 #include "GrFixedClip.h"
+#include "GrProxyProvider.h"
+#include "GrRenderTargetContext.h"
 #include "GrRenderTargetContextPriv.h"
-#include "effects/GrSimpleTextureEffect.h"
 #include "GrStyle.h"
 #include "GrTextureProxy.h"
+#include "effects/GrSimpleTextureEffect.h"
+
 #include "SkDraw.h"
 #include "SkGr.h"
 #include "SkMaskFilterBase.h"
@@ -49,6 +52,10 @@
     return true;
 }
 
+static void mask_release_proc(void* addr, void* /*context*/) {
+    SkMask::FreeImage(addr);
+}
+
 static bool sw_draw_with_mask_filter(GrContext* context,
                                      GrRenderTargetContext* renderTargetContext,
                                      const GrClip& clipData,
@@ -58,7 +65,7 @@
                                      const SkIRect& clipBounds,
                                      GrPaint&& paint,
                                      SkStrokeRec::InitStyle fillOrHairline) {
-    SkMask  srcM, dstM;
+    SkMask srcM, dstM;
     if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
                             SkMask::kComputeBoundsAndRenderImage_CreateMode, fillOrHairline)) {
         return false;
@@ -77,25 +84,23 @@
 
     // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
     // the current clip (and identity matrix) and GrPaint settings
-    GrSurfaceDesc desc;
-    desc.fWidth = dstM.fBounds.width();
-    desc.fHeight = dstM.fBounds.height();
-    desc.fConfig = kAlpha_8_GrPixelConfig;
-
-    sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeDeferredSurfaceContext(
-            desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kApprox,
-            SkBudgeted::kYes);
-    if (!sContext) {
+    SkBitmap bm;
+    if (!bm.installPixels(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
+                          autoDst.release(), dstM.fRowBytes, mask_release_proc, nullptr)) {
         return false;
     }
+    bm.setImmutable();
 
-    SkImageInfo ii = SkImageInfo::MakeA8(desc.fWidth, desc.fHeight);
-    if (!sContext->writePixels(ii, dstM.fImage, dstM.fRowBytes, 0, 0)) {
-        return false;
-    }
+    sk_sp<SkImage> image = SkImage::MakeFromBitmap(bm);
+
+    auto proxyProvider = context->contextPriv().proxyProvider();
+    sk_sp<GrTextureProxy> maskProxy = proxyProvider->createTextureProxy(std::move(image),
+                                                                        kNone_GrSurfaceFlags,
+                                                                        1, SkBudgeted::kYes,
+                                                                        SkBackingFit::kApprox);
 
     return draw_mask(renderTargetContext, clipData, viewMatrix,
-                     dstM.fBounds, std::move(paint), sContext->asTextureProxyRef());
+                     dstM.fBounds, std::move(paint), std::move(maskProxy));
 }
 
 // Create a mask of 'devPath' and place the result in 'mask'.
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 9a9c2d5..fe42a93 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -44,12 +44,12 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrGpu::isACopyNeededForTextureParams(int width, int height,
+bool GrGpu::IsACopyNeededForTextureParams(const GrCaps* caps,
+                                          int width, int height,
                                           const GrSamplerState& textureParams,
                                           GrTextureProducer::CopyParams* copyParams,
-                                          SkScalar scaleAdjust[2]) const {
-    const GrCaps& caps = *this->caps();
-    if (textureParams.isRepeated() && !caps.npotTextureTileSupport() &&
+                                          SkScalar scaleAdjust[2]) {
+    if (textureParams.isRepeated() && !caps->npotTextureTileSupport() &&
         (!SkIsPow2(width) || !SkIsPow2(height))) {
         SkASSERT(scaleAdjust);
         copyParams->fWidth = GrNextPow2(width);
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 786fb31..b06b0d7 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -480,9 +480,9 @@
     // Determines whether a texture will need to be rescaled in order to be used with the
     // GrSamplerState. This variation is called when the caller will create a new texture using the
     // resource provider from a non-texture src (cpu-backed image, ...).
-    bool isACopyNeededForTextureParams(int width, int height, const GrSamplerState&,
-                                       GrTextureProducer::CopyParams*,
-                                       SkScalar scaleAdjust[2]) const;
+    static bool IsACopyNeededForTextureParams(const GrCaps*, int width, int height,
+                                              const GrSamplerState&, GrTextureProducer::CopyParams*,
+                                              SkScalar scaleAdjust[2]);
 
     // Like the above but this variation should be called when the caller is not creating the
     // original texture but rather was handed the original texture. It adds additional checks
@@ -491,8 +491,8 @@
     bool isACopyNeededForTextureParams(GrTextureProxy* proxy, const GrSamplerState& params,
                                        GrTextureProducer::CopyParams* copyParams,
                                        SkScalar scaleAdjust[2]) const {
-        if (this->isACopyNeededForTextureParams(proxy->width(), proxy->height(), params,
-                                                copyParams, scaleAdjust)) {
+        if (IsACopyNeededForTextureParams(this->caps(), proxy->width(), proxy->height(), params,
+                                          copyParams, scaleAdjust)) {
             return true;
         }
         return this->onIsACopyNeededForTextureParams(proxy, params, copyParams, scaleAdjust);
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index c78e998..76414b5 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -22,6 +22,9 @@
 #include "SkMipMap.h"
 
 #ifdef SK_DEBUG
+#include "GrRenderTarget.h"
+#include "GrRenderTargetPriv.h"
+
 static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
     return desc.fWidth <= 0 &&
            desc.fHeight <= 0 &&
@@ -171,9 +174,17 @@
 void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
     SkASSERT(!fTarget && surface);
     fTarget = surface.release();
+
     this->INHERITED::transferRefs();
 
 #ifdef SK_DEBUG
+    if (this->asRenderTargetProxy()) {
+        SkASSERT(fTarget->asRenderTarget());
+        if (this->asRenderTargetProxy()->needsStencil()) {
+           SkASSERT(fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment());
+        }
+    }
+
     if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
         SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
     }
@@ -393,6 +404,12 @@
     fProxy->fWidth = surface->width();
     fProxy->fHeight = surface->height();
 
+    bool needsStencil = fProxy->asRenderTargetProxy()
+                                        ? fProxy->asRenderTargetProxy()->needsStencil()
+                                        : false;
+
+    GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(), needsStencil);
+
     SkASSERT(surface->config() == fProxy->fConfig);
     SkDEBUGCODE(fProxy->validateLazySurface(surface.get());)
     this->assign(std::move(surface));
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index 5043675..720f357 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -28,16 +28,17 @@
         *texColorSpace = this->getColorSpace(dstColorSpace);
     }
 
-    GrGpu* gpu = fContext->contextPriv().getGpu();
     sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
                                                                  AllowedTexGenType::kCheap));
     if (original) {
+        GrGpu* gpu = fContext->contextPriv().getGpu();
+
         if (!gpu->isACopyNeededForTextureParams(original.get(), params, &copyParams, scaleAdjust)) {
             return original;
         }
     } else {
-        if (!gpu->isACopyNeededForTextureParams(this->width(), this->height(),
-                                                params, &copyParams, scaleAdjust)) {
+        if (!GrGpu::IsACopyNeededForTextureParams(fContext->caps(), this->width(), this->height(),
+                                                  params, &copyParams, scaleAdjust)) {
             return this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
                                                  AllowedTexGenType::kAny);
         }
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index 0025af0..59a35bc 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -25,6 +25,7 @@
 
 int32_t GrTextureStripAtlas::gCacheCount = 0;
 
+// DDL TODO: The texture strip atlas can't have this global!
 GrTextureStripAtlas::Hash* GrTextureStripAtlas::gAtlasCache = nullptr;
 
 GrTextureStripAtlas::Hash* GrTextureStripAtlas::GetCache() {