/*
 * 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 "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrThreadSafeUniquelyKeyedProxyViewCache.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"

#include <thread>

static constexpr int kImageWH = 32;
static constexpr auto kImageOrigin = kBottomLeft_GrSurfaceOrigin;

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_key(GrUniqueKey* key, int wh) {
    static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
    GrUniqueKey::Builder builder(key, kDomain, 1);
    builder[0] = wh;
    builder.finish();
};

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);

    return bitmap;
}

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

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

    TestHelper(GrDirectContext* dContext) : fDContext(dContext) {

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

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

        fRecorder1 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);

        fRecorder2 = std::make_unique<SkDeferredDisplayListRecorder>(characterization);
    }

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

    Stats* stats() { return &fStats; }

    int numCacheEntries() const { return this->threadSafeViewCache()->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;
    }

    GrThreadSafeUniquelyKeyedProxyViewCache* threadSafeViewCache() {
        return fDContext->priv().threadSafeViewCache();
    }

    const GrThreadSafeUniquelyKeyedProxyViewCache* threadSafeViewCache() const {
        return fDContext->priv().threadSafeViewCache();
    }

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

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

        auto rtc = canvas->internal_private_accessTopLayerRenderTargetContext();

        rtc->drawTexture(nullptr,
                         view,
                         kPremul_SkAlphaType,
                         GrSamplerState::Filter::kNearest,
                         GrSamplerState::MipmapMode::kNone,
                         SkBlendMode::kSrcOver,
                         SkPMColor4f(),
                         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 hits, int misses, int numRefs) {
        if (fStats.fCacheHits != hits || fStats.fCacheMisses != misses) {
            SkDebugf("Hits E: %d A: %d --- Misses E: %d A: %d\n",
                     hits, fStats.fCacheHits, misses, fStats.fCacheMisses);
            return false;
        }

        GrUniqueKey key;
        create_key(&key, wh);

        auto threadSafeViewCache = this->threadSafeViewCache();

        GrSurfaceProxyView view = threadSafeViewCache->find(key);
        if (!view.proxy()) {
            return false;
        }

        if (!view.proxy()->refCntGreaterThan(numRefs+1) ||  // +1 for 'view's ref
            view.proxy()->refCntGreaterThan(numRefs+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;
    }

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

        return GrSurface::ComputeSize(*fDContext->priv().caps(), format,
                                      {wh, wh}, 1, GrMipMapped::kNo, false);
    }

private:
    // In the gpu-creation case, we need to pre-emptively place a lazy proxy in the shared
    // cache. This object allows that lazy proxy to be instantiated with some rendering result
    // generated after the fact.
    class Trampoline : public SkRefCnt {
    public:
        sk_sp<GrTextureProxy> fProxy;
    };

    static GrSurfaceProxyView AccessCachedView(GrRecordingContext*,
                                               GrThreadSafeUniquelyKeyedProxyViewCache*,
                                               int wh,
                                               bool failLookup, bool failFillingIn,
                                               Stats*);
    static GrSurfaceProxyView CreateViewOnCpu(GrRecordingContext*, int wh, Stats*);
    static std::tuple<GrSurfaceProxyView, sk_sp<Trampoline>> CreateLazyView(GrDirectContext*,
                                                                            int wh, Stats*);
    static bool FillInViewOnGpu(GrDirectContext*, int wh, Stats*,
                                const GrSurfaceProxyView& lazyView,
                                sk_sp<Trampoline>);

    Stats fStats;
    GrDirectContext* fDContext = nullptr;

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

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

std::tuple<GrSurfaceProxyView, sk_sp<TestHelper::Trampoline>> TestHelper::CreateLazyView(
            GrDirectContext* dContext, int wh, Stats* stats) {

    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();

    sk_sp<Trampoline> trampoline(new Trampoline);

    GrProxyProvider::TextureInfo texInfo { GrMipMapped::kNo, GrTextureType::k2D };

    GrBackendFormat format = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                            GrRenderable::kYes);
    sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
        [trampoline] (GrResourceProvider* resourceProvider, const GrSurfaceProxy::LazySurfaceDesc&)
                -> GrSurfaceProxy::LazyCallbackResult {
            if (!resourceProvider || !trampoline->fProxy || !trampoline->fProxy->isInstantiated()) {
                return GrSurfaceProxy::LazyCallbackResult(nullptr, true);

            }

            SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
            return GrSurfaceProxy::LazyCallbackResult(sk_ref_sp(trampoline->fProxy->peekTexture()));
        },
        format,
        {wh, wh},
        /* renderTargetSampleCnt */ 1,
        GrInternalSurfaceFlags::kNone,
        &texInfo,
        GrMipmapStatus::kNotAllocated,
        SkBackingFit::kExact,
        SkBudgeted::kYes,
        GrProtected::kNo,
        /* wrapsVkSecondaryCB */ false,
        GrSurfaceProxy::UseAllocator::kYes);

    GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, GrColorType::kRGBA_8888);

    ++stats->fNumLazyCreations;
    return {{std::move(proxy), kImageOrigin, swizzle}, std::move(trampoline)};
}

bool TestHelper::FillInViewOnGpu(GrDirectContext* dContext, int wh, Stats* stats,
                                 const GrSurfaceProxyView& lazyView,
                                 sk_sp<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,
                                    GrThreadSafeUniquelyKeyedProxyViewCache* threadSafeViewCache,
                                    int wh,
                                    bool failLookup, bool failFillingIn,
                                    Stats* stats) {
    GrUniqueKey key;
    create_key(&key, wh);

    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] = CreateLazyView(dContext, wh, stats);

        GrSurfaceProxyView view = threadSafeViewCache->findOrAdd(key, lazyView);
        if (view != lazyView) {
            ++stats->fCacheHits;
            return view;
        }

        ++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.
            threadSafeViewCache->remove(key);
            return {};
        }

        return view;
    } else {
        GrSurfaceProxyView view;

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

        ++stats->fCacheMisses;

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

        return threadSafeViewCache->add(key, view);
    }
}

// Case 1: ensure two DDL recorders share the view
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache1, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

    helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1));

    helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 1, /*misses*/ 1, /*refs*/ 2));

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

// Case 2: ensure that, if the direct context version wins, it is reused by the DDL recorders
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache2, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

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

    helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 1, /*misses*/ 1, /*refs*/ 2));

    helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 2, /*misses*/ 1, /*refs*/ 3));

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

// Case 3: ensure that, if the cpu-version wins, it is reused by the direct context
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache3, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

    helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1));

    helper.accessCachedView(helper.liveCanvas(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
                                               /*hits*/ 1, /*misses*/ 1, /*refs*/ 2));

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

// Case 4: ensure that, if two DDL recorders get in a race, they still end up sharing a single view
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache4, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

    helper.accessCachedView(helper.ddlCanvas1(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1));

    static const bool kFailLookup = true;
    helper.accessCachedView(helper.ddlCanvas2(), kImageWH, kFailLookup);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 2));

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

// Case 4.5: check that, if a live rendering and a DDL recording get into a race, the live
// rendering takes precedence.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache4_5, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

    helper.accessCachedView(helper.liveCanvas(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 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.accessCachedView(helper.ddlCanvas1(), kImageWH, kFailLookup);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 2));

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

// Case 4.75: check that, if a live rendering fails to generate the content needed to instantiate
//            its lazy proxy, life goes on
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache4_75, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();

    TestHelper helper(dContext);

    static const bool kFailFillingIn = true;
    helper.accessCachedView(helper.liveCanvas(), kImageWH, false, kFailFillingIn);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 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 == 0);

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

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

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

// Case 5: ensure that expanding the map works
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache5, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

    auto threadSafeViewCache = helper.threadSafeViewCache();

    int size = 16;
    helper.accessCachedView(helper.ddlCanvas1(), size);

    size_t initialSize = threadSafeViewCache->approxBytesUsedForHash();

    while (initialSize == threadSafeViewCache->approxBytesUsedForHash()) {
        size *= 2;
        helper.accessCachedView(helper.ddlCanvas1(), size);
    }
}

// Case 6: check on dropping refs
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache6, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

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

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

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

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

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

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

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

// Case 7: check that invoking dropAllRefs and dropAllUniqueRefs directly works as expected
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache7, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

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

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

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

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

    ddl1 = nullptr;

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

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

    ddl2 = nullptr;
}

// 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.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache8, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

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

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

    helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 2, /*misses*/ 1, /*refs*/ 3));

    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);

    ctxInfo.directContext()->abandonContext(); // This should exercise dropAllRefs

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

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

    ddl1 = nullptr;
    ddl2 = nullptr;
}

// 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.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache9, reporter, ctxInfo) {
    TestHelper helper(ctxInfo.directContext());

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

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

    helper.accessCachedView(helper.ddlCanvas2(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), kImageWH,
                                               /*hits*/ 2, /*misses*/ 1, /*refs*/ 3));

    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);

    ctxInfo.directContext()->releaseResourcesAndAbandonContext(); // This should hit dropAllRefs

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

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

    ddl1 = nullptr;
    ddl2 = nullptr;
}

// 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.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache10, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();

    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.accessCachedView(helper.liveCanvas(), kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1));

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

    helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 1, /*misses*/ 2, /*refs*/ 1));

    helper.accessCachedView(helper.ddlCanvas2(), 2*kImageWH);
    sk_sp<SkDeferredDisplayList> ddl2 = helper.snap2();
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), 2*kImageWH,
                                               /*hits*/ 2, /*misses*/ 2, /*refs*/ 2));

    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.checkView(helper.liveCanvas(), kImageWH,
                                               /*hits*/ 2, /*misses*/ 2, /*refs*/ 0));
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 2, /*misses*/ 2, /*refs*/ 0));

    // 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.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 2, /*misses*/ 2, /*refs*/ 0));
}

// Case 11: This checks that scratch-only variant of GrContext::purgeUnlockedResources works as
//          expected wrt the thread safe cache.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache11, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();

    TestHelper helper(dContext);

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

    helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 1));

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

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

    // 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);
}

// Case 12: Test out purges caused by resetting the cache budget
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache12, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();

    TestHelper helper(dContext);

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

    helper.accessCachedView(helper.liveCanvas(), 2*kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 1, /*misses*/ 2, /*refs*/ 1));

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

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

    dContext->setResourceCacheLimit(0);

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

    ddl1 = nullptr;

    dContext->performDeferredCleanup(std::chrono::milliseconds(0));

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

// Case 13: Test out the 'msNotUsed' parameter to GrContext::performDeferredCleanup.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeViewCache13, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();

    TestHelper helper(dContext);

    helper.accessCachedView(helper.ddlCanvas1(), kImageWH);

    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas1(), kImageWH,
                                               /*hits*/ 0, /*misses*/ 1, /*refs*/ 1));
    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.accessCachedView(helper.ddlCanvas2(), 2*kImageWH);
    REPORTER_ASSERT(reporter, helper.checkView(helper.ddlCanvas2(), 2*kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 1));
    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.checkView(helper.liveCanvas(), 2*kImageWH,
                                               /*hits*/ 0, /*misses*/ 2, /*refs*/ 0));
}
