/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkDeferredDisplayListRecorder.h"
#include "include/core/SkSurfaceCharacterization.h"
#include "include/private/SkMalloc.h"
#include "include/utils/SkRandom.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkMessageBus.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrThreadSafeCache.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
#include "tools/gpu/ProxyUtils.h"

#include <thread>

static constexpr int kImageWH = 32;
static constexpr auto kImageOrigin = kBottomLeft_GrSurfaceOrigin;
static constexpr int kNoID = -1;

static SkImageInfo default_ii(int wh) {
    return SkImageInfo::Make(wh, wh, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
}

static std::unique_ptr<skgpu::v1::SurfaceDrawContext> new_SDC(GrRecordingContext* rContext,
                                                              int wh) {
    return skgpu::v1::SurfaceDrawContext::Make(rContext,
                                               GrColorType::kRGBA_8888,
                                               nullptr,
                                               SkBackingFit::kExact,
                                               {wh, wh},
                                               SkSurfaceProps(),
                                               1,
                                               GrMipMapped::kNo,
                                               GrProtected::kNo,
                                               kImageOrigin,
                                               SkBudgeted::kYes);
}

static void create_view_key(skgpu::UniqueKey* key, int wh, int id) {
    static const skgpu::UniqueKey::Domain kViewDomain = skgpu::UniqueKey::GenerateDomain();
    skgpu::UniqueKey::Builder builder(key, kViewDomain, 1);
    builder[0] = wh;
    builder.finish();

    if (id != kNoID) {
        key->setCustomData(SkData::MakeWithCopy(&id, sizeof(id)));
    }
}

static void create_vert_key(skgpu::UniqueKey* key, int wh, int id) {
    static const skgpu::UniqueKey::Domain kVertDomain = skgpu::UniqueKey::GenerateDomain();
    skgpu::UniqueKey::Builder builder(key, kVertDomain, 1);
    builder[0] = wh;
    builder.finish();

    if (id != kNoID) {
        key->setCustomData(SkData::MakeWithCopy(&id, sizeof(id)));
    }
}

static bool default_is_newer_better(SkData* incumbent, SkData* challenger) {
    return false;
}

// When testing views we create a bitmap that covers the entire screen and has an inset blue rect
// atop a field of white.
// When testing verts we clear the background to white and simply draw an inset blur rect.
static SkBitmap create_bitmap(int wh) {
    SkBitmap bitmap;

    bitmap.allocPixels(default_ii(wh));

    SkCanvas tmp(bitmap);
    tmp.clear(SK_ColorWHITE);

    SkPaint blue;
    blue.setColor(SK_ColorBLUE);
    blue.setAntiAlias(false);

    tmp.drawRect({10, 10, wh-10.0f, wh-10.0f}, blue);

    bitmap.setImmutable();
    return bitmap;
}

class GrThreadSafeVertexTestOp;

class TestHelper {
public:
    struct Stats {
        int fCacheHits = 0;
        int fCacheMisses = 0;

        int fNumSWCreations = 0;
        int fNumLazyCreations = 0;
        int fNumHWCreations = 0;
    };

    TestHelper(GrDirectContext* dContext,
               GrThreadSafeCache::IsNewerBetter isNewerBetter = default_is_newer_better)
            : fDContext(dContext)
            , fIsNewerBetter(isNewerBetter) {

        fDst = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, default_ii(kImageWH));
        SkAssertResult(fDst);

        SkSurfaceCharacterization characterization;
        SkAssertResult(fDst->characterize(&characterization));

        fRecorder1 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);
        this->ddlCanvas1()->clear(SkColors::kWhite);

        fRecorder2 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);
        this->ddlCanvas2()->clear(SkColors::kWhite);

        fDst->getCanvas()->clear(SkColors::kWhite);
    }

    ~TestHelper() {
        fDContext->flush();
        fDContext->submit(true);
    }

    Stats* stats() { return &fStats; }

    int numCacheEntries() const { return this->threadSafeCache()->numEntries(); }

    GrDirectContext* dContext() { return fDContext; }

    SkCanvas* liveCanvas() { return fDst ? fDst->getCanvas() : nullptr; }
    SkCanvas* ddlCanvas1() { return fRecorder1 ? fRecorder1->getCanvas() : nullptr; }
    sk_sp<SkDeferredDisplayList> snap1() {
        if (fRecorder1) {
            sk_sp<SkDeferredDisplayList> tmp = fRecorder1->detach();
            fRecorder1 = nullptr;
            return tmp;
        }

        return nullptr;
    }
    SkCanvas* ddlCanvas2() { return fRecorder2 ? fRecorder2->getCanvas() : nullptr; }
    sk_sp<SkDeferredDisplayList> snap2() {
        if (fRecorder2) {
            sk_sp<SkDeferredDisplayList> tmp = fRecorder2->detach();
            fRecorder2 = nullptr;
            return tmp;
        }

        return nullptr;
    }

    GrThreadSafeCache* threadSafeCache() { return fDContext->priv().threadSafeCache(); }
    const GrThreadSafeCache* threadSafeCache() const { return fDContext->priv().threadSafeCache(); }

    typedef void (TestHelper::*addAccessFP)(SkCanvas*, int wh, int id,
                                            bool failLookUp, bool failFillingIn);
    typedef bool (TestHelper::*checkFP)(SkCanvas*, int wh,
                                        int expectedHits, int expectedMisses,
                                        int expectedNumRefs, int expectedID);

    // Add a draw on 'canvas' that will introduce a ref on the 'wh' view
    void addViewAccess(SkCanvas* canvas,
                       int wh,
                       int id = kNoID,
                       bool failLookup = false,
                       bool failFillingIn = false) {
        auto rContext = canvas->recordingContext();

        auto view = AccessCachedView(rContext, this->threadSafeCache(),
                                     wh, failLookup, failFillingIn, id, &fStats);
        SkASSERT(view);

        auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);

        sdc->drawTexture(nullptr,
                         view,
                         kPremul_SkAlphaType,
                         GrSamplerState::Filter::kNearest,
                         GrSamplerState::MipmapMode::kNone,
                         SkBlendMode::kSrcOver,
                         {1.0f, 1.0f, 1.0f, 1.0f},
                         SkRect::MakeWH(wh, wh),
                         SkRect::MakeWH(wh, wh),
                         GrAA::kNo,
                         GrQuadAAFlags::kNone,
                         SkCanvas::kFast_SrcRectConstraint,
                         SkMatrix::I(),
                         nullptr);
    }

    // Besides checking that the number of refs and cache hits and misses are as expected, this
    // method also validates that the unique key doesn't appear in any of the other caches.
    bool checkView(SkCanvas* canvas, int wh,
                   int expectedHits, int expectedMisses, int expectedNumRefs, int expectedID) {
        if (fStats.fCacheHits != expectedHits || fStats.fCacheMisses != expectedMisses) {
            SkDebugf("Hits E: %d A: %d --- Misses E: %d A: %d\n",
                     expectedHits, fStats.fCacheHits, expectedMisses, fStats.fCacheMisses);
            return false;
        }

        skgpu::UniqueKey key;
        create_view_key(&key, wh, kNoID);

        auto threadSafeCache = this->threadSafeCache();

        auto [view, xtraData] = threadSafeCache->findWithData(key);
        if (!view.proxy()) {
            return false;
        }

        if (expectedID < 0) {
            if (xtraData) {
                return false;
            }
        } else {
            if (!xtraData) {
                return false;
            }

            const int* cachedID = static_cast<const int*>(xtraData->data());
            if (*cachedID != expectedID) {
                return false;
            }
        }

        if (!view.proxy()->refCntGreaterThan(expectedNumRefs+1) ||  // +1 for 'view's ref
            view.proxy()->refCntGreaterThan(expectedNumRefs+2)) {
            return false;
        }

        if (canvas) {
            GrRecordingContext* rContext = canvas->recordingContext();
            GrProxyProvider* recordingProxyProvider = rContext->priv().proxyProvider();
            sk_sp<GrTextureProxy> result = recordingProxyProvider->findProxyByUniqueKey(key);
            if (result) {
                // views in this cache should never appear in the recorder's cache
                return false;
            }
        }

        {
            GrProxyProvider* directProxyProvider = fDContext->priv().proxyProvider();
            sk_sp<GrTextureProxy> result = directProxyProvider->findProxyByUniqueKey(key);
            if (result) {
                // views in this cache should never appear in the main proxy cache
                return false;
            }
        }

        {
            auto resourceProvider = fDContext->priv().resourceProvider();
            sk_sp<GrSurface> surf = resourceProvider->findByUniqueKey<GrSurface>(key);
            if (surf) {
                // the textures backing the views in this cache should never be discoverable in the
                // resource cache
                return false;
            }
        }

        return true;
    }

    void addVertAccess(SkCanvas* canvas,
                       int wh,
                       int id,
                       bool failLookup,
                       bool failFillingIn,
                       GrThreadSafeVertexTestOp** createdOp);

    // Add a draw on 'canvas' that will introduce a ref on a 'wh' vertex data
    void addVertAccess(SkCanvas* canvas,
                       int wh,
                       int id = kNoID,
                       bool failLookup = false,
                       bool failFillingIn = false) {
        this->addVertAccess(canvas, wh, id, failLookup, failFillingIn, nullptr);
    }

    bool checkVert(SkCanvas* canvas, int wh,
                   int expectedHits, int expectedMisses, int expectedNumRefs, int expectedID) {
        if (fStats.fCacheHits != expectedHits || fStats.fCacheMisses != expectedMisses) {
            SkDebugf("Hits E: %d A: %d --- Misses E: %d A: %d\n",
                     expectedHits, fStats.fCacheHits, expectedMisses, fStats.fCacheMisses);
            return false;
        }

        skgpu::UniqueKey key;
        create_vert_key(&key, wh, kNoID);

        auto threadSafeCache = this->threadSafeCache();

        auto [vertData, xtraData] = threadSafeCache->findVertsWithData(key);
        if (!vertData) {
            return false;
        }

        if (expectedID < 0) {
            if (xtraData) {
                return false;
            }
        } else {
            if (!xtraData) {
                return false;
            }

            const int* cachedID = static_cast<const int*>(xtraData->data());
            if (*cachedID != expectedID) {
                return false;
            }
        }

        if (!vertData->refCntGreaterThan(expectedNumRefs+1) ||  // +1 for 'vertData's ref
            vertData->refCntGreaterThan(expectedNumRefs+2)) {
            return false;
        }

        {
            auto resourceProvider = fDContext->priv().resourceProvider();
            sk_sp<GrGpuBuffer> buffer = resourceProvider->findByUniqueKey<GrGpuBuffer>(key);
            if (buffer) {
                // the buffer holding the vertex data in this cache should never be discoverable
                // in the resource cache
                return false;
            }
        }

        return true;
    }

    bool checkImage(skiatest::Reporter* reporter, sk_sp<SkSurface> s) {
        SkBitmap actual;

        actual.allocPixels(default_ii(kImageWH));

        if (!s->readPixels(actual, 0, 0)) {
            return false;
        }

        SkBitmap expected = create_bitmap(kImageWH);

        const float tols[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

        auto error = std::function<ComparePixmapsErrorReporter>(
            [reporter](int x, int y, const float diffs[4]) {
                SkASSERT(x >= 0 && y >= 0);
                ERRORF(reporter, "mismatch at %d, %d (%f, %f, %f %f)",
                       x, y, diffs[0], diffs[1], diffs[2], diffs[3]);
            });

        return ComparePixels(expected.pixmap(), actual.pixmap(), tols, error);
    }

    bool checkImage(skiatest::Reporter* reporter) {
        return this->checkImage(reporter, fDst);
    }

    bool checkImage(skiatest::Reporter* reporter, sk_sp<SkDeferredDisplayList> ddl) {
        sk_sp<SkSurface> tmp = SkSurface::MakeRenderTarget(fDContext,
                                                           SkBudgeted::kNo,
                                                           default_ii(kImageWH));
        if (!tmp) {
            return false;
        }

        if (!tmp->draw(std::move(ddl))) {
            return false;
        }

        return this->checkImage(reporter, std::move(tmp));
    }

    size_t gpuSize(int wh) const {
        GrBackendFormat format = fDContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                                 GrRenderable::kNo);

        return GrSurface::ComputeSize(format, {wh, wh}, /*colorSamplesPerPixel=*/1,
                                      GrMipMapped::kNo, /*binSize=*/false);
    }

private:
    static GrSurfaceProxyView AccessCachedView(GrRecordingContext*,
                                               GrThreadSafeCache*,
                                               int wh,
                                               bool failLookup, bool failFillingIn, int id,
                                               Stats*);
    static GrSurfaceProxyView CreateViewOnCpu(GrRecordingContext*, int wh, Stats*);
    static bool FillInViewOnGpu(GrDirectContext*, int wh, Stats*,
                                const GrSurfaceProxyView& lazyView,
                                sk_sp<GrThreadSafeCache::Trampoline>);

    Stats fStats;
    GrDirectContext* fDContext = nullptr;
    GrThreadSafeCache::IsNewerBetter fIsNewerBetter;

    sk_sp<SkSurface> fDst;
    std::unique_ptr<SkDeferredDisplayListRecorder> fRecorder1;
    std::unique_ptr<SkDeferredDisplayListRecorder> fRecorder2;
};

class GrThreadSafeVertexTestOp : public GrDrawOp {
public:
    DEFINE_OP_CLASS_ID

    static GrOp::Owner Make(GrRecordingContext* rContext, TestHelper::Stats* stats,
                            int wh, int id, bool failLookup, bool failFillingIn,
                            GrThreadSafeCache::IsNewerBetter isNewerBetter) {

        return GrOp::Make<GrThreadSafeVertexTestOp>(
                rContext, rContext, stats, wh, id, failLookup, failFillingIn, isNewerBetter);
    }

    const GrThreadSafeCache::VertexData* vertexData() const { return fVertexData.get(); }

private:
    friend class GrOp; // for ctor

    GrThreadSafeVertexTestOp(GrRecordingContext* rContext, TestHelper::Stats* stats, int wh, int id,
                             bool failLookup, bool failFillingIn,
                             GrThreadSafeCache::IsNewerBetter isNewerBetter)
            : INHERITED(ClassID())
            , fStats(stats)
            , fWH(wh)
            , fID(id)
            , fFailFillingIn(failFillingIn)
            , fIsNewerBetter(isNewerBetter) {
        this->setBounds(SkRect::MakeIWH(fWH, fWH), HasAABloat::kNo, IsHairline::kNo);

        // Normally we wouldn't add a ref to the vertex data at this point. However, it is
        // needed in this unit test to get the ref counts on the uniquely keyed resources
        // to be as expected.
        this->findOrCreateVertices(rContext, failLookup, fFailFillingIn);
    }

    const char* name() const override { return "GrThreadSafeVertexTestOp"; }
    FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
        return GrProcessorSet::EmptySetAnalysis();
    }

    GrProgramInfo* createProgramInfo(const GrCaps* caps,
                                     SkArenaAlloc* arena,
                                     const GrSurfaceProxyView& writeView,
                                     bool usesMSAASurface,
                                     GrAppliedClip&& appliedClip,
                                     const GrDstProxyView& dstProxyView,
                                     GrXferBarrierFlags renderPassXferBarriers,
                                     GrLoadOp colorLoadOp) const {
        using namespace GrDefaultGeoProcFactory;

        Color color({ 0.0f, 0.0f, 1.0f, 1.0f });

        auto gp = MakeForDeviceSpace(arena, color,
                                     Coverage::kSolid_Type,
                                     LocalCoords::kUnused_Type,
                                     SkMatrix::I());

        return sk_gpu_test::CreateProgramInfo(caps, arena, writeView, usesMSAASurface,
                                              std::move(appliedClip), dstProxyView,
                                              gp, SkBlendMode::kSrcOver,
                                              GrPrimitiveType::kTriangleStrip,
                                              renderPassXferBarriers, colorLoadOp);
    }

    GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
        return this->createProgramInfo(&flushState->caps(),
                                       flushState->allocator(),
                                       flushState->writeView(),
                                       flushState->usesMSAASurface(),
                                       flushState->detachAppliedClip(),
                                       flushState->dstProxyView(),
                                       flushState->renderPassBarriers(),
                                       flushState->colorLoadOp());
    }

    void findOrCreateVertices(GrRecordingContext* rContext, bool failLookup, bool failFillingIn) {

        if (!fVertexData) {
            auto threadSafeViewCache = rContext->priv().threadSafeCache();

            if (rContext->asDirectContext()) {
                // The vertex variant doesn't have a correlate to lazyProxies but increment this
                // here to make the unit tests happy.
                ++fStats->fNumLazyCreations;
            }

            skgpu::UniqueKey key;
            create_vert_key(&key, fWH, fID);

            // We can "fail the lookup" to simulate a threaded race condition
            auto [cachedVerts, data] = threadSafeViewCache->findVertsWithData(key);
            if (cachedVerts && !failLookup) {
                fVertexData = cachedVerts;
                ++fStats->fCacheHits;
                return;
            }

            ++fStats->fCacheMisses;
            if (!rContext->asDirectContext()) {
                ++fStats->fNumSWCreations;
            }

            constexpr size_t kVertSize = sizeof(SkPoint);
            SkPoint* verts = static_cast<SkPoint*>(sk_malloc_throw(4 * kVertSize));

            verts[0].set(10.0f, 10.0f);
            verts[1].set(fWH-10.0f, 10.0f);
            verts[2].set(10.0f, fWH-10.0f);
            verts[3].set(fWH-10.0f, fWH-10.0f);

            fVertexData = GrThreadSafeCache::MakeVertexData(verts, 4, kVertSize);

            auto [tmpV, tmpD] = threadSafeViewCache->addVertsWithData(key, fVertexData,
                                                                      fIsNewerBetter);
            if (tmpV != fVertexData) {
                // Someone beat us to creating the vertex data. Use that version.
                fVertexData = tmpV;
            }
        }

        if (auto dContext = rContext->asDirectContext(); dContext && !fVertexData->gpuBuffer()) {
            auto rp = dContext->priv().resourceProvider();

            if (!failFillingIn) {
                ++fStats->fNumHWCreations;

                sk_sp<GrGpuBuffer> tmp = rp->createBuffer(fVertexData->size(),
                                                          GrGpuBufferType::kVertex,
                                                          kStatic_GrAccessPattern,
                                                          fVertexData->vertices());
                fVertexData->setGpuBuffer(std::move(tmp));
            }
        }
    }

    void onPrePrepare(GrRecordingContext* rContext,
                      const GrSurfaceProxyView& writeView,
                      GrAppliedClip* clip,
                      const GrDstProxyView& dstProxyView,
                      GrXferBarrierFlags renderPassXferBarriers,
                      GrLoadOp colorLoadOp) override {
        SkArenaAlloc* arena = rContext->priv().recordTimeAllocator();

        // DMSAA is not supported on DDL.
        bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;

        // This is equivalent to a GrOpFlushState::detachAppliedClip
        GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();

        fProgramInfo = this->createProgramInfo(rContext->priv().caps(), arena, writeView,
                                               usesMSAASurface, std::move(appliedClip),
                                               dstProxyView, renderPassXferBarriers, colorLoadOp);

        rContext->priv().recordProgramInfo(fProgramInfo);

        // This is now a noop (bc it is always called in the ctor) but is where we would normally
        // create the vertices.
        this->findOrCreateVertices(rContext, false, fFailFillingIn);
    }

    void onPrepare(GrOpFlushState* flushState) override {
        auto dContext = flushState->gpu()->getContext();

        // This call site is not a noop bc this op could've been created on with DDL context
        // and, therefore, could be lacking a gpu-side buffer
        this->findOrCreateVertices(dContext, false, fFailFillingIn);
    }

    void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
        if (!fVertexData || !fVertexData->gpuBuffer()) {
            return;
        }

        if (!fProgramInfo) {
            fProgramInfo = this->createProgramInfo(flushState);
        }

        flushState->bindPipeline(*fProgramInfo, SkRect::MakeIWH(fWH, fWH));
        flushState->bindBuffers(nullptr, nullptr, fVertexData->refGpuBuffer());
        flushState->draw(4, 0);
    }

    TestHelper::Stats*               fStats;
    int                              fWH;
    int                              fID;
    bool                             fFailFillingIn;
    GrThreadSafeCache::IsNewerBetter fIsNewerBetter;

    sk_sp<GrThreadSafeCache::VertexData> fVertexData;
    GrProgramInfo*                   fProgramInfo = nullptr;

    using INHERITED = GrDrawOp;
};

void TestHelper::addVertAccess(SkCanvas* canvas,
                               int wh, int id,
                               bool failLookup, bool failFillingIn,
                               GrThreadSafeVertexTestOp** createdOp) {
    auto rContext = canvas->recordingContext();
    auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);

    GrOp::Owner op = GrThreadSafeVertexTestOp::Make(rContext, &fStats,
                                                    wh, id,
                                                    failLookup, failFillingIn,
                                                    fIsNewerBetter);
    if (createdOp) {
        *createdOp = (GrThreadSafeVertexTestOp*) op.get();
    }

    sdc->addDrawOp(std::move(op));
}

GrSurfaceProxyView TestHelper::CreateViewOnCpu(GrRecordingContext* rContext,
                                               int wh,
                                               Stats* stats) {
    GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();

    sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(create_bitmap(wh),
                                                                       GrMipmapped::kNo,
                                                                       SkBackingFit::kExact,
                                                                       SkBudgeted::kYes);
    if (!proxy) {
        return {};
    }

    GrSwizzle swizzle = rContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
                                                                GrColorType::kRGBA_8888);
    ++stats->fNumSWCreations;
    return {std::move(proxy), kImageOrigin, swizzle};
}

bool TestHelper::FillInViewOnGpu(GrDirectContext* dContext, int wh, Stats* stats,
                                 const GrSurfaceProxyView& lazyView,
                                 sk_sp<GrThreadSafeCache::Trampoline> trampoline) {

    std::unique_ptr<skgpu::v1::SurfaceDrawContext> sdc = new_SDC(dContext, wh);

    GrPaint paint;
    paint.setColor4f({0.0f, 0.0f, 1.0f, 1.0f});

    sdc->clear(SkPMColor4f{1.0f, 1.0f, 1.0f, 1.0f});
    sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                  { 10, 10, wh-10.0f, wh-10.0f }, &GrStyle::SimpleFill());

    ++stats->fNumHWCreations;
    auto view = sdc->readSurfaceView();

    SkASSERT(view.swizzle() == lazyView.swizzle());
    SkASSERT(view.origin() == lazyView.origin());
    trampoline->fProxy = view.asTextureProxyRef();

    return true;
}

GrSurfaceProxyView TestHelper::AccessCachedView(GrRecordingContext* rContext,
                                                GrThreadSafeCache* threadSafeCache,
                                                int wh,
                                                bool failLookup, bool failFillingIn, int id,
                                                Stats* stats) {
    skgpu::UniqueKey key;
    create_view_key(&key, wh, id);

    if (GrDirectContext* dContext = rContext->asDirectContext()) {
        // The gpu thread gets priority over the recording threads. If the gpu thread is first,
        // it crams a lazy proxy into the cache and then fills it in later.
        auto [lazyView, trampoline] = GrThreadSafeCache::CreateLazyView(
            dContext, GrColorType::kRGBA_8888, {wh, wh}, kImageOrigin, SkBackingFit::kExact);
        ++stats->fNumLazyCreations;

        auto [view, data] = threadSafeCache->findOrAddWithData(key, lazyView);
        if (view != lazyView) {
            ++stats->fCacheHits;
            return view;
        } else if (id != kNoID) {
            // Make sure, in this case, that the customData stuck
            SkASSERT(data);
            SkDEBUGCODE(const int* cachedID = static_cast<const int*>(data->data());)
            SkASSERT(*cachedID == id);
        }

        ++stats->fCacheMisses;

        if (failFillingIn) {
            // Simulate something going horribly wrong at flush-time so no GrTexture is
            // available to fulfill the lazy proxy.
            return view;
        }

        if (!FillInViewOnGpu(dContext, wh, stats, lazyView, std::move(trampoline))) {
            // In this case something has gone disastrously wrong so set up to drop the draw
            // that needed this resource and reduce future pollution of the cache.
            threadSafeCache->remove(key);
            return {};
        }

        return view;
    } else {
        GrSurfaceProxyView view;

        // We can "fail the lookup" to simulate a threaded race condition
        if (view = threadSafeCache->find(key); !failLookup && view) {
            ++stats->fCacheHits;
            return view;
        }

        ++stats->fCacheMisses;

        view = CreateViewOnCpu(rContext, wh, stats);
        SkASSERT(view);

        auto [newView, data] = threadSafeCache->addWithData(key, view);
        if (view == newView && id != kNoID) {
            // Make sure, in this case, that the customData stuck
            SkASSERT(data);
            SkDEBUGCODE(const int* cachedID = static_cast<const int*>(data->data());)
            SkASSERT(*cachedID == id);
        }
        return newView;
    }
}

// Case 1: ensure two DDL recorders share the view/vertexData
static void test_1(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 2, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 1);

    helper.checkImage(reporter, helper.snap1());
    helper.checkImage(reporter, helper.snap2());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache1View, reporter, ctxInfo) {
    test_1(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache1Verts, reporter, ctxInfo) {
    test_1(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 2: ensure that, if the direct context version wins, its result is reused by the
//         DDL recorders
static void test_2(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, 1, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 2, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 3, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);

    helper.checkImage(reporter);
    helper.checkImage(reporter, helper.snap1());
    helper.checkImage(reporter, helper.snap2());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache2View, reporter, ctxInfo) {
    test_2(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache2Verts, reporter, ctxInfo) {
    test_2(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 3: ensure that, if the cpu-version wins, its result is reused by the direct context
static void test_3(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, 2, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 1);

    helper.checkImage(reporter);
    helper.checkImage(reporter, helper.snap1());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache3View, reporter, ctxInfo) {
    test_3(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache3Verts, reporter, ctxInfo) {
    test_3(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 4: ensure that, if two DDL recorders get in a race, they still end up sharing a single
//         view/vertexData
static void test_4(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 1, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));

    static const bool kFailLookup = true;
    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, 2, kFailLookup, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 2);

    helper.checkImage(reporter, helper.snap1());
    helper.checkImage(reporter, helper.snap2());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4View, reporter, ctxInfo) {
    test_4(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4Verts, reporter, ctxInfo) {
    test_4(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 4.5: check that, if a live rendering and a DDL recording get into a race, the live
//           rendering takes precedence.
static void test_4_5(GrDirectContext* dContext, skiatest::Reporter* reporter,
                     TestHelper::addAccessFP addAccess,
                     TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, 1, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);

    static const bool kFailLookup = true;
    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, 2, kFailLookup, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 2, /*id*/ 1));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 1);

    helper.checkImage(reporter);
    helper.checkImage(reporter, helper.snap1());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_5View, reporter, ctxInfo) {
    test_4_5(ctxInfo.directContext(), reporter,
             &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_5Verts, reporter, ctxInfo) {
    test_4_5(ctxInfo.directContext(), reporter,
             &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 4.75: check that, if a live rendering fails to generate the content needed to instantiate
//            its lazy proxy, life goes on
static void test_4_75(GrDirectContext* dContext, skiatest::Reporter* reporter,
                      TestHelper::addAccessFP addAccess,
                      TestHelper::checkFP check) {

    TestHelper helper(dContext);

    static const bool kFailFillingIn = true;
    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, kFailFillingIn);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);

    dContext->flush();
    dContext->submit(true);

    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 0, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 0);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_75View, reporter, ctxInfo) {
    test_4_75(ctxInfo.directContext(), reporter,
              &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache4_75Verts, reporter, ctxInfo) {
    test_4_75(ctxInfo.directContext(), reporter,
              &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 5: ensure that expanding the map works (esp. wrt custom data)
static void test_5(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    auto threadSafeCache = helper.threadSafeCache();

    int size = 16;
    (helper.*addAccess)(helper.ddlCanvas1(), size, /*id*/ size, false, false);

    size_t initialSize = threadSafeCache->approxBytesUsedForHash();

    while (initialSize == threadSafeCache->approxBytesUsedForHash()) {
        size *= 2;
        (helper.*addAccess)(helper.ddlCanvas1(), size, /*id*/ size, false, false);
    }

    for (int i = 16; i <= size; i *= 2) {
        REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(),
                                                  /*wh*/ i,
                                                  /*hits*/ 0,
                                                  /*misses*/ threadSafeCache->numEntries(),
                                                  /*refs*/ 1,
                                                  /*id*/ i));
    }
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache5View, reporter, ctxInfo) {
    test_5(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache5Verts, reporter, ctxInfo) {
    test_5(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 6: Check on dropping refs. In particular, that the cache has its own ref to keep
//         the backing resource alive and locked.
static void test_6(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    ddl1 = nullptr;
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 1, kNoID));

    ddl2 = nullptr;
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));

    // The cache still has its ref
    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 0, kNoID));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache6View, reporter, ctxInfo) {
    test_6(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache6Verts, reporter, ctxInfo) {
    test_6(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 7: Check that invoking dropAllRefs and dropUniqueRefs directly works as expected; i.e.,
//         dropAllRefs removes everything while dropUniqueRefs is more measured.
static void test_7(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);

    helper.threadSafeCache()->dropUniqueRefs(nullptr);
    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);

    ddl1 = nullptr;

    helper.threadSafeCache()->dropUniqueRefs(nullptr);
    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, (helper.*check)(nullptr, 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));

    helper.threadSafeCache()->dropAllRefs();
    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);

    ddl2 = nullptr;
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache7View, reporter, ctxInfo) {
    test_7(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache7Verts, reporter, ctxInfo) {
    test_7(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 8: This checks that GrContext::abandonContext works as expected wrt the thread
//         safe cache. This simulates the case where we have one DDL that has finished
//         recording but one still recording when the abandonContext fires.
static void test_8(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);

    dContext->abandonContext(); // This should exercise dropAllRefs

    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);

    ddl1 = nullptr;
    ddl2 = nullptr;
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache8View, reporter, ctxInfo) {
    test_8(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache8Verts, reporter, ctxInfo) {
    test_8(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 9: This checks that GrContext::releaseResourcesAndAbandonContext works as expected wrt
//         the thread safe cache. This simulates the case where we have one DDL that has finished
//         recording but one still recording when the releaseResourcesAndAbandonContext fires.
static void test_9(GrDirectContext* dContext, skiatest::Reporter* reporter,
                   TestHelper::addAccessFP addAccess,
                   TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 2, /*misses*/ 1, /*refs*/ 3, kNoID));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumLazyCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumHWCreations == 1);
    REPORTER_ASSERT(reporter, helper.stats()->fNumSWCreations == 0);

    dContext->releaseResourcesAndAbandonContext(); // This should hit dropAllRefs

    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);

    ddl1 = nullptr;
    ddl2 = nullptr;
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9View, reporter, ctxInfo) {
    test_9(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9Verts, reporter, ctxInfo) {
    test_9(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 10: This checks that the GrContext::purgeUnlockedResources(size_t) variant works as
//          expected wrt the thread safe cache. It, in particular, tests out the MRU behavior
//          of the shared cache.
static void test_10(GrDirectContext* dContext, skiatest::Reporter* reporter,
                    TestHelper::addAccessFP addAccess,
                    TestHelper::checkFP check) {

    if (GrBackendApi::kOpenGL != dContext->backend()) {
        // The lower-level backends have too much going on for the following simple purging
        // test to work
        return;
    }

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));

    (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), 2*kImageWH,
                                              /*hits*/ 2, /*misses*/ 2, /*refs*/ 2, kNoID));

    dContext->flush();
    dContext->submit(true);

    // This should clear out everything but the textures locked in the thread-safe cache
    dContext->purgeUnlockedResources(false);

    ddl1 = nullptr;
    ddl2 = nullptr;

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));

    // Regardless of which image is MRU, this should force the other out
    size_t desiredBytes = helper.gpuSize(2*kImageWH) + helper.gpuSize(kImageWH)/2;

    auto cache = dContext->priv().getResourceCache();
    size_t currentBytes = cache->getResourceBytes();

    SkASSERT(currentBytes >= desiredBytes);
    size_t amountToPurge = currentBytes - desiredBytes;

    // The 2*kImageWH texture should be MRU.
    dContext->purgeUnlockedResources(amountToPurge, true);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10View, reporter, ctxInfo) {
    test_10(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

// To enable test_10 with verts would require a bit more work, namely:
//    have a different # of verts based on size
//    also pass in a gpuSize function to 'test_10'
//DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10Verts, reporter, ctxInfo) {
//    test_10(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
//}

// Case 11: This checks that scratch-only variant of GrContext::purgeUnlockedResources works as
//          expected wrt the thread safe cache. In particular, that when 'scratchResourcesOnly'
//          is true, the call has no effect on the cache.
static void test_11(GrDirectContext* dContext, skiatest::Reporter* reporter,
                    TestHelper::addAccessFP addAccess,
                    TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));

    (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));

    dContext->flush();
    dContext->submit(true);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));

    // This shouldn't remove anything from the cache
    dContext->purgeUnlockedResources(/* scratchResourcesOnly */ true);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);

    dContext->purgeUnlockedResources(/* scratchResourcesOnly */ false);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache11View, reporter, ctxInfo) {
    test_11(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache11Verts, reporter, ctxInfo) {
    test_11(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 12: Test out purges caused by resetting the cache budget to 0. Note that, due to
//          the how the cache operates (i.e., not directly driven by ref/unrefs) there
//          needs to be an explicit kick to purge the cache.
static void test_12(GrDirectContext* dContext, skiatest::Reporter* reporter,
                    TestHelper::addAccessFP addAccess,
                    TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 1, /*refs*/ 2, kNoID));

    (helper.*addAccess)(helper.liveCanvas(), 2*kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));

    dContext->flush();
    dContext->submit(true);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), kImageWH,
                                              /*hits*/ 1, /*misses*/ 2, /*refs*/ 1, kNoID));
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 1, /*misses*/ 2, /*refs*/ 0, kNoID));

    dContext->setResourceCacheLimit(0);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    ddl1 = nullptr;

    // Explicitly kick off the purge - it won't happen automatically on unref
    dContext->performDeferredCleanup(std::chrono::milliseconds(0));

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache12View, reporter, ctxInfo) {
    test_12(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache12Verts, reporter, ctxInfo) {
    test_12(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 13: Test out the 'msNotUsed' parameter to GrContext::performDeferredCleanup.
static void test_13(GrDirectContext* dContext, skiatest::Reporter* reporter,
                    TestHelper::addAccessFP addAccess,
                    TestHelper::checkFP check) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();

    std::this_thread::sleep_for(std::chrono::milliseconds(5));
    auto firstTime = GrStdSteadyClock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(5));

    (helper.*addAccess)(helper.ddlCanvas2(), 2*kImageWH, kNoID, false, false);

    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();

    ddl1 = nullptr;
    ddl2 = nullptr;

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 2);

    auto secondTime = GrStdSteadyClock::now();

    auto msecs = std::chrono::duration_cast<std::chrono::milliseconds>(secondTime - firstTime);
    dContext->performDeferredCleanup(msecs);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.liveCanvas(), 2*kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 0, kNoID));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache13View, reporter, ctxInfo) {
    test_13(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache13Verts, reporter, ctxInfo) {
    test_13(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert);
}

// Case 14: Test out mixing & matching view & vertex data w/ recycling of the cache entries to
//          wring out the anonymous union code. This is mainly for the MSAN bot's consumption.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache14, reporter, ctxInfo) {
    constexpr int kBestPrimeNumber = 73; // palindromic in binary
    SkRandom rand(kBestPrimeNumber);

    TestHelper helper(ctxInfo.directContext());

    for (int i = 0; i < 2; ++i) {
        SkCanvas* ddlCanvas = (!i) ? helper.ddlCanvas1() : helper.ddlCanvas2();

        for (int j = 0; j < 10; ++j) {
            int numResources = 10*i + j + 1;
            int wh = numResources;

            if (rand.nextBool()) {
                helper.addViewAccess(ddlCanvas, wh, kNoID, false, false);
                REPORTER_ASSERT(reporter, helper.checkView(ddlCanvas, wh,
                                                           /*hits*/ 0, /*misses*/ numResources,
                                                           /*refs*/ 1, kNoID));
            } else {
                helper.addVertAccess(ddlCanvas, wh, kNoID, false, false);
                REPORTER_ASSERT(reporter, helper.checkVert(ddlCanvas, wh,
                                                           /*hits*/ 0, /*misses*/ numResources,
                                                           /*refs*/ 1, kNoID));
            }
        }

        if (!i) {
            // Drop all the accumulated resources from the thread-safe cache
            helper.snap1();
            ctxInfo.directContext()->purgeUnlockedResources(/* scratchResourcesOnly */ false);
        }
    }
}

// Case 15: Test out posting invalidation messages that involve the thread safe cache
static void test_15(GrDirectContext* dContext, skiatest::Reporter* reporter,
                    TestHelper::addAccessFP addAccess,
                    TestHelper::checkFP check,
                    void (*create_key)(skgpu::UniqueKey*, int wh, int id)) {

    TestHelper helper(dContext);

    (helper.*addAccess)(helper.ddlCanvas1(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas1(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    skgpu::UniqueKey key;
    (*create_key)(&key, kImageWH, kNoID);

    skgpu::UniqueKeyInvalidatedMessage msg(key, dContext->priv().contextID(),
                                      /* inThreadSafeCache */ true);

    SkMessageBus<skgpu::UniqueKeyInvalidatedMessage, uint32_t>::Post(msg);

    // This purge call is needed to process the invalidation messages
    dContext->purgeUnlockedResources(/* scratchResourcesOnly */ true);

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 0);

    (helper.*addAccess)(helper.ddlCanvas2(), kImageWH, kNoID, false, false);
    REPORTER_ASSERT(reporter, (helper.*check)(helper.ddlCanvas2(), kImageWH,
                                              /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();

    REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);

    helper.checkImage(reporter, std::move(ddl1));
    helper.checkImage(reporter, std::move(ddl2));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache15View, reporter, ctxInfo) {
    test_15(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView,
            create_view_key);
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache15Verts, reporter, ctxInfo) {
    test_15(ctxInfo.directContext(), reporter, &TestHelper::addVertAccess, &TestHelper::checkVert,
            create_vert_key);
}

// Case 16: Test out pre-emption of an existing vertex-data cache entry. This test simulates
//          the case where there is a race to create vertex data. However, the second one
//          to finish is better and usurps the first's position in the cache.
//
//          This capability isn't available for views.

static bool newer_is_always_better(SkData* /* incumbent */, SkData* /* challenger */) {
    return true;
};

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache16Verts, reporter, ctxInfo) {
    skgpu::UniqueKey key;
    create_vert_key(&key, kImageWH, kNoID);

    TestHelper helper(ctxInfo.directContext(), newer_is_always_better);

    GrThreadSafeVertexTestOp* op1 = nullptr, *op2 = nullptr;

    helper.addVertAccess(helper.ddlCanvas1(), kImageWH, kNoID, false, false, &op1);
    REPORTER_ASSERT(reporter, helper.checkVert(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl1 = helper.snap1();

    {
        REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
        auto [vertexData, xtraData] = helper.threadSafeCache()->findVertsWithData(key);
        REPORTER_ASSERT(reporter, vertexData.get() == op1->vertexData());
    }

    helper.addVertAccess(helper.ddlCanvas2(), kImageWH, kNoID, /* failLookup */ true, false, &op2);
    REPORTER_ASSERT(reporter, helper.checkVert(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 1, kNoID));
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();

    REPORTER_ASSERT(reporter, op1->vertexData() != op2->vertexData());

    {
        REPORTER_ASSERT(reporter, helper.numCacheEntries() == 1);
        auto [vertexData, xtraData] = helper.threadSafeCache()->findVertsWithData(key);
        REPORTER_ASSERT(reporter, vertexData.get() == op2->vertexData());
    }

    helper.checkImage(reporter, std::move(ddl1));
    helper.checkImage(reporter, std::move(ddl2));
}
