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

#include "include/core/SkAlphaType.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTo.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrResourceAllocator.h"
#include "src/gpu/ganesh/GrResourceCache.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrSurface.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyPriv.h"
#include "src/gpu/ganesh/GrTexture.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/gpu/ManagedBackendTexture.h"

#include <array>
#include <cstddef>
#include <functional>
#include <utility>

using namespace skia_private;

class GrRecordingContext;
struct GrContextOptions;

namespace {
struct ProxyParams {
    int             fSize;
    GrRenderable    fRenderable;
    GrColorType     fColorType;
    SkBackingFit    fFit;
    int             fSampleCnt;
    skgpu::Budgeted fBudgeted;
    enum Kind {
        kDeferred,
        kBackend,
        kFullyLazy,
        kLazy,
        kInstantiated
    };
    Kind            fKind;
    skgpu::UniqueKey     fUniqueKey = skgpu::UniqueKey();
    // TODO: do we care about mipmapping
};

constexpr GrRenderable kRT = GrRenderable::kYes;
constexpr GrRenderable kNotRT = GrRenderable::kNo;

constexpr GrColorType kRGBA = GrColorType::kRGBA_8888;
constexpr GrColorType kAlpha = GrColorType::kAlpha_8;

constexpr SkBackingFit kE = SkBackingFit::kExact;
constexpr SkBackingFit kA = SkBackingFit::kApprox;

constexpr skgpu::Budgeted kNotB = skgpu::Budgeted::kNo;
constexpr skgpu::Budgeted kB = skgpu::Budgeted::kYes;

constexpr ProxyParams::Kind kDeferred = ProxyParams::Kind::kDeferred;
constexpr ProxyParams::Kind kBackend = ProxyParams::Kind::kBackend;
constexpr ProxyParams::Kind kInstantiated = ProxyParams::Kind::kInstantiated;
constexpr ProxyParams::Kind kLazy = ProxyParams::Kind::kLazy;
constexpr ProxyParams::Kind kFullyLazy = ProxyParams::Kind::kFullyLazy;
}

static sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const GrCaps* caps,
                                           const ProxyParams& p) {
    const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable);
    return proxyProvider->createProxy(format,
                                      {p.fSize, p.fSize},
                                      p.fRenderable,
                                      p.fSampleCnt,
                                      skgpu::Mipmapped::kNo,
                                      p.fFit,
                                      p.fBudgeted,
                                      GrProtected::kNo,
                                      /*label=*/"ResourceAllocatorTest_Deffered");
}

static sk_sp<GrSurfaceProxy> make_backend(GrDirectContext* dContext, const ProxyParams& p) {
    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();

    SkColorType skColorType = GrColorTypeToSkColorType(p.fColorType);
    SkASSERT(SkColorType::kUnknown_SkColorType != skColorType);

    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
            dContext, p.fSize, p.fSize, skColorType, skgpu::Mipmapped::kNo, GrRenderable::kNo);

    if (!mbet) {
        return nullptr;
    }

    return proxyProvider->wrapBackendTexture(mbet->texture(),
                                             kBorrow_GrWrapOwnership,
                                             GrWrapCacheable::kNo,
                                             kRead_GrIOType,
                                             mbet->refCountedCallback());
}

static sk_sp<GrSurfaceProxy> make_fully_lazy(GrProxyProvider* proxyProvider, const GrCaps* caps,
                                             const ProxyParams& p) {
    const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable);
    auto cb = [p](GrResourceProvider* provider, const GrSurfaceProxy::LazySurfaceDesc& desc) {
        auto tex = provider->createTexture({p.fSize, p.fSize},
                                           desc.fFormat,
                                           desc.fTextureType,
                                           desc.fRenderable,
                                           desc.fSampleCnt,
                                           desc.fMipmapped,
                                           desc.fBudgeted,
                                           desc.fProtected,
                                           /*label=*/"ResourceAllocatorTest_FullLazy");
        return GrSurfaceProxy::LazyCallbackResult(std::move(tex));
    };
    return GrProxyProvider::MakeFullyLazyProxy(std::move(cb), format, p.fRenderable, p.fSampleCnt,
                                               GrProtected::kNo, *caps,
                                               GrSurfaceProxy::UseAllocator::kYes);
}

static sk_sp<GrSurfaceProxy> make_lazy(GrProxyProvider* proxyProvider, const GrCaps* caps,
                                       const ProxyParams& p) {
    const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable);
    auto cb = [](GrResourceProvider* provider, const GrSurfaceProxy::LazySurfaceDesc& desc) {
        auto tex = provider->createTexture(desc.fDimensions,
                                           desc.fFormat,
                                           desc.fTextureType,
                                           desc.fRenderable,
                                           desc.fSampleCnt,
                                           desc.fMipmapped,
                                           desc.fBudgeted,
                                           desc.fProtected,
                                           /*label=*/"ResourceAllocatorTest_Lazy");
        return GrSurfaceProxy::LazyCallbackResult(std::move(tex));
    };
    return proxyProvider->createLazyProxy(std::move(cb),
                                          format,
                                          {p.fSize, p.fSize},
                                          skgpu::Mipmapped::kNo,
                                          GrMipmapStatus::kNotAllocated,
                                          GrInternalSurfaceFlags::kNone,
                                          p.fFit,
                                          p.fBudgeted,
                                          GrProtected::kNo,
                                          GrSurfaceProxy::UseAllocator::kYes,
                                          /*label=*/{});
}

static sk_sp<GrSurfaceProxy> make_proxy(GrDirectContext* dContext, const ProxyParams& p) {
    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
    const GrCaps* caps = dContext->priv().caps();
    sk_sp<GrSurfaceProxy> proxy;
    switch (p.fKind) {
        case ProxyParams::kDeferred:
            proxy = make_deferred(proxyProvider, caps, p);
            break;
        case ProxyParams::kBackend:
            proxy = make_backend(dContext, p);
            break;
        case ProxyParams::kFullyLazy:
            proxy = make_fully_lazy(proxyProvider, caps, p);
            break;
        case ProxyParams::kLazy:
            proxy = make_lazy(proxyProvider, caps, p);
            break;
        case ProxyParams::kInstantiated:
            proxy = make_deferred(proxyProvider, caps, p);
            if (proxy) {
                auto surf = proxy->priv().createSurface(dContext->priv().resourceProvider());
                proxy->priv().assign(std::move(surf));
            }
            break;
    }
    if (proxy && p.fUniqueKey.isValid()) {
        SkASSERT(proxy->asTextureProxy());
        proxyProvider->assignUniqueKeyToProxy(p.fUniqueKey, proxy->asTextureProxy());
    }
    return proxy;
}

// Basic test that two proxies with overlapping intervals and compatible descriptors are
// assigned different GrSurfaces.
static void overlap_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
                         const sk_sp<GrSurfaceProxy>& p1, const sk_sp<GrSurfaceProxy>& p2,
                         bool expectedResult) {
    GrResourceAllocator alloc(dContext);

    alloc.addInterval(p1.get(), 0, 4, GrResourceAllocator::ActualUse::kYes,
                      GrResourceAllocator::AllowRecycling::kYes);
    alloc.incOps();
    alloc.addInterval(p2.get(), 1, 2, GrResourceAllocator::ActualUse::kYes,
                      GrResourceAllocator::AllowRecycling::kYes);
    alloc.incOps();

    REPORTER_ASSERT(reporter, alloc.planAssignment());
    REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom());
    REPORTER_ASSERT(reporter, alloc.assign());

    REPORTER_ASSERT(reporter, p1->peekSurface());
    REPORTER_ASSERT(reporter, p2->peekSurface());
    bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
    REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
}

// Test various cases when two proxies do not have overlapping intervals.
// This mainly acts as a test of the ResourceAllocator's free pool.
static void non_overlap_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
                             const sk_sp<GrSurfaceProxy>& p1, const sk_sp<GrSurfaceProxy>& p2,
                             bool expectedResult) {
    GrResourceAllocator alloc(dContext);

    alloc.incOps();
    alloc.incOps();
    alloc.incOps();
    alloc.incOps();
    alloc.incOps();
    alloc.incOps();

    alloc.addInterval(p1.get(), 0, 2, GrResourceAllocator::ActualUse::kYes,
                      GrResourceAllocator::AllowRecycling::kYes);
    alloc.addInterval(p2.get(), 3, 5, GrResourceAllocator::ActualUse::kYes,
                      GrResourceAllocator::AllowRecycling::kYes);

    REPORTER_ASSERT(reporter, alloc.planAssignment());
    REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom());
    REPORTER_ASSERT(reporter, alloc.assign());

    REPORTER_ASSERT(reporter, p1->peekSurface());
    REPORTER_ASSERT(reporter, p2->peekSurface());
    bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
    REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();
    const GrCaps* caps = dContext->priv().caps();

    struct TestCase {
        ProxyParams   fP1;
        ProxyParams   fP2;
        bool          fExpectation;
    };

    constexpr bool kShare = true;
    constexpr bool kDontShare = false;

    // Non-RT GrSurfaces are never recycled on some platforms.
    bool kConditionallyShare = caps->reuseScratchTextures();

    static const auto overlappingTests = std::to_array<TestCase>({
            // Two proxies with overlapping intervals and compatible descriptors should never share
            // RT version
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                     {64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                     kDontShare},
            // non-RT version
            TestCase{{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                     {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                     kDontShare},
    });

    for (size_t i = 0; i < std::size(overlappingTests); i++) {
        const TestCase& test = overlappingTests[i];
        sk_sp<GrSurfaceProxy> p1 = make_proxy(dContext, test.fP1);
        sk_sp<GrSurfaceProxy> p2 = make_proxy(dContext, test.fP2);
        reporter->push(SkStringPrintf("case %d", SkToInt(i)));
        overlap_test(reporter, dContext, std::move(p1), std::move(p2), test.fExpectation);
        reporter->pop();
    }

    auto beFormat = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kYes);
    int k2 = caps->getRenderTargetSampleCount(2, beFormat);
    int k4 = caps->getRenderTargetSampleCount(4, beFormat);

    // This cannot be made static as some of the members depend on non static variables like
    // kConditionallyShare, k2, and k4.
    const auto nonOverlappingTests = std::to_array<TestCase>({
            // Two non-overlapping intervals w/ compatible proxies should share
            // both same size & approx
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kShare},
            TestCase{{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kConditionallyShare},
            // diffs sizes but still approx
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {50, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kShare},
            TestCase{{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {50, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kConditionallyShare},
            // sames sizes but exact
            TestCase{{64, kRT, kRGBA, kE, 1, kNotB, kDeferred},
                    {64, kRT, kRGBA, kE, 1, kNotB, kDeferred},
                    kShare},
            TestCase{{64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred},
                    {64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred},
                    kConditionallyShare},
            // Two non-overlapping intervals w/ different exact sizes should not share
            TestCase{{56, kRT, kRGBA, kE, 1, kNotB, kDeferred},
                    {54, kRT, kRGBA, kE, 1, kNotB, kDeferred},
                    kDontShare},
            // Two non-overlapping intervals w/ _very different_ approx sizes should not share
            TestCase{{255, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {127, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kDontShare},
            // Two non-overlapping intervals w/ different MSAA sample counts should not share
            TestCase{{64, kRT, kRGBA, kA, k2, kNotB, kDeferred},
                    {64, kRT, kRGBA, kA, k4, kNotB, kDeferred},
                    k2 == k4},
            // Two non-overlapping intervals w/ different configs should not share
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kRT, kAlpha, kA, 1, kNotB, kDeferred},
                    kDontShare},
            // Two non-overlapping intervals w/ different RT classifications should never share
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kDontShare},
            TestCase{{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kDontShare},
            // Two non-overlapping intervals w/ different origins should share
            TestCase{{64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    {64, kRT, kRGBA, kA, 1, kNotB, kDeferred},
                    kShare},
            // Wrapped backend textures should never be reused
            TestCase{{64, kNotRT, kRGBA, kE, 1, kNotB, kBackend},
                    {64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred},
                    kDontShare}});

    for (size_t i = 0; i < std::size(nonOverlappingTests); i++) {
        const TestCase& test = nonOverlappingTests[i];
        sk_sp<GrSurfaceProxy> p1 = make_proxy(dContext, test.fP1);
        sk_sp<GrSurfaceProxy> p2 = make_proxy(dContext, test.fP2);

        if (!p1 || !p2) {
            continue; // creation can fail (e.g., for msaa4 on iOS)
        }

        reporter->push(SkStringPrintf("case %d", SkToInt(i)));
        non_overlap_test(reporter, dContext, std::move(p1), std::move(p2),
                         test.fExpectation);
        reporter->pop();
    }
}

static void draw(GrRecordingContext* rContext) {
    SkImageInfo ii = SkImageInfo::Make(1024, 1024, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    sk_sp<SkSurface> s = SkSurfaces::RenderTarget(
            rContext, skgpu::Budgeted::kYes, ii, 1, kTopLeft_GrSurfaceOrigin, nullptr);

    SkCanvas* c = s->getCanvas();

    c->clear(SK_ColorBLACK);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorStressTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    auto context = ctxInfo.directContext();

    size_t maxBytes = context->getResourceCacheLimit();

    context->setResourceCacheLimit(0); // We'll always be overbudget

    draw(context);
    draw(context);
    draw(context);
    draw(context);
    context->flushAndSubmit();

    context->setResourceCacheLimit(maxBytes);
}

struct Interval {
    ProxyParams           fParams;
    int                   fStart;
    int                   fEnd;
    sk_sp<GrSurfaceProxy> fProxy = nullptr;
};

struct TestCase {
    const char *          fName;
    bool                  fShouldFit;
    size_t                fBudget;
    TArray<ProxyParams> fPurgeableResourcesInCache = {};
    TArray<ProxyParams> fUnpurgeableResourcesInCache = {};
    TArray<Interval>    fIntervals;
};

static void memory_budget_test(skiatest::Reporter* reporter,
                               GrDirectContext* dContext,
                               const TestCase& test) {
    // Reset cache.
    auto cache = dContext->priv().getResourceCache();
    cache->releaseAll();
    cache->setLimit(test.fBudget);

    // Add purgeable entries.
    size_t expectedPurgeableBytes = 0;
    TArray<sk_sp<GrSurface>> purgeableSurfaces;
    for (auto& params : test.fPurgeableResourcesInCache) {
        SkASSERT(params.fKind == kInstantiated);
        sk_sp<GrSurfaceProxy> proxy = make_proxy(dContext, params);
        REPORTER_ASSERT(reporter, proxy->peekSurface());
        expectedPurgeableBytes += proxy->gpuMemorySize();
        purgeableSurfaces.push_back(sk_ref_sp(proxy->peekSurface()));
    }
    purgeableSurfaces.clear();
    REPORTER_ASSERT(reporter, expectedPurgeableBytes == cache->getPurgeableBytes(),
                    "%zu", cache->getPurgeableBytes());

    // Add unpurgeable entries.
    size_t expectedUnpurgeableBytes = 0;
    TArray<sk_sp<GrSurface>> unpurgeableSurfaces;
    for (auto& params : test.fUnpurgeableResourcesInCache) {
        SkASSERT(params.fKind == kInstantiated);
        sk_sp<GrSurfaceProxy> proxy = make_proxy(dContext, params);
        REPORTER_ASSERT(reporter, proxy->peekSurface());
        expectedUnpurgeableBytes += proxy->gpuMemorySize();
        unpurgeableSurfaces.push_back(sk_ref_sp(proxy->peekSurface()));
    }

    auto unpurgeableBytes = cache->getBudgetedResourceBytes() - cache->getPurgeableBytes();
    REPORTER_ASSERT(reporter, expectedUnpurgeableBytes == unpurgeableBytes,
                    "%zu", unpurgeableBytes);

    // Add intervals and test.
    GrResourceAllocator alloc(dContext);
    for (auto& interval : test.fIntervals) {
        for (int i = interval.fStart; i <= interval.fEnd; i++) {
            alloc.incOps();
        }
        alloc.addInterval(interval.fProxy.get(), interval.fStart, interval.fEnd,
                          GrResourceAllocator::ActualUse::kYes,
                          GrResourceAllocator::AllowRecycling::kYes);
    }
    REPORTER_ASSERT(reporter, alloc.planAssignment());
    REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom() == test.fShouldFit);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorMemoryBudgetTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();

    constexpr bool    kUnder               = true;
    constexpr bool    kOver                = false;
    constexpr size_t  kRGBA64Bytes         = 4 * 64 * 64;
    const ProxyParams kProxy64             = {64, kRT, kRGBA, kE, 1, kB,    kDeferred};
    const ProxyParams kProxy64NotBudgeted  = {64, kRT, kRGBA, kE, 1, kNotB, kDeferred};
    const ProxyParams kProxy64Lazy         = {64, kRT, kRGBA, kE, 1, kB,    kLazy};
    const ProxyParams kProxy64FullyLazy    = {64, kRT, kRGBA, kE, 1, kB,    kFullyLazy};
    const ProxyParams kProxy32Instantiated = {32, kRT, kRGBA, kE, 1, kB,    kInstantiated};
    const ProxyParams kProxy64Instantiated = {64, kRT, kRGBA, kE, 1, kB,    kInstantiated};

    auto tests = std::to_array<TestCase>({
            TestCase{"empty DAG", kUnder, 0, {}, {}, {}},
            TestCase{"unbudgeted", kUnder, 0, {}, {}, {{kProxy64NotBudgeted, 0, 2}}},
            TestCase{"basic", kUnder, kRGBA64Bytes, {}, {}, {{kProxy64, 0, 2}}},
            TestCase{"basic, over", kOver, kRGBA64Bytes - 1, {}, {}, {{kProxy64, 0, 2}}},
            TestCase{"shared",
                     kUnder,
                     kRGBA64Bytes,
                     {},
                     {},
                     {
                             {kProxy64, 0, 2},
                             {kProxy64, 3, 5},
                     }},
            TestCase{"retrieved from cache",
                     kUnder,
                     kRGBA64Bytes,
                     /* purgeable */ {kProxy64Instantiated},
                     /* unpurgeable */ {},
                     {{kProxy64, 0, 2}}},
            TestCase{"purge 4",
                     kUnder,
                     kRGBA64Bytes,
                     /* purgeable */
                     {kProxy32Instantiated,
                      kProxy32Instantiated,
                      kProxy32Instantiated,
                      kProxy32Instantiated},
                     /* unpurgeable */ {},
                     {{kProxy64, 0, 2}}},
            TestCase{"dont purge what we've reserved",
                     kOver,
                     kRGBA64Bytes,
                     /* purgeable */ {kProxy64Instantiated},
                     /* unpurgeable */ {},
                     {{kProxy64, 0, 2}, {kProxy64, 1, 3}}},
            TestCase{"unpurgeable",
                     kOver,
                     kRGBA64Bytes,
                     /* purgeable */ {},
                     /* unpurgeable */ {kProxy64Instantiated},
                     {{kProxy64, 0, 2}}},
            TestCase{"lazy",
                     kUnder,
                     kRGBA64Bytes,
                     /* purgeable */ {},
                     /* unpurgeable */ {},
                     {{kProxy64Lazy, 0, 2}}},
            TestCase{"lazy, over",
                     kOver,
                     kRGBA64Bytes - 1,
                     /* purgeable */ {},
                     /* unpurgeable */ {},
                     {{kProxy64Lazy, 0, 2}}},
            TestCase{"fully-lazy",
                     kUnder,
                     kRGBA64Bytes,
                     /* purgeable */ {},
                     /* unpurgeable */ {},
                     {{kProxy64FullyLazy, 0, 2}}},
            TestCase{"fully-lazy, over",
                     kOver,
                     kRGBA64Bytes - 1,
                     /* purgeable */ {},
                     /* unpurgeable */ {},
                     {{kProxy64FullyLazy, 0, 2}}},
    });
    SkString match("");
    for (size_t i = 0; i < std::size(tests); i++) {
        TestCase& test = tests[i];
        if (match.isEmpty() || match == SkString(test.fName)) {
            // Create proxies
            for (Interval& interval : test.fIntervals) {
                interval.fProxy = make_proxy(dContext, interval.fParams);
            }
            reporter->push(SkString(test.fName));
            memory_budget_test(reporter, dContext, test);
            reporter->pop();
        }
    }
}
