/*
 * 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/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/GrRenderTargetContext.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrThreadSafeCache.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<GrRenderTargetContext> new_RTC(GrRecordingContext* rContext, int wh) {
    return GrRenderTargetContext::Make(rContext,
                                       GrColorType::kRGBA_8888,
                                       nullptr,
                                       SkBackingFit::kExact,
                                       {wh, wh},
                                       1,
                                       GrMipMapped::kNo,
                                       GrProtected::kNo,
                                       kImageOrigin,
                                       SkBudgeted::kYes);
}

static void create_view_key(GrUniqueKey* key, int wh, int id) {
    static const GrUniqueKey::Domain kViewDomain = GrUniqueKey::GenerateDomain();
    GrUniqueKey::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(GrUniqueKey* key, int wh, int id) {
    static const GrUniqueKey::Domain kVertDomain = GrUniqueKey::GenerateDomain();
    GrUniqueKey::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 rtc = canvas->internal_private_accessTopLayerRenderTargetContext();

        rtc->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;
        }

        GrUniqueKey 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;
        }

        GrUniqueKey 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*,
                                      bool hasMixedSampledCoverage, GrClampType) override {
        return GrProcessorSet::EmptySetAnalysis();
    }

    GrProgramInfo* createProgramInfo(const GrCaps* caps,
                                     SkArenaAlloc* arena,
                                     const GrSurfaceProxyView& writeView,
                                     GrAppliedClip&& appliedClip,
                                     const GrXferProcessor::DstProxyView& 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,
                                              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->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;
            }

            GrUniqueKey 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 GrXferProcessor::DstProxyView& dstProxyView,
                      GrXferBarrierFlags renderPassXferBarriers,
                      GrLoadOp colorLoadOp) override {
        SkArenaAlloc* arena = rContext->priv().recordTimeAllocator();

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

        fProgramInfo = this->createProgramInfo(rContext->priv().caps(), arena, writeView,
                                               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 rtc = canvas->internal_private_accessTopLayerRenderTargetContext();

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

    rtc->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<GrRenderTargetContext> rtc = new_RTC(dContext, wh);

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

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

    ++stats->fNumHWCreations;
    auto view = rtc->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) {
    GrUniqueKey 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)(GrUniqueKey*, 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);

    GrUniqueKey key;
    (*create_key)(&key, kImageWH, kNoID);

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

    SkMessageBus<GrUniqueKeyInvalidatedMessage>::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) {
    GrUniqueKey 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));
}
